RCE Endeavors 😅

May 27, 2011

Messing with Protocols: Preliminary (1/3)

Filed under: Game Hacking,Reverse Engineering — admin @ 3:01 PM

This next series of posts will focus on looking at a game’s protocol. Specifically, the packet structure and some basic steps into the world of packet reversing. I will focus on explaining how a specific packet (a chat packet) is built in-game and how understanding the packet structure can let someone do some fun and unexpected things. It should be noted that this won’t be an article in server emulation as that is much too complex and time consuming to both perform and write about. The steps and methodologies discussed though can aid in beginning to fully reverse a protocol and begin a project in server emulation. This whole series will be broken down into three parts:

  • A preliminary post (this one) discussing how to perform a high level inspection of a protocol.
  • Reverse engineering the target application to see where and how a specific packet is built.
  • Example programs that could be written to send your own packets or modify parts of incoming/outgoing packets.

To start off, the target will be Age of Empires II: The Conquerors Expansion. This was chosen because the chat packets of the protocol are unencrypted so there won’t be any large sidetrack about hunting down encryption keys or reversing algorithms. There are other factors like the game being dead (developing studio disbanded), and it being one of the few multiplayer games that I own. That said, it’s time for some analysis. One of the better tools for this job is WPE Pro. It’s extremely easy to use and provides a simple interface that displays everything that is needed. To get started, I created a LAN game with myself and used WPE to log packets on one instance. Below is an example of some chat packets that were sent. These can be analyzed for patterns and guesses at the different parts of it can be taken and later verified or discarded. The hex dump of the packets is shown below, with the sent chat in blue and the changes between the packets highlighted in red:
D8 26 D9 16 00 00 00 00 43 17 00 00 06 00 00 00 E7 07 00 00 01 DC 59 59 4E 4E 4E 4E 4E 4E 32 00 01 00 00 00 01 41 00 00 24 DC 18
D8 26 D9 16 00 00 00 00 43 18 23 02 06 00 00 00 E8 07 00 00 01 DC 59 59 4E 4E 4E 4E 4E 4E 32 00 02 00 00 00 01 41 41 00 24 DC 18 00
D8 26 D9 16 00 00 00 00 43 19 18 00 06 00 00 00 E9 07 00 00 01 DC 59 59 4E 4E 4E 4E 4E 4E 32 00 03 00 00 00 01 41 41 41 00 DC 18 00 80
D8 26 D9 16 00 00 00 00 43 1A 18 00 06 00 00 00 EA 07 00 00 01 DC 59 59 4E 4E 4E 4E 4E 4E 32 00 04 00 00 00 01 41 41 41 41 00 18 00 80 DC
D8 26 D9 16 00 00 00 00 43 1B 23 02 06 00 00 00 EB 07 00 00 01 DC 59 59 4E 4E 4E 4E 4E 4E 32 00 05 00 00 00 01 41 41 41 41 41 00 00 80 DC 54
These packets show sending “A”, “AA”, “AAA”, “AAAA”, and “AAAAA” to the chat, which can be seen (0x41 characters). One thing to immediately note is that the name of the player sending the chat is not contained in the packet. That means that there is some field in the packet which denotes who is sending the packet. There also appear to be a few flags that serve as counters. The first packet contains 0x17 and 0xE7, the next one increments these bytes to 0x18 and 0xE8, the one afterwards to 0x19 and 0xE9, and so on. There is also a lone field in the packet which matches the size of the chat being sent. Lastly, there are some unknown values which seem to change with each packet sent. To get a better understanding of things, it is better to log packets over multiple instances/connections. The game was restarted and the same five packets were sent. Reproduced below are the five packets with their differences and chat highlighted. Additionally, the logging was done from sending chat as the second player in the game session.
DD BF 35 17 00 00 00 00 43 07 00 00 06 00 00 00 A7 0F 00 00 02 DC 59 59 4E 4E 4E 4E 4E 4E 4B 00 01 00 00 00 01 41 00 00 24 DC 18
DD BF 35 17 00 00 00 00 43 08 3D 02 06 00 00 00 A8 0F 00 00 02 DC 59 59 4E 4E 4E 4E 4E 4E 4B 00 02 00 00 00 01 41 41 00 24 DC 18 00
DD BF 35 17 00 00 00 00 43 09 18 00 06 00 00 00 A9 0F 00 00 02 DC 59 59 4E 4E 4E 4E 4E 4E 4B 00 03 00 00 00 01 41 41 41 00 DC 18 00 80
DD BF 35 17 00 00 00 00 43 0A 18 00 06 00 00 00 AA 0F 00 00 02 DC 59 59 4E 4E 4E 4E 4E 4E 4B 00 04 00 00 00 01 41 41 41 41 00 18 00 80 DC
DD BF 35 17 00 00 00 00 43 0B 3D 02 06 00 00 00 AB 0F 00 00 02 DC 59 59 4E 4E 4E 4E 4E 4E 4B 00 05 00 00 00 01 41 41 41 41 41 00 00 80 DC 54
Changes appeared to have happened within the expected offsets in the packets. Comparing differences between two packets from two different sessions:
D8 26 D9 16 00 00 00 00 43 1B 23 02 06 00 00 00 EB 07 00 00 01 DC 59 59 4E 4E 4E 4E 4E 4E 32 00 05 00 00 00 01 41 41 41 41 41 00 00 80 DC 54
DD BF 35 17 00 00 00 00 43 0B 3D 02 06 00 00 00 AB 0F 00 00 02 DC 59 59 4E 4E 4E 4E 4E 4E 4B 00 05 00 00 00 01 41 41 41 41 41 00 00 80 DC 54
The 0x1B and 0x0B flags are highlighted differently because they’re supposed to be the same. There were some intermediate messages sent between testing in one of the sessions and it threw off the counter. Everything else should be normal. One of the “unexpected” changes was that 0x01 changed to 0x02 and 0x32 changed to 0x4B. Since the only change aside from a new session was that the sending player was in the second player slot, it might be reasonable to guess that the byte that changed from 0x01 to 0x02 holds the number of the player who is sending the chat. The change in the other byte is unknown. The other unexpected change was that the first four bytes of the packet also changed. For the sake of not having to explain, I’ll simply mention that the first four, possibly eight, bytes appear to be a session key since they precede all packets sent throughout the game (not just chat ones). The actual value of the key is calculated external to the game, in the DirectPlay networking library. Finding out how the key is negotiated is still something that I am working on and won’t be covered in this series of posts — perhaps at a future date as my progress develops. The downside to not knowing how to calculate this is that in order to send custom packets to the client the connection must already exist. Obtaining the key is not really a problem however as sendto/recvfrom can be hooked and the key stored. The next thing to note is about the last four bytes of the packet. These are also external to game and appended by DirectPlay. From my testing, these four bytes appear to be a checksum on the size of the packet. For example, sending “a”, “b”, “q”, “$”, or any one character chat text will append 00 24 DC 18 to the packet. All two character texts have the same bytes appended at the end, and so on. The last thing is about the eight bytes after the player index. In the samples these bytes 0x59 and 0x4E. For a high level analysis, it is important to test as many things as possible. The in-game chat has three options: all (default), team, and enemy. Testing sending messages using these three options reveals that these eight bytes are the “audience” flags of who of the at most eight players in a game can see the chat message. Given that a majority of the packet has been understood and guessed at, this completes the high level preliminary analysis. A sample packet is shown below and guessed at or known fields are highlighted.
DD BF 35 17 00 00 00 00 43 0B 3D 02 06 00 00 00 AB 0F 00 00 02 DC 59 59 4E 4E 4E 4E 4E 4E 4B 00 05 00 00 00 01 41 41 41 41 41 00 00 80 DC 54

