Archive for the ‘World of Warcaft’ Category

WoW Alpha Client and PDB

February 23rd, 2009

The following is the alpha WoW client (just the main exe) and accompanying PDB file that was leaked before WoW was even released. This is what is primarily responsible for the swift development of bots, hacks, and emulators for WoW. The reason I’m posting it is that I’ve had a fair few requests for it so I figured I may as well post it here because it’s a pain to get your hands on (not impossible, but ‘difficult’). Yes it is very old, but it is still useful to this date. Lots of the function prototypes, structures, etc are still fairly accurate and what actually has changed can usually be filled in fairly quickly.

Anyway, here it is:

WoW Alpha

If the link goes down it’s probably because Blizzard filed a complaint and had it taken down. If that’s the case I’ll try and find somewhere more appropriate to host it. Also, you can always contact me directly and I’ll send you a link.

Hopefully this will help any prospective WoW hackers. (Its surprising how few people know/remember this exists and how useful it is.)

Games, Reverse Engineering, World of Warcaft , , , , ,

Another Quick Poll

February 11th, 2009

Another WoW related post coming late today (or late tomorrow at the latest I hope). So let me know, what do you want to see this time?

Games, World of Warcaft ,

WoW’s Console

February 6th, 2009

Hey, as requested I’m gonna post the info needed to use WoW’s console in a hack. Because I’m a little short on time I’m just going to post the bare minimum, but at the end of the post I’ll point out some of the other functions that may be of interest in case you want to go hunting for them.

