All pastes #612723 Raw Edit

Unnamed

public text v1 · immutable
·published 2007-07-10 16:02 UTC
rendered paste body
D2 Smells is a Diablo II packet research tool. It is provided for educational purposes only. The author shall in no way be liable for anything you do with your computer, whether using this program or not. If you are unsure how to use this software, please do not contact your supervisor.

It uses the WinPcap library, and thus you will need to install that first.
You will also need the .NET Framework v2.0, a computer and a brain (each sold separately.)

Getting Started

1-Unpack
2-Start Diablo II if you haven't already.
3-Open D2 Smells.exe
4-If you have multiple Diablo instances open, select the one you want to bind to.
5-If the Diablo instance you have selected is not already connected to Battle.net, select the correct adapter to bind to if you have multiple connected adapters.
6-Click "Start Sniffing".


Shell

You can type C# code in bottom part of the Shell tab. The code is divided in three parts using another tab control: Main will be compiled as a function and is the code that will be run on a new thread with Execute is clicked. In Members, you can define additional members of the class that will be generated, such as methods and global fields. The third text box, "Saved Members" is for commonly used additional members that will be automatically saved and restored. The top text box is used as standard output. You can return a string which will be appended to it, or call print(string).

Shell arguments:

d2
The D2Toolkit.D2Instance associated with the current user command.
code
The D2ToolKit.UserCodeThread for this instance.


Shell commands:

print(string str)
Outputs a string to stdout.

sendGC(string bytes)
Sends a packet to the Game Server, exactly like the packet sender on Packets tab does.
sendGC(byte[] bytes)
Sends a packet to the Game Server.


Shell example(s):

Code:  ‹ Select › ‹ Expand ›

d2.Title = "Diablo II - Testing";

d2.Activate();

d2.Click(450, 500);
Thread.Sleep(100);

d2.SendKey(Keys.Enter);
Thread.Sleep(100);
d2.SendKey('h');
Thread.Sleep(100);
d2.SendKey('i');
Thread.Sleep(100);
d2.SendKey(Keys.Enter);
Thread.Sleep(100);

sendGC("14 00 00 49 20 61 6d 20 4e 4f 54 20 53 74 65 70 68 65 6e 20 43 6f 6c 62 65 72 74 21 00 00 00");
Thread.Sleep(100);

sendGC(UnequipItem.Build(EquipmentLocation.RightHand));


Here's an example demonstrating use of packet listeners. It will output all received and sent messages to the console in the same format as Diablo II.

In Main:

Code:  ‹ Select › ‹ Expand ›

d2.Sniffer.AddAsyncListener(BnetServerPacket.ChatEvent, new PacketEventHandler(onChatEvent));
d2.Sniffer.AddAsyncListener(GameServerPacket.GameMessage, new PacketEventHandler(onGameMessage));
d2.Sniffer.AddAsyncListener(GameServerPacket.PlayerInGame, new PacketEventHandler(onPlayerInGame));
d2.Sniffer.AddAsyncListener(GameServerPacket.PlayerAssign, new PacketEventHandler(onPlayerAssign));
d2.Sniffer.AddAsyncListener(GameServerPacket.PlayerAssign, new PacketEventHandler(onGameOver));

while(true) Thread.Sleep(1000);


In Members:

Code:  ‹ Select › ‹ Expand ›

ArrayList players = new ArrayList();

class Player
{
  public uint uid;
  public string name;
  public Player(uint uid, string name)
  {
    this.uid = uid;
    this.name = name;
  }
}

void addPlayer(uint uid, string name)
{
  lock(players)
  {
    foreach(Player p in players)
    {
      if (p.uid == uid)
      {
        return;
      }
    }
    players.Add(new Player(uid, name));
  }
}

string getPlayerName(uint uid)
{
  lock(players)
  {
    foreach(Player p in players)
    {
      if (p.uid == uid) return p.name;
    }
  }
  return uid.ToString();
}

void onGameOver(object sender, PacketEventArgs args)
{
  lock(players)
  {
    if (players.Count > 0)
      players.RemoveRange(0, players.Count);
  }
}

void onPlayerInGame(object sender, PacketEventArgs args)
{
  GameServer.PlayerInGame p = args.Packet as GameServer.PlayerInGame;
  addPlayer(p.UID, p.Name);
}

void onPlayerAssign(object sender, PacketEventArgs args)
{
  GameServer.PlayerAssign p = args.Packet as GameServer.PlayerAssign;
  addPlayer(p.UID, p.Name);
}

void onChatEvent(object sender, PacketEventArgs args)
{
  BnetServer.ChatEvent p = args.Packet as BnetServer.ChatEvent;
  if (p.Event == BnetServer.ChatEventType.ReceiveWhisper)
 {
  print(String.Format("From {0} (*{1}): {2}", p.Name, p.Account, p.Message));
 }
 else if (p.Event == BnetServer.ChatEventType.WhisperSent)
 {
  print(String.Format("Sent to {0} (*{1}): {2}", p.Name, p.Account, p.Message));
 }
  else if (p.Event == BnetServer.ChatEventType.Broadcast)
 {
  print(String.Format("<Battle.net>: {0}", p.Message));
 }
}

void onGameMessage(object sender, PacketEventArgs args)
{
  GameServer.GameMessage p = args.Packet as GameServer.GameMessage;
  if (p.MessageType == GameMessageType.GameMessage)
  {
    print(String.Format("{0}: {1}", p.PlayerName, p.Message));
  }
  else if (p.MessageType == GameMessageType.OverheadMessage)
  {
    if (p.UnitType == UnitType.Player)
      print(String.Format("{0} shouts: {1}", getPlayerName(p.UID), p.Message));
  }
  else if (p.MessageType == GameMessageType.GameWhisper)
  {
    print(String.Format("{0} whispers: {1}", p.PlayerName, p.Message));
  }
  else if (p.MessageType == GameMessageType.GameWhisperReceipt)
  {
    print(String.Format("You whispered to {0}: {1}", p.PlayerName, p.Message));
  }
}



Edit: new version, fixed some bugs, and um did stuff...

Edit 2: some more bug fixes and added SendKey, SendKeyDown and SendKeyUp methods to Window.

Edit 3: also I raised maximum out of sync frames to 20 (was 5 for testing, 20 sounds reasonable for 'production'... higher means less chance of missing packets in watched connection, but also possibly more time to find the first good packet when starting to sniff an active connection). Tell me if you're still seeing some MaxOutOfSyncFramesExceeded and SequenceLower in your logs.

Edit 4: please report any remaining bugs as I'm hoping to release D2 Smells as a packet research tool soon before moving on with a new module / script launcher / manager + shell GUI for toolkit... or something like that I believe.

Edit 5: New update, fixed the splitter distance restore bug, TabIndex orders and other minor UI changes.

Edit 6: New update, add two panes to shell to define class members.

Edit 7: New version, added script management, UI improvements and more bug fixes.

Edit 32e4324: Added packet documentation, more UI fixes, more packet classes and many packet parsing improvements / bugfixes.

-ET