Red indicates a session key.
Blue indicates some sort of counter bytes.
Pink indicates the player sending the chat.
Green indicates who is to receive the message.
Yellow indicates the length of the chat string.
Grey indicates the chat string and the null terminator.
Teal indicates the trailing checksum.
Orange indicates unknown bytes that were constant across multiple sessions.
Black indicates unknown bytes that were variable across multiple sessions.

One last point to make is that at a high level, how some of these bytes are interpreted could be off. For example, the size of the packet shown as 0x05 could actually be given two bytes, 0x00 and 0x05 in the packet, making that orange unknown byte part of the size. The 0x06, 0x00, 0x00, 0x00 bytes could actually be a DWORD instead of four unique, unrelated properties, and so on. The high level analysis is good for getting started but the actual application will require reverse engineering to fully know what is going on. This will be the topic of the next post.

A downloadble PDF of this post can be found here.

May 26, 2011

Quick Post: Auto-updating with Signature Scanning

Filed under: Game Hacking,General x86,General x86-64 — admin @ 2:38 AM

One common problem with developing hacks or external modifications for games/applications is when the target application gets modified through patches, new versions, or so on. This might render offsets, structures, functions, or anything important that is used in the hack as useless if it is hardcoded. For example, assume that the hack puts a hook on a function at 0x1234ABCD. One day, a new version of the application is released and the new compiled version no longer has this function at 0x1234ABCD, but it’s at some different address, 0x12345678. Now the hack no longer works, and in the worst case, even crashes the application when used. This becomes annoying because some applications are frequently updated, which in turn requires frequent updates on the part of the hack developer. Even if the updates aren’t too frequent, it can be unnecessarily inconvenient to hunt down where the structures, functions, and so on ended up. One solution to this is called signature scanning. This technique is nothing new or special and has been used by both hack developers and anti-virus programs for many years (anti-viruses probably much longer than in hacks). It relies on finding parts of a program through scanning for certain byte patterns. For example, anti-virus programs rely partially on signature scanning when they scan files since each virus or variant can be identified with a sequence of bytes unique to it. Byte strings from scanned programs are taken and hashed. This hash is compared with known virus hashes in a database and if there is a match then there is a good chance that the application is a virus or has been infected. This of course ignores additional heuristics and scanning methods incorporated into anti-virus programs, but is still at a very basic level a key component of how they all work. This same methodology can be applied to developing game hacks or external modifications to applications in general since functions, structures, and so on also have unique byte patterns identifying them.