Note: I’m assuming you already know how to enable and use WoW’s console. (Hint: ‘WoW.exe -console’, then use the ‘`’ key to bring it down. Just like in most other games.)

First off, registering console commands. The easiest way to find the function needed to do this is look for a known command in the binary. I chose ‘worldport’ because I’ve used it before, and found this:

.text:004073B3                 push    0               ; int
.text:004073B5                 push    0               ; int
.text:004073B7                 push    offset sub_406D70 ; int
.text:004073BC                 push    offset aWorldport ; “worldport”
.text:004073C1                 call    sub_6A0BD0

Now, from that we can easily see that sub_6A0BD0 is the function we are interested in because it takes both the command name and the associated function pointer (which you can verify by looking inside). Based on that the callback registration function prototype will be the following:

void __cdecl RegisterConsoleCommand(unsigned int Unk1 = 0, unsigned int Unk2 = 0, void* pCallback, const char* Command);

What you will notice though is that if you try to use your new command WoW will exit. Why is that? Well, if you go to the trouble of debugging it (Hint: start at ConsoleExec, called by the Lua subroutine by the same name) you will come across the following function:

.text:007CB3A0 sub_7CB3A0      proc near               ; CODE XREF: sub_69F470+B9p
.text:007CB3A0                                         ; sub_6A11A0+1Ap …
.text:007CB3A0 var_40          = byte ptr -40h
.text:007CB3A0 arg_0           = dword ptr  8
.text:007CB3A0                 push    ebp
.text:007CB3A1                 mov     ebp, esp
.text:007CB3A3                 mov     eax, dword_12EA640
.text:007CB3A8                 mov     ecx, dword_12EA644
.text:007CB3AE                 sub     esp, 40h
.text:007CB3B1                 test    eax, eax
.text:007CB3B3                 jz      short loc_7CB3B9
.text:007CB3B5                 test    ecx, ecx
.text:007CB3B7                 jnz     short loc_7CB3C9
.text:007CB3B9 loc_7CB3B9:                             ; CODE XREF: sub_7CB3A0+13j
.text:007CB3B9                 call    sub_7CB310      ; <”Unable to find .text section”, “.text”>
.text:007CB3BE                 mov     eax, dword_12EA640
.text:007CB3C3                 mov     ecx, dword_12EA644
.text:007CB3C9 loc_7CB3C9:                             ; CODE XREF: sub_7CB3A0+17j
.text:007CB3C9                 mov     edx, [ebp+arg_0]
.text:007CB3CC                 cmp     edx, eax
.text:007CB3CE                 jb      short loc_7CB3D4
.text:007CB3D0                 cmp     edx, ecx
.text:007CB3D2                 jb      short loc_7CB3F1
.text:007CB3D4 loc_7CB3D4:                             ; CODE XREF: sub_7CB3A0+2Ej
.text:007CB3D4                 push    edx
.text:007CB3D5                 push    offset aInvalidFunctio ; “Invalid function pointer: %p”
.text:007CB3DA                 lea     eax, [ebp+var_40]
.text:007CB3DD                 push    40h
.text:007CB3DF                 push    eax             ; char
.text:007CB3E0                 call    sub_6A6920
.text:007CB3E5                 lea     ecx, [ebp+var_40]
.text:007CB3E8                 push    ecx             ; char *
.text:007CB3E9                 call    sub_6A9E60
.text:007CB3EE ; —————————————————————————
.text:007CB3EE                 add     esp, 14h
.text:007CB3F1 loc_7CB3F1:                             ; CODE XREF: sub_7CB3A0+32j
.text:007CB3F1                 mov     esp, ebp
.text:007CB3F3                 pop     ebp
.text:007CB3F4                 retn
.text:007CB3F4 sub_7CB3A0      endp

Again, if you go to the trouble of reversing this function (which I’m not going to explain in detail because its beside the point of this post) you will see that it is looking at WoWs PE header, getting the start and end of WoW’s ‘.text’ segment (which is where all code is kept) and ensuring no function pointers are being registered outside that range. If a function pointer outside the valid range is found then WoW will quit.

What is the easiest way to get around this? Hook the function to just do a “return” at the start. If you want to just write a single byte to do the same (even easier), simply write ‘0xC3′ to the top of the function. Please keep in mind this is ignoring the presence of Warden. If you want to ensure you don’t get detected by Warden you will need to breakpoint whatever you’re hooking to ensure it’s not being scanned, or use a generic Warden bypass.

Now with that out of the way we move to printing output. Funnily enough we can backtrack to the exact same starting position as before:

.text:004073B3                 push    0               ; int
.text:004073B5                 push    0               ; int
.text:004073B7                 push    offset sub_406D70 ; int
.text:004073BC                 push    offset aWorldport ; “worldport”
.text:004073C1                 call    sub_6A0BD0

I checked worldport and happen to know that if you pass it invalid params it will print usage information to the console. Knowing that we can dive into worldport’s callback and we find this:

.text:00406DED                 push    4
.text:00406DEF                 push    offset aUsageWorldport ; “Usage: worldport <continentID> [x y z] “…
.text:00406DF4                 call    sub_69D850      ; <”.\ConsoleClient.cpp”, “.?AUCONSOLELINE@@”>
.text:00406DF9                 add     esp, 8

Again, very obvious what’s going on there.

void __cdecl ConsolePrint(unsigned int Unk1 = 0, const char* Output);

Using that you can easily write output to the console.

Well, that pretty much sums up the pure basics. If people are interested in some of the other console related stuff (changing the print colour, registering cvars, modifying/retrieving cvar values, what the parameters we’re ignoring are for, etc.) let me know. If you’d rather see something different like packet-based stuff, or even something non WoW related like my new usermode rootkit project or something else related to Windows reversing and internals feel free to suggest that too.

Extra Credit:

See if you can work out what the extra parameters I’ve marked as “Unk” (unknown) in each function are for. I’ll let you know if you’re right or wrong.

Games, Reverse Engineering, Windows, World of Warcaft , ,

Quick Poll

February 3rd, 2009

Hey, before I write my next post (which will be WoW related) I was wondering what topic people would be more interested in. Console hooking was brought up, as was packet-based stuff (logging packets, spoofing packets, etc). So rather than just pick blindly I was wondering, what do you want to see?

Note: Obviously not limited to the two above they were just two random examples that had been brought up.

Games, Reverse Engineering, World of Warcaft , ,

World of Warcraft Morph Hack

February 1st, 2009

Today you’re going to learn about how a WoW morph hack works!

Posting this for two reasons:

  1. People cry when things don’t get updated and I’m sick of getting PMs.
  2. On the other hand, they cry anyway so rather than spoonfeed people I’ll give them the means to write their own hack.

Quick side note: Sorry if this post is hard to follow or understand, I’m kinda rushed at the moment. Please leave a comment and let me know if anything doesn’t make sense.

The concept is fairly simple. Every (unit) model has a unique display id. This id (from memory) is stored in WoWs DBC files (which are basically glorified csv files to hold localization info and other data that shouldn’t be hardcoded into the client). When a unit is created, its display id is stored in UNIT_FIELD_DISPLAYID and UNIT_FIELD_NATIVEDISPLAYID. Whenever a unit is ‘morphed’, for example by a spell like Polymorph or Hex, the UNIT_FIELD_DISPLAYID is overwritten with the new display id and the model is redrawn.

Your goal is to replicate the spell morph effect by forcing a new value for the display id and then calling the function to redraw the model. Obviously to do this you will need to find that function. At first this may seem like a difficult task but its actually quite simple.

Note: I’m assuming you already know how to enumerate objects and also get access to an object’s pStorage/descriptor-array/etc (names vary) in order for you to give UNIT_FIELD_DISPLAYID a new value. If you don’t, please consult the WoW Memory Editing forums on MMOwned, there is more than enough information there on the topic.

First you need to work out your starting point. Because morphing is (normally) initiated by the server there would most likely be a packet to perform the morph. If you dig into Mangos/ArcEmu/etc (or if you have a debug client you could use that instead)  and view the opcode list you will see that you are in luck and that the packet SMSG_FORCE_DISPLAY_UPDATE (opcode 0×403) is probably what you want. You can find the packet handler for this by opening WoW in IDA and searching for ‘push 403h’ (which is the opcode being passed to the function which registers the packet handlers).

You will likely get two results for that search.

One like this:

push 403h

call sub_12345678

And another like this:

push <reg>

push offset sub_87654321

push 403h

call sub_23456789

The second is the one you are interested in because you can clearly see it is the one that registers the callback (it takes a function pointer and the opcode), the other one can be discarded (but if you look into it closely you will see it is resetting the opcode in question).

If you follow the function pointer you will be presented with something like the following (the code below is from 3.0.3 - I used an older client so you can’t ‘cheat’):

.text:0067EB00 sub_67EB00      proc near               ; DATA XREF: sub_67F8F0+6E9o


.text:0067EB00 var_8           = dword ptr -8

.text:0067EB00 var_4           = dword ptr -4

.text:0067EB00 arg_C           = dword ptr  14h


.text:0067EB00                 push    ebp

.text:0067EB01                 mov     ebp, esp

.text:0067EB03                 mov     ecx, [ebp+arg_C]

.text:0067EB06                 sub     esp, 8

.text:0067EB09                 lea     eax, [ebp+var_8]

.text:0067EB0C                 push    eax

.text:0067EB0D                 push    ecx

.text:0067EB0E                 call    sub_69FE30

.text:0067EB13                 mov     edx, [ebp+var_4]

.text:0067EB16                 mov     eax, [ebp+var_8]

.text:0067EB19                 push    65Fh

.text:0067EB1E                 push    offset a_Unit_c_cpp ; “.\\Unit_C.cpp”

.text:0067EB23                 push    8

.text:0067EB25                 push    edx

.text:0067EB26                 push    eax

.text:0067EB27                 call    sub_46D3C0

.text:0067EB2C                 add     esp, 1Ch

.text:0067EB2F                 test    eax, eax

.text:0067EB31                 jz      short loc_67EB3E

.text:0067EB33                 push    1

.text:0067EB35                 push    1

.text:0067EB37                 mov     ecx, eax

.text:0067EB39                 call    sub_67B2E0


.text:0067EB3E loc_67EB3E:                             ; CODE XREF: sub_67EB00+31j

.text:0067EB3E                 mov     eax, 1

.text:0067EB43                 mov     esp, ebp

.text:0067EB45                 pop     ebp

.text:0067EB46                 retn

.text:0067EB46 sub_67EB00      endp

If you read the function you can see it takes the packet data and does some processing with it (in sub_69FE30) which returns two unsigned ints via pointers to local variables. These variables are then passed to a second function. Because the morph is done on a single unit we can likely guess that that the function that performs the morphing is a member function of CGUnit_C (the class used to represent units in WoW). Based on this we can see that sub_67B2E0 is the function we want. sub_46D3C0 takes the two unsigned ints (along with some other things) and its return value is passed to sub_67B2E0 through ecx, this means that sub_67B2E0 is a class member function which confirms our suspicions about it being a member of CGUnit_C. We can now see that the two unsigned ints are actually the GUID of the unit that the game is going to morph and that the return value of sub_46D3C0 is the pointer to the unit which corresponds to that guid.

With this information we can now get the prototype and address for the function we need to call to redraw the object with its new display id. We know its done on units (just based on regular gameplay, but you can also tell from the string that is passed to the function which grabs the object pointer via guid), we also know the params we need to pass (we can just rip them right from the packet handler, we don’t really need to know or care what they’re actually for). From this we can derive:

void CGUnit_C::UpdateModel(unsigned int Unk1 = 1, unsigned int Unk2 = 1); // Address = 0×006800A0

It would be even more obvious what was going on if we looked inside the functions being called by the packet handler but its so simple that we don’t really need to.

Exercise for the reader: Find the function for the latest patch, and for bonus points, write a simple morph hack for the latest patch.

Pop quiz: You are the only person who can see the changed model. Why is this?

Games, Reverse Engineering, World of Warcaft , ,