HowToHackD2 - Edition #2

Status
Not open for further replies.

_Bull

Member!
Joined
Oct 29, 2005
Messages
15
Reaction score
0
Location
toronto
Website
warriorforum.xforum.se
File: HowToHackD2_Edition2.txt - Part I
Author: Jan Miller

Disclaimer

This article has been written for your viewing pleasure only. It is not meant to inspire anyone to hack Diablo II, as it is against the END USER LICENCE AGREEMENT that you agreed to when buying the game. If you are part of Blizzard Entertainment or Vivdendi Universal or Battle.Net and think I did a great job writing up this article, then please do contact me, as I wouldn't mind visiting California for a summer semester or two. Contact details appended at the bottom of this article. :)


Requirements

-C Language basic knowledge
-x88 intel ASM basics
-Windows API / Windows programming basic knowledge
-OllyDbg (http://www.ollydbg.de)
-Diablo II: Lord of Destruction with v1.11b Patch fully installed


Introduction

I'm assuming that the readers of this paper have already "consumed" the first edition of this series of papers. If you haven't yet, it's probably best to look up my webpage, find the paper and suck up its contents (google's site:<url> keyword is a great aid for site-specific queries!). The papers I'm writing are intended to increase in "difficulty", as I do hope that the readers of my previous paper have "developed" in the meanwhile. :) If you're just curious about gamehacking (specifically Diablo II) that's just fine, aswell. Okay, but let's get on topic again. This time, I will demonstrate how to find a suitable "patch location" in Diablo II's drawing code, so that we can draw our own stuff! After that's done, I will demonstrate how to create a nifty little window for us to draw. It will be the same type of window you see when talking to an NPC in the game. You can see a demo of how this "nifty little window" I'm talking about looks here: http://www.gamemunchers.net/web/pics/3_0eMH2.jpg (the background square frame that has a sligth fade)


Authors Recommendations

Alright, I believe a few people have misunderstood the actual idea behind my papers. The idea isn't to hold your hand and walk you step-by-step to become a successful "Diablo II hacking master" ;)). I will at times skip a few steps, and they will be left for you to figure out! Programming is all about trying things yourself, so please only view my papers as a general guide or maybe a "helper" to get the right mind-set on these kind of things. Another important aspects are "programming fluids" (as my new prof. likes to call good quality german beer). Do NOT attempt to follow this article without the proper content in your fridge! :)


"Behind the scenes" - What is an NPC and what is a unit?

An NPC is an "interactable unit" in Diablo II. It is used by players to repair their equipment, sell items, buy items, and alot more. When "interacting" with a NPC a small little "menu" pops up that will neatly present all the different options of the NPC to the player. Here is an example of an NPC menu:



As you can see, the menu is a faded rectangle with a thin frame bordering it. Each menu is just a simple text that will highlight when hovered with the mouse. In Diablo II, there is various types of units: Players, Monsters, Items, Missiles, and a few more. All of these units have an underlying data structure, that is quite similar for all of them (NPC's are categorized as "Monsters"). For each unit type Diablo II has a global table that will store a pointer to the data structure of a specific unit. The table has usually 128 members, and each pointer to a "unit data structure" is 4 bytes in size. That results in 128*4 = 512 bytes for each table. Futhermore, each unit has an assigned "unit ID" which is unique for each unit. This "unit ID" is used to index into the unit tables, but more to that later. It's important for you to know all of this, because we will use the knowledge we have about units to create our own menu.


Chapter I - Finding a suitable "patch location" to draw

The approach is actually quite simple: We will try to set a breakpoint in an area that Diablo II calls in its drawing-routine. So, what do we know about Diablo II's drawing routine? Obviously, Diablo II draws alot, so we will try to focus on something easy, such as the "current levelname" text that Diablo II draws in the right corner of your screen. You can see an example image of the "current levelname" here:



Important: Always make observations about the conditions that apply to the target code (in our case, the "DrawLevelName" function) area. In our case, a very important observation is that the "current levelname" text will ONLY be drawn if the AUTOMAP is enabled. Hence, we can assume that once we find the "DrawLevelName" function, it will be called from within the "DrawAutomap" function. This observation is important, because it'll help us understand better what code we are looking at later.

Alright, launch Diablo II in window mode (make a shortcut appending the -w parameter), make a singleplayer game and attach with OllyDbg. I won't go into details here, as I'm assuming you read the first edition, where these things are explained in more detail. If you don't know how to use OllyDbg properly, you better read up on that elsewhere. :) Now, after having attached successfully to Diablo II we should make sure that the AUTOMAP is enabled, because we are going to try to find the "DrawLevelName" function, remember? ;-) I'm going to continue in a step-by-step manner now, to make things abit easier to follow.

1) Open up the "module list" (ALT-E) and select "d2lang.dll". Now press the ctrl-n combination to open up the "module names" list (should be titled "Names in D2Lang"). You will see a list of exported and imported functions here.