Shown above is part of a function that could serve as a signature. No other function in the application performs this unique set of instructions so assuming that this function does not change (the actual code within it is modified or things like new optimization settings or compilers being used) then it can always be identified with \x55\x8B\xEC\x51\x6A\x10\...\xD9\x59\x04 regardless of any updates of patches to the application. However, this technique is not without its downsides: scanning an entire file or image is costly in terms of speed. Thus, it is a pretty bad idea to develop a hack that scans an image for a signature each time it is loaded since that can slow things down a lot. What I personally do is keep an external config file that holds signatures and the offset (RVA) into the image at which they’re located. Then when a hack is loaded it can read in the config file and check that the signature exists where it’s supposed to. If it doesn’t then the hack will perform a scan on the whole image and write back into the config file where the new signature exists. This is only one way of doing it though so to each their own. Since the implementation is just searching for a substring, I feel that there’s really no need to put one here. Important things to note though for developing signature scanners:

  • Signature scanners should have some wildcard usage built in. Whether EAX, EBX and so on is used to hold a temporary value is irrelevant. For example, MOV EAX, 123 as a byte string is B823010000 and MOV EBX, 123 is BB23010000. The important part of those instructions is the 123 immediate value, so the B8 or BB byte is irrelevant. The signature can then be \x??\x23\x01\x00\x00. How \x?? is treated is implementation dependent.
  • Usually the most important parts of a signature are any references to other code, structures, local variables, etc. Getting a signature containing these will increase the chance of it being found. However, references to other code is a bit dangerous since relative distances can change between new versions of a target application.
  • A signature, by definition, should be unique. Using PUSH EBP ; MOV EBP, ESP is a bad idea.

A downloadable PDF of this post can be found here.

February 4, 2011

Game Hacking: Age of Empires II (Part 2/?)

Filed under: Game Hacking,Reverse Engineering — admin @ 11:26 AM

This part will focus on how to draw player stats on the game screen. One obvious advantage to this over the previous article is that the player stats are directly in the game, thus there is no need to alt-tab out or play in windowed mode to see what the other players have. Additionally, a toggle feature will be added that allows the player to cycle through various modes to see different types of statistics on the others. The first step is to find a place where either some text, or more specifically, the players scores are drawn. The advantage to finding where the player scores are drawn is that player statistics will be drawn in a natural location and that they can correspond in color to the player. The first step is to think about how the player text is drawn on screen. There is always the player name, a colon followed by a space, and two numbers with a forward slash separating them. Searching for a format similar to this in the games referenced strings leads to what could be the right path.
A string with our desired format is found, and some other interesting strings which hint to drawing. Setting a breakpoint on where the “%s: %d/%d” string is referenced shows that it does in fact relate to the players  scores. The function that uses this is called on a timer continually to update the players scores on the screen. The image below shows what values are loaded in registers on the first and second call respectively.

The general gist of how the function works is that the player whose score is to be retrieved is loaded into the EAX register. The function flow continues until the score is retrieved. The score for the next player is retrieved while the string containing the name and score of the previous player is drawn on the screen. The process then continues for the next player and restarts while the game is active. Modifying the name on a call shows that this does indeed affect how the text is drawn on the screen

This can then be taken advantage of to draw what we want. Tracing exactly where the name gets drawn leads to the call from .text:0052107D.

.text:0052104C                 mov     eax, [esp+350h+var_330]
.text:00521050                 mov     ecx, [esp+350h+var_340]
.text:00521054                 mov     edx, [esi+8]
.text:00521057                 push    eax             ; int
.text:00521058                 mov     eax, [esi+4]
.text:0052105B                 push    ecx             ; int
.text:0052105C                 mov     ecx, [esi]
.text:0052105E                 push    ebx             ; int
.text:0052105F                 push    edi             ; int
.text:00521060                 push    edx             ; int
.text:00521061                 mov     edx, [esp+364h+var_31C]
.text:00521065                 push    eax             ; int
.text:00521066                 mov     eax, [esp+368h+var_318]
.text:0052106A                 push    ecx             ; int
.text:0052106B                 push    edx             ; int
.text:0052106C                 mov     edx, [esp+370h+var_338]
.text:00521070                 lea     ecx, [esp+370h+Str1]
.text:00521077                 push    eax             ; int
.text:00521078                 push    ecx             ; Str1
.text:00521079                 mov     ecx, [edx]
.text:0052107B                 push    5               ; int
.text:0052107D                 call    sub_54A510

Immediately after this routine completes, the text is drawn on the screen. The function has 11 arguments, the second one being the player name, and third being the RGB value of the player. For the purpose of developing this portion of the hack, the other arguments are irrelevant and probably relate to the position on the screen where the text is to be drawn if I had to take a guess. The idea then is to hook .text:0054A510, grab the stats for the players name, modify the resulting string (which will be in “%s: %d/%d” format) to our custom string, and then pass this back to the original function to be drawn on the screen. The resulting code would look like

__declspec(naked) int score_update_hook(int always_five, char *player, int rgb_value, int unk1, int unk2,
    int unk3, int unk4, int unk5, int unk6, int unk7, int unk8) {
    __asm pushad
    char *name; //Placeholder for address of name buffer
    __asm {
        mov ebx, dword ptr[esp+0x28]
        mov name, ebx
    }
    stats = items_find_by_name(&base_pointers, name);
    if(stats != NULL) {
        if(toggle_option == CURRENT_RES)
            _snprintf(name, SCORE_MAX_LENGTH, "W:%1.0f  F:%1.0f  G:%1.0f  S:%1.0f\0",
            stats->player_stat->wood, stats->player_stat->food, stats->player_stat->gold,
            stats->player_stat->stone);
        else if(toggle_option == ALL_RES)
            _snprintf(name, SCORE_MAX_LENGTH, "W:%1.0f  F:%1.0f  G:%1.0f  S:%1.0f\0",
            stats->player_stat->total_wood_gathered, stats->player_stat->total_food_gathered,
            stats->player_stat->total_gold_gathered, stats->player_stat->total_stone_gathered);
        else if(toggle_option == POP_AGE)
            _snprintf(name, SCORE_MAX_LENGTH, "Pop: %1.0f/%1.0f  Vil:%1.0f  Mil:%1.0f  Age:%1.0f\0",
            stats->player_stat->pop_current, (stats->player_stat->pop_current + stats->player_stat->pop_left),
            stats->player_stat->num_villagers, stats->player_stat->num_military, stats->player_stat->current_age);
    }
    __asm {
        popad
        jmp score_update
    }
}

