----------------------------------------------------------------------------------------
! W A R N I N G !
LARGE TUTORIAL!
... but the content is fairly straightforward! I hope you learn something new!
----------------------------------------------------------------------------------------
I N T R O D U C T I O N:
Tutorial by: thong aka Paul of team [Limited edition] @
www.gamehackers.net // USEast.Battle.net OP Obsolete
Type of tutorial: Advanced FYI (For Your Information)
Main focus of this tutorial: To create a packet sender for Diablo II LoD V1.10 *AND* hopefully give you (The reader) a better understanding of what Packet DASM is and how to write your very own packet sender for D2 or other gaming titles!
Skills required: An understanding of SoftICE, x86 ASM and a brain!
Tools used: SoftICE, WDASM, DHack, Notepad, WPE Pro and a brain!
First, this is the second tutorial I've written covering the topic of "Packet DASM" using Diablo II LoD as our game of choice to reverse engineer. This tutorial will be very similiar to my previous one, but with a few different twists because the programmers of the new V1.10 patch have updated quite a few things in the packeting send()'ing process! Nothing that we can't overcome though! ;-)
... Lets go ahead and start this project!
Some information about Diablo 2 LoD:
- This game does not use encrypted data packets for send(), in-game! Keep this in mind if you plan to apply this tutorial to games that are using encrypted packets in-game. I'm frequently asked how to decrypt packet data that is encrypted on some of these odd ball games, such as Prince of Qin Online and it's frustrating for me to give an answer to this question because of all the unknowns. Each game is different on how things are done, but because a packet is generated using an encryption technique within the game code it CAN be found and CAN be reversed. It's just a matter of extra backtracing and stepping. The principles used in this tutorial can help aid you in your quest, but only to a certain degree; most of the time locating packet building processes before they are encrypted require alot of time tracing AND guessing, especially if there isn't any documentation on the game code. IE: Open Source or some other game hacker released a packet reference to decrypted data from his/her own efforts. So fair warning, if you aren't the type of person who can spend hours and hours, possibly even months, in game code trying to understand how it works you should bail out now! Making packet senders aren't for you!
P A R T I:
There are several ways to locate WSOCK32 send() functions within a game. Here are some that are more commonly used:
Step 1.) The first thing I did was fire up Diablo 2 LoD and joined/created a game.
Step 2.) Next, I ran SoftICE's Symbol Loader. (Remember to load SoftICE first if you're on NT!)
Step 3.) Loaded WSOCK32.dll in SoftICE's Symbol Loader.
Step 4.) Returned to my Diablo II LoD game.
Step 5.) Ctrl+D into SoftICE! -> addr Game
Step 6.) From SoftICE's command line I type'd: bpx send
Step 7.) Returned to Diablo 2 LoD
Step 8.) Toggled my gear with the "w" key!
Step 9.) SoftICE pops up. Press F11!
Step 9.) SoftICE pops up here:
D2Net.dll
* Reference To: WSOCK32.send, Ord:0013h
|
:6FC017BE FF158C71C06F Call dword ptr [6FC0718C]
:6FC017C4 83F8FF cmp eax, FFFFFFFF
:6FC017C7 7535 jne 6FC017FE
[ECX] stores the packet! In SoftICE type: d ecx
AL and BL stores the packet length!
Step 10.) After typing "d ecx" in SoftICE, you'll notice [ECX] stores the following:
60 00 XX XX XX XX ...
And AL and BL have the following value:
00000001
We can now assume that the following is the syntax for toggling gear with the "w" key:
60 [No trailing 00 is required because the length is only 1 byte! Besides, I believe the D2 client adds trailing 00's.]
Step 11.) Now, for testing purposes you can "bpx 6FC017BE" from SoftICE and preform various actions. For every action that you do in-game that sends ANY data what-so-ever to others SoftICE will pop up at 6FC017BE and you can view that packet in [ECX] and length of that packet in AL or BL.
6FC017BE is a very useful address to us! :-P
Side note:
If SoftICE pops up without you doing anything after setting a breakpoint at 6FC017BE, chances are your client is sending an auto-update out, which is on a timer!
The packet type for the client update is 0x6C and its routine can be found here in the D2Client.dll:
* Reference To: KERNEL32.GetTickCount, Ord:0186h
:6FAAD3B4 8B3514DFB66F mov esi, dword ptr [6FB6DF14]
:6FAAD3BA FFD6 call esi
:6FAAD3BC 8B15F079BA6F mov edx, dword ptr [6FBA79F0]
:6FAAD3C2 8BC8 mov ecx, eax
:6FAAD3C4 2BCA sub ecx, edx
:6FAAD3C6 81F988130000 cmp ecx, 00001388
:6FAAD3CC 7243 jb 6FAAD411
:6FAAD3CE A3F079BA6F mov dword ptr [6FBA79F0], eax
:6FAAD3D3 C64424046C mov [esp+04], 6C <----- Client update packet type / Keepalive
:6FAAD3D8 FFD6 call esi
:6FAAD3DA 89442405 mov dword ptr [esp+05], eax
:6FAAD3DE E8FDC6FFFF call 6FAA9AE0
:6FAAD3E3 8D542404 lea edx, dword ptr [esp+04]
:6FAAD3E7 6A09 push 00000009 <----- Packet length = 9 bytes
:6FAAD3E9 52 push edx
:6FAAD3EA D1E8 shr eax, 1
:6FAAD3EC 6A00 push 00000000
:6FAAD3EE 89442415 mov dword ptr [esp+15], eax
:6FAAD3F2 E811EA0B00 Call 6FB6BE08 <----- Call a send() for auto-update!
The other technique used to locate send() fuctions within the game, other than the stated above method, is to load the game files into WDASM. From WDASM you will click on the "Imports" button on the toolbar. Once the Import Functions table loads locate AND double click on the following:
WSOCK32.send
Using the above example load D2Net.dll into WDASM. Goto Import Functions table. Locate and double click on WSOCK32.send.
WDASM will take you to the following code:
* Reference To: WSOCK32.send, Ord:0013h
:6FC017BE FF158C71C06F Call dword ptr [6FC0718C]
Some people will say that the WDASM technique is alot easier than the SoftICE method BUT what if the file you were trying to hack was packed? What then? What if the Import Functions table did not show send()?? What then?? ;-) Ahhh!
P A R T I I:
Q: What now?
A: Well, now that we have our main address, which is 6FC017BE, our next step is to locate just where in the game code are these packets being built. Afterward, we can inject our own code to "hi-jack" the packet building process to build our own custom packets!
OK, from SoftICE set a breakpoint on execution at 6FC017BE. This is accomplished with the following command:
bpx 6FC017BE
Step 1.) Think about what type of action you want to do. The first action that comes to mind for me is running!
Step 2.) Run!
Step 3.) SoftICE will break at 6FC017BE.
Step 4.) In [ECX] "d ecx" you will notice something like this:
03 XX YY XX YY 00
xx = Any value
YY = Any value
AL or BL both store the following:
00000005
Because AL/BL show 00000005, we can assume that the packet length for sending "run packets" are 5 bytes in length!
Our syntax for a running packet is:
03 [WORD] [WORD] // [WORD] = XY Coordinates
Step 5.) While still in SoftICE at bpx 6FC017BE, press the following button: F12 (Backtrace)
You will land at the following piece of code:
D2Client.dll
:6FAAD910 E8F3E40B00 Call 6FB6BE08
:6FAAD915 85C0 test eax, eax <----- SoftICE breaks here after pressing F12!
:6FAAD917 7419 je 6FAAD932
:6FAAD919 8B0DF41ABC6F mov ecx, dword ptr [6FBC1AF4]
:6FAAD91F A1FC1ABC6F mov eax, dword ptr [6FBC1AFC]
:6FAAD924 03CB add ecx, ebx
:6FAAD926 40 inc eax
:6FAAD927 890DF41ABC6F mov dword ptr [6FBC1AF4], ecx
:6FAAD92D A3FC1ABC6F mov dword ptr [6FBC1AFC], eax
Step 6.) Clear all breakpoints using the "bc*" command from SoftICE!
Step 7.) Set a breakpoint on execution at 6FAAD910 (bpx 6FAAD910).
Step 8.) Return to Diablo II and run again!
Step 9.) SoftICE breaks at 6FAAD910!
Step 10.) Press F12 one more time!
You will be placed here:
D2Client.dll -- Routine used to build ALL packets with a length of 5 bytes!
:6FAAD9B0 83EC08 sub esp, 00000008 <----- Address to send all of our calls to for 5 byte packets!
:6FAAD9B3 668B44240C mov ax, word ptr [esp+0C]
:6FAAD9B8 884C2400 mov byte ptr [esp], cl <----- Packet type
:6FAAD9BC 6689542401 mov word ptr [esp+01], dx <----- First [WORD] in packet! Note: edx
:6FAAD9C1 BA05000000 mov edx, 00000005 <----- Packet length
:6FAAD9C6 8D4C2400 lea ecx, dword ptr [esp]
:6FAAD9CA 6689442403 mov word ptr [esp+03], ax <----- Last [WORD] in packet! Note: eax
:6FAAD9CF E87CFEFFFF call 6FAAD850 <----- Call send()
:6FAAD9D4 83C408 add esp, 00000008 <----- SoftICE breaks here after press F12!
:6FAAD9D7 C20400 ret 0004
Q: What if a packet is not 5 bytes in length? What if it is more OR less??
A: From my previous tutorial you might remember that once we found a routine that was used to build a particular packet with a fixed length the Call send() could help track down other routines that built certain packets with a fixed length. This is also the case in V1.10! Every \"call 6FAAD850\" is used to send packet data! So, what does this mean? Well, it makes our job alot easier asfar as locating remaining packet building processes in the D2Client.dll if we wanted to hi-jack them to send custom packets of our own!
Step 1.) Open D2Client.dll in WDASM
Step 2.) Goto Seach from the menu bar > Find Text > Type: call 6FAAD850 > Find Next
Here are some of the other packet building routines that I found using the above search method:
D2Client.dll -- Routine used to build ALL packets with a length of 3 bytes!
:6FAAD990 51 push ecx
:6FAAD991 884C2400 mov byte ptr [esp], cl <------ Packet type
:6FAAD995 6689542401 mov word ptr [esp+01], dx
:6FAAD99A BA03000000 mov edx, 00000003 <----- Packet length
:6FAAD99F 8D4C2400 lea ecx, dword ptr [esp]
:6FAAD9A3 E8A8FEFFFF call 6FAAD850
:6FAAD9A8 59 pop ecx
:6FAAD9A9 C3 ret
D2Client.dll -- Routine used to build ALL packets with a length of 7 bytes!
:6FAAD9E0 83EC08 sub esp, 00000008 <----- Address to send all of our calls to for 7 byte packets!
:6FAAD9E3 668B44240C mov ax, word ptr [esp+0C]
:6FAAD9E8 884C2400 mov byte ptr [esp], cl <------ Packet type
:6FAAD9EC 668B4C2410 mov cx, word ptr [esp+10]
:6FAAD9F1 6689542401 mov word ptr [esp+01], dx
:6FAAD9F6 66894C2405 mov word ptr [esp+05], cx
:6FAAD9FB BA07000000 mov edx, 00000007 <----- Packet length
:6FAADA00 8D4C2400 lea ecx, dword ptr [esp]
:6FAADA04 6689442403 mov word ptr [esp+03], ax
:6FAADA09 E842FEFFFF call 6FAAD850 <----- Call send()
:6FAADA0E 83C408 add esp, 00000008
:6FAADA11 C20800 ret 0008
D2Client.dll -- Routine used to build ALL packets with a length of 9 bytes!
:6FAADA40 83EC0C sub esp, 0000000C <----- Address to send all of our calls to for 9 byte packets!
:6FAADA43 8B442410 mov eax, dword ptr [esp+10]
:6FAADA47 884C2400 mov byte ptr [esp], cl <----- Packet type
:6FAADA4B 89542401 mov dword ptr [esp+01], edx<----- First [DWORD]
:6FAADA4F BA09000000 mov edx, 00000009 <----- Packet length
:6FAADA54 8D4C2400 lea ecx, dword ptr [esp]
:6FAADA58 89442405 mov dword ptr [esp+05], eax <----- Second [DWORD]
:6FAADA5C E8EFFDFFFF call 6FAAD850 <----- Call send()
:6FAADA61 83C40C add esp, 0000000C
:6FAADA64 C20400 ret 0004
D2Client.dll -- Routine used to build ALL packets with a length of 13 bytes!
:6FAADA70 83EC10 sub esp, 00000010 <----- Address to send all of our calls to for 13 byte packets!
:6FAADA73 8B442414 mov eax, dword ptr [esp+14]
:6FAADA77 884C2400 mov byte ptr [esp], cl
:6FAADA7B 8B4C2418 mov ecx, dword ptr [esp+18]
:6FAADA7F 89542401 mov dword ptr [esp+01], edx
:6FAADA83 894C2409 mov dword ptr [esp+09], ecx
:6FAADA87 BA0D000000 mov edx, 0000000D <----- Packet length
:6FAADA8C 8D4C2400 lea ecx, dword ptr [esp]
:6FAADA90 89442405 mov dword ptr [esp+05], eax
:6FAADA94 E8B7FDFFFF call 6FAAD850 <----- Call send()
:6FAADA99 83C410 add esp, 00000010
:6FAADA9C C20800 ret 0008
These aren\'t the only routines like this in the D2Client.dll BUT these are the most commonly used ones!
P A R T I I I:
In part 3 of my tutorial we will discuss how to take all of our findings and put them into code that we can inject into our game!
Here we go again! `:-P
This part of the tutorial is where your Assembly (x86 ASM) knowledge will come into play! AND this is why I call this an Advanced tutorial... it requires you to use your brain and think of reasonable code to pass information from our \"soon-to-be\" injected code to one of the routines we found in the D2Client.dll! See part 2! You might need to bpx the routine and step through the code (F8), but I broke down the building process fairly well I think!
Before we start using our brain lets locate a hotkey function within the game code that we can rip! :-)
D2Client.dll -- Hotkey function
:6FAD5A19 B9382DBB6F mov ecx, 6FBB2D38 // ESI stores keypressID
*I\'m not going to get into details about locating this because most people don\'t use this method for hooking keyboard functions.
Okie dokie, brain time!
My source code after stepping in SoftICE and figuring out how things are passed in the packet building routine/s! See part 2! (D2Client.dll -- Routine used to build ALL packets with a length of 9 bytes!)
#Start
pushad// Save
cmp esi, 7B// Was F12 pressed?
jne @ End// If not ignore and cleanup!
#Custom build
mov dword ptr eax, [2nd DWORD]// Second DWORD in our packet. See Part II
push eax// Save eax
mov byte ptr cl, packetID// Custom packet type goes here. Why? See Part II
mov dword ptr edx, [1st DWORD]// First DWORD in our packet. See Part II
call 6FAADA40// Call send() with fixed length of 9 bytes!
#End// Return to original process
popad// Restore
mov dword ptr ecx, 6FBB2D38// Original data at 6FAD5A19
ret// Return to game!
#Our custom packet data goes here
[1st DWORD]
[2nd DWORD]
Cave address for injected code:
Found in D2Lang.dll
:6FC1A900
*I\'m not going to explain how to locate cave codes...
OPCode/DHack format examples:
LocateBy WindowName \"Diablo II\"
START \"V1.10\" \"Paul\'s 3 Byte Diablo II LoD Packet Sender.Hak (Press F12)\"
#Activate after you\'re in a game!
6FAD5A19 B9382DBB6F E8E24E1400
6FC1A900 000000 83FE7B
6FC1A903 0000 750F
6FC1A905 00 60
6FC1A906 00 B1
6FC1A908 000000000000 8B151AA9C16F
6FC1A90E 0000000000 E87C30E9FF
6FC1A913 00 61
6FC1A914 0000000000 B9382DBB6F
6FC1A919 00 C3
#
#Custom packet type:
6FC1A907 ** 3F
#Custom packet data:
6FC1A91A ** 1900
END
START \"V1.10\" \"Paul\'s 9 Byte Diablo II LoD Packet Sender.Hak (Press F12)\"
#Activate after you\'re in a game!
6FAD5A19 B9382DBB6F E8E24E1400
6FC1A900 00 60
6FC1A901 000000 83FE7B
6FC1A904 0000 7513
6FC1A906 0000000000 A124A9C16F
6FC1A90B 00 50
6FC1A90C 00 B1
6FC1A90E 000000000000 8B1520A9C16F
6FC1A914 0000000000 E82731E9FF
6FC1A919 00 61
6FC1A91A 0000000000 B9382DBB6F
6FC1A91F 00 C3
#
#Custom packet type:
6FC1A90D ** 0D
#Custom packet data:
6FC1A920 ** 00000000FFFFFFFF
END
P A R T I V:
In this part of the tutorial we will be testing our code. For this, I use an application called DHack to patch the above code/s in to memory! Also, WPE Pro to see if my custom packet is actually being sent!
Step 1.) Load Diablo II / Join or Create a game!
Step 2.) Load DHack and open my .Hak file included with this tutorial.
Step 3.) Load WPE Pro > Select Game.exe > Start capturing data
Step 4.) Press F12 multiple times!
Step 5.) Check your WPE Pro packet log!
C O N C L U S I O N:
There are many things you can do with Packet DASM, such as testing Servers for exploits by sending custom crafted game packets of your own! Because more and more gaming companies are switching to client - server based Software learning about packet disassembly is strongly recommended, especially if you\'re an aspiring game hacker, such as myself!
Feel free to critique my work and if you feel something could be better explained; by all means share your thoughts! I\'m always willing to improve my game hacking skills! OR If I fudged up someplace don\'t hesitate to laugh at me! I feed off of you! :-p
Stay tuned! More tutorials from [Le] to come!
More info for D2 game hackers:
Update for packet 0x0D:
V1.10: 0D 00000000 [DWORD ID = 4 Random bytes? Looks that way!] Who can figure it out? ;-)
Example 1: 0D 00 00 00 00 14 8F A6 3A
Example 2: 0D 00 00 00 00 02 94 A9 AA
V1.09d: It\'s no longer 0D 00000000 01-08? 000000
Example 1: 0D 00 00 00 00 01 00 00 00
Example 2: 0D 00 00 00 00 02 00 00 00
Q: What\'s so important about 0x0D? Who cares??
A: Sending custom crafted 0x0D packets can auto hit players! You can create a duel hack!!
... I wonder how long it will be before we start seeing players abusing this packet type! :-D
S H O U T Z:
TechWarrior -- I wouldn\'t know most of what I know without you!
Soulburner -- Great source material from Diablo I. I learned ALOT from his hacks!
All of team [Limited edition] and of course CES. ;-)
/me is out!