2) In the "module names" list of d2lang.dll scroll down until you find this function: "?strlen@Unicode@@SIHPBU1@@Z" - which is the UNICODE version of strlen that Diablo II has implemented to deal with strings. Set an execution breakpoint by hitting the "F2" key on your keyboard.

3) Once the execution breakpoint is set (indicated by the line turning red) open Diablo II back up again. OllyDbg should be popping up again immidiately, because the exported "?strlen@Unicode@@SIHPBU1@@Z" function has been executed by Diablo II. You should see something like this:



As we see, the UNICODE string is passed in the ECX register to "?strlen@Unicode@@SIHPBU1@@Z", which is an indication that "?strlen@Unicode@@SIHPBU1@@Z" is a function with the "fastcall" convention.

4) Press F9 (run) command until the desired levelname appears in the ECX register. I'm using the german Diablo II version and my player is in the intial level of the game, so we are searching for the "Lager der Jägerinnen" string right now. You should be seeing something like this:



The interesting part right now is the stack, as we're not interested in finding the "DrawText" function, but more so interested in finding a good code location to overwrite, which will call our own code, so WE can draw whatever we like.

5) The answer to all our questions right now is the stack. The stack is essentially a "history" of the function calls that happened before the line of execution reached the code address that we breakpointed at. Note: A "call" instruction is essentially the same as "PUSH EIP, JMP CALL <DESTINATION ADDR>, MOV EIP, <DESTINATION ADDR>" (EIP always holding the address of the next instruction to be executed). The "ret" instruction is essentially the same as "POP EIP" ..

Your stack should be as follows, when you followed steps 1) to 4) until now properly:



Anyway, it turns out that the highlighted line (see image above) in the stack was the call to the "DrawAutomapStuff" function. You can simply right-click the line highlighted and select "Follow in Disassembler" option. The disassembly window should be putting you right here:



Aha! ;-) We now found the global variable that determines wether the automap is open (6FBB40E8h) and the call to the "DrawAutomapStuff" function. As we want to draw AFTER the automap does (to be sure that everything we draw is ONTOP of the automap) 6FB16AB6h is quite a good patch location. We will simply overwrite the 4 bytes "delta" value at 6FB16AB7h with the "delta" to our own function (assuming our code is in the address space of Diablo II). Then, everytime Diablo II is done drawing the automap, it will magically call OUR function and we can do everything we like. Note: When "overwriting" a call with your own call, you should always be sure to call the overwritten function inside your code, to make sure no Diablo II code is skipped, as that might have unpredictable consequences. I will provide sample code of how to patch a call in the next chapter.



Chapter II - Writing our patching code

This is goning to be the "first version" of our module that we will be writing in this edition. It will be expanded later in "chapter IV - Implementing the results of our analysis". Anyway, here comes the patching code with some hopefully helpful comments (you should probably copy this into your favorite IDE for better viewing pleasures):-

Code:
#include <windows.h>

static DWORD OurDraw(VOID) {
	//we can add any drawing code here
	//..
	return (DWORD)GetModuleHandle("d2client.dll");
}

static __declspec(naked) VOID OurDrawSTUB(VOID) {
	__asm {
 call Ourdraw
 test eax,eax
 je _exit
//we will call the original function here. as we want the original call to be module position independent,
//we will add the delta of the original function to its module base here:-
//d2client.dll base + 62670h = original call (6FB12670h)
 add eax,0x62670
 push eax
 ret
_exit: //something is wrong, we failed to get a base address for d2client
 push 0 //exitcode
 call ExitProcess
	}
}