The actual structure of the function is abused a bit here. Since .text:0054A510 has no local variables, we can create one on the stack at [EBP-0x4], since there won’t be anything to overwrite there. This dummy argument will act as our third argument at [ESP+0x28] (this function does not set up any sort of BP-based frame). Then anything we do to this dummy argument will be reflected as a change to the third parameter. Thus, the hook grabs the player name of who is to be updated, gets their stats, and checks what mode the user wants to be displayed. The modes are currently controlled through a regular enum in toggle_options.h

typedef enum TOGGLE_OPTIONS {
    CURRENT_RES = 1,
    ALL_RES,
    POP_AGE
} toggle_options;

Future plans can be to extend this system to allow the user to script their own format to be displayed with what they want. This technique still holds on multiplayer, as shown by the screenshots below.

Multiplayer note: The hooking technique posted below is detectable by Voobly. See the end of part 1 for suggestions on bypasses.

Usage: Enter a game and hit the hotkey to enable (default is F5). Use F6 to disable the hack, F7 to toggle options, and F8 to clear the stat list in case all names were not retrieved. A player is added to the list when they perform any action in game that modifies their resources. Duplicates are not stored in the list.

I’d prefer for the hack to develop through a series of articles instead of opening up a SVN server on here since that will give me motivation to continue its development.

The source for the in-game hack DLL can be found here.

A downloadable PDF of this post can be found here.

February 2, 2011

Game Hacking: Age of Empires II (Part 1/?)

Filed under: Game Hacking,Reverse Engineering — admin @ 7:06 AM

This article will be one of an ongoing series — as I have time to write them. I’ve spent the better part of this past weekend and this week focusing on game hacking. The target was an old classic, Age of Empires II: The Conquerors.

It is an old 2D RTS game where you build up an empire, build armies, make/break alliances, and so on. For a much more in-depth explanation than I care to provide see the Wikipedia article on its predecessor. One of the interesting things that I discovered while messing around with this game is that the statistics (all resource/villager/military/… counts, current age, population, etc) counts are stored in a structure that is indexed into for the appropriate player. This wouldn’t be too interesting as a single player game, but Age of Empires is a multiplayer game, with a semi-big community of around 1200 active players. The same base classes/structures are shared between AI bots and active players, meaning there are no modifications to be made between single and multiplayer, in terms of hack development.

Finding the stat structure started off normally, by using Cheat Engine to search for the type of variable the player’s resources were stored in, and what was writing to it. Doing the usual things like building/destroying buildings, collecting resources, and making units yielded a wide variety of results. In the end, there were multiple candidates for where values are being written from, but they were narrowed down to a very good function at .text:00555470.

This is good candidate because the floating point stack is being utilized, and it was the only one like it that popped up when dropping resources off at the town center. Looking actively into this function yields clues about how it works. The important parts are reproduced below.

.text:0055544F                 mov     eax, [ecx+0A4h]
.text:00555455                 movsx   edx, si
.text:00555458                 cmp     edx, eax
.text:0055545A                 jge     loc_5554FE
.text:00555460                 mov     eax, [ecx+0A8h]
.text:00555466                 fld     [esp+4+arg_4]
.text:0055546A                 fadd    dword ptr [eax+edx*4]
.text:0055546D                 lea     eax, [eax+edx*4]
.text:00555470                 fstp    dword ptr [eax]
.text:00555472                 mov     eax, [ecx+4]
.text:00555475                 test    eax, eax
.text:00555477                 jz      loc_5554FE

This function is very interesting because it is a __thiscall and does not set up any sort of bp-based stack frame. ECX here is used without being initialized (hint for __thiscall) and the arguments are also referenced directly through the stack pointer. This is where the static code analysis ends though, and a debugger needs to be attached to follow exactly how everything behaves. OllyDbg happens to be one of the best for live code analysis.

Breakpoints set, everything can be observed as this function gets called. When I created a unit, the following values were in the registers when the first breakpoint hit.

Here ECX is the “this” pointer. It points to the base of the calling class. When the EIP is 0x0055546A, the application had the following state

1.0f was loaded into ST0. However, when I dequeued a unit, -1.0f was loaded into ST0. The second parameter is therefore some sort of flag for whether a unit is being queued or dequeued. This value is added to [EAX+EDX*4], and the result stored in the address that EAX points to. Looking at what is inside [EAX] then yields what is more or less a holy grail.

While the values may look nonsensical at first, this is actually a layout of a structure that holds a ton of statistics about a player.

The first four members of this structure correlate to the players food, wood, stone, and gold. Then comes the population left before hitting the cap, an unknown value, the current age, and so on (see player_stats.h for my listings). These values can continue to be found by setting memory breakpoints on an individual one or a region, followed by performing an action in the game and observing what breakpoints are triggered. Since the base of this structure is a member of the calling class, it can always be found at (base address of class + 0xA8), as evidenced in the disassembly of the function. Just looking at the base address of the class yields some interesting information.

In addition to having pointers to some ridiculously large structures (possibly covered in the future), the player’s name is also listed at (base address of class + 0xA8). Sidenote: The address pointing to it is different since I started another game instance between taking the two screenshots. This provides identifying information for each class that calls .text:00555470. Then the theory is that if I hook .text:00555470, I can store all of the pointers to every player in the game. This is true because this function is called by every player on the games start, and also throughout the game. Using Microsoft’s Detours library makes this extremely easy. The hook function looks as follows

__declspec(naked) void resources_changed_hook(short int res_type, float usage_type, int unused) {
	__asm {
		pushad
		mov eax, temp_pointer
		mov dword ptr[eax], ecx         //temp_pointer->base_pointer points to calling class
    }
    temp_pointer->player_name = (char*)(*(temp_pointer->base_pointer + (0x98 / sizeof(DWORD_PTR))));
    temp_pointer->player_stat = (player_stats*)(*(temp_pointer->base_pointer + (0xA8 / sizeof(DWORD_PTR))));
    if(insert(&base_pointers, temp_pointer) == true)
        temp_pointer = (item_set*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(item_set));
    __asm {
		popad
		jmp resources_changed
	}
}

The stack is preserved, the address of the calling class is stored, the offsets calculated and set, and the calling function inserted into a set (no repetitions allowed).

The actual structure is a shell of the calling class and stores only the class pointer, the statistics structure, and the players name

typedef struct ITEM_SET {
	int* base_pointer;
        char* player_name;
	player_stats* player_stat;
	ITEM_SET *next;
} item_set, *pitem_set;

This can/will all be expanded and redone as more of the calling class is reverse engineered. The stored items can then be simply traversed like a list and the data for each player printed out.

void print(item_set** head) {
	if(*head == NULL)
		return;
	item_set* node_ptr = *head;
	while(node_ptr != NULL) {
        printf("Player: %s -- Wood: %1.0f - Food %1.0f - Gold: %1.0f - Stone: %1.0f\n", node_ptr->player_name,
            node_ptr->player_stat->wood, node_ptr->player_stat->food, node_ptr->player_stat->gold, node_ptr->player_stat->stone);
		node_ptr = node_ptr->next;
	}
	printf("\n");
}

Here is an example of it in action:


Using this, a player is able to modify their own stats in addition to reading the stats of others. Doing something like

while(node_ptr != NULL) {
    if(strcmp("qwerty", node_ptr->player_name) == 0) {
        node_ptr->player_stat->food = 10000.0f;
        break;
    }
    node_ptr = node_ptr->next;
}

Would work fine on single player. However, on multiplayer this would cause an out of sync error. Since each player keeps a copy of the other players information in their game, any unwarranted change would cause the game to go out of sync. However, simply reading memory will still be fine. The player_stats structure consists of 198 members with roughly half of them documented by me. Additional help is welcome.

A screenshot from a CBA game at Voobly — technique still holds.

Warning: The version posted here will result in a ban from Voobly. Their anti-cheat checks functions for hooks and will ban any user found to be modifying the functions in memory. This is still extremely easy to get around using hardware breakpoints and a different DLL injection technique with no keyboard hook — but that might be another part of this series. The risk takers who are uninitiated with those topics may want to try to attach the hooks prior to an in-game lobby launch and detach immediately upon entering the game to beat the anti-cheat scan. This is definitely not recommended however. Also, the fact that it is in a separate window makes this more of a proof of concept than an actual functional hack until further work/posts are done on the game.

Possible future articles as time permits:

Hooking internal drawing functions or DirectDraw functions to draw text on the screen

Reversing the protocol and packet structure

Bypassing Voobly’s anti-cheat system (large hints given)

The source code to the hooking DLL can be found here.

A downloadable PDF of this post can be found here.

« Newer Posts

Powered by WordPress