#define x86INST_CALL	0xE8
#define x86INST_NOP 0x90
static BOOL InstallCallHook(LPVOID addr, LPVOID stub, DWORD len) {
	DWORD dummy;
	if(VirtualProtect((LPVOID)addr, len, PAGE_READWRITE, &dummy)) { //set the page access, so we can write
 unsigned char* patch=new unsigned char[len]; //allocate "len" bytes on the heap
 *patch=x86INST_CALL; //first byte is call opcode
 //the delta between our patch address and the function is (DWORD)patch-(DWORD)stub
 //we add 5 to it, because the "call" opcode has the following syntax: 
 // <1 byte identifier><4 bytes delta>
 //the toatl length ot the "call" opcode is 5 bytes. since the <4 bytes delta> are calculated
 //off of the EIP register when the call instruction is executed, the "real" delta isn't at our
 //patching address, but rather at the next instruction, which is at +5 bytes (hope that made sense)
 *(DWORD*)(patch+1)=(DWORD)adddr-(DWORD)stub+5;
 if(len>5) memset(patch+5,x86INST_NOP,len-5); //pad remaining bytes with "NOP" (no instruction) opcode
 memcpy(addr,patch,len); //write bytes
 delete patch; //free the previously allocated memory
 VirtualProtect((LPVOID)patch, len, dummy, &dummy); //restore the old page access
 return TRUE;
	}
	return FALSE;
}

BOOL WINAPI DllMain(HINSTANCE hDll,DWORD dwReason,LPVOID lpReserved)
{
	switch (dwReason) {
 case DLL_PROCESS_ATTACH:
 	DWORD dwClientBase=(DWORD)GetModuleHandle("d2client.dll");
 	if(!dwClientBase)
  break;
 	//let's install our "patch" at 0x6FB16AB1 (base+0x66AB1) -> see image above
 	if(!InstallCallHook(dwClientBase+0x66AB1,(DWORD)OurDrawSTUB,5))
  return FALSE; //unload, we were unable to set the page access
 	break;
 case DLL_PROCESS_DETACH:
 case DLL_THREAD_ATTACH:
 case DLL_THREAD_DETACH:
 default:
 	break;
	}
	return TRUE;
}
You can compile this code into your own module and force Diablo II to load it by creating a remote thread that will call "LoadLibrary" on your module for you. I won't go into detail of this technique here, because it's nothing new and this article is about hacking Diablo II anyway, right? ;-) You can find a great article on dll injection here: http://www.codeproject.com/dll/RemoteLib.asp

It do not suggest to simply inject a dll into Diablo II running on Battle.Net, as their new anti-hack system will easily identify the external dll and probably ban you. It breaches the EULA of Battle.Net, too. Everything mentioned in this article is purely for your own entertainment.

It seems like this edition is getting out of hand, so I've seperated it into two parts. The next part of edition #2 will include the following two chapters:

"Chapter III - Finding the NPC Menu code and analyzing it"
"Chapter IV - Implementing the results of our analysis"



Contact Details

E-Mail: webmaster@gamemunchers.net
Website: http://www.gamemunchers.net
IRC:

Hope you enjoyed the read nevertheless! I'm glad about any input on this article.

-Jan

Maybe add this to the sticky or whatever
 

bLueStarz

Member!
Joined
Jul 3, 2005
Messages
50
Reaction score
0
Good job. I think sum1 should think about a lil tutorial for VB6 d2 hacking... Never found one yet
 

_CM

Respected Member
Joined
May 19, 2003
Messages
3,874
Reaction score
3
Location
Luxembourg
bLueStarz said:
Good job. I think sum1 should think about a lil tutorial for VB6 d2 hacking... Never found one yet
well that might be because you can't really "hack" with vb.
 

wasup999999

BattleForums Member
Joined
Oct 10, 2003
Messages
450
Reaction score
0
Location
Hmm, Where Do You Think?
Website
Visit site
Yea, you can't really change anything internally with vb6; however you can send clicks, text and anything a human can do (except reason) with the window minimized. Anyway, best not to get into an argument due to the fact that people are really pushy on the subject.

PS: Are you gunna merge this with the how to hack ver1 sticky?
 

sunjester

Member!
Joined
Dec 16, 2007
Messages
28
Reaction score
0
Location
southern cali
Website
mrsunjester.info
well that might be because you can't really "hack" with vb.
thats not correct at all. VB just isnt as high up the ladder as c is. c is a "high level language" vb is a "rad", and there are plenty of hacks and utilities written in vb, like, the hero editor.

you still have access to windows' hooks, and you also have access to the windows API and microsofts winsock, possibilities are endless.

ill write a short one later if someone reminds me.
 
Status
Not open for further replies.

NewPosts

New threads

Top