Log in

View Full Version : Patching a game function call


rookie182
December 30th, 2008, 13:01
Hi,

I've been looking around for a while, but I guess I may not be searching with the right terms, because what I want to do will probably seem simple.

I would like to process dynamic text in an application using my own code (probably inject a dll). So basically, I would like to write a bot that reads the game chat and does things.

I've ran the process with spy++ and I didn't catch any useful messages when I typed or received things in the chat box.

So I'm thinking a good direction to go would be to dissassemble the game, find the function that prints to the chat box, and patch it to call my processing code. Just not sure how to do that, with what tool, or even if it's a viable direction.

ty

Aimless
December 30th, 2008, 16:36
You might want to download the DIRECTX SDK while you do that... Doubtful if the ingame chat is built using NORMAL WINDOWS Functions...

ANd don't forget OpenGL SDK also...

Have Phun

WaxfordSqueers
December 31st, 2008, 22:54
Quote:
[Originally Posted by rookie182;78443]I've ran the process with spy++ and I didn't catch any useful messages when I typed or received things in the chat box.
If it is DX, as Aimless implied, you can get at the functions using softice and the specific nms file for the mouse or keyboard. DX sends its own messages and spyXX wont detect them. You could probably do the same with Olly unless you get into ring 0 code, but I don't know much about Olly.

arc_
January 1st, 2009, 07:51
WaxfordSqueers, I highly doubt a game would have its chat code running in kernel mode, so Olly should be just fine for this .

rookie182: you probably won't find much by simply looking at a disassembly, you will have to debug the game. Seeing as the game is rendering the chat on each frame, it must keep the chat contents in memory somewhere. You could search the game's memory for a chat message that is currently on screen and place a memory breakpoint on it. Then once the breakpoint hits, look around at the code and try to figure out how it got to that memory location: the chat content might be simply a fixed-size, fixed-location preallocated block in the data section, or it could be allocated dynamically on the heap and referenced through a pointer. And maybe the chat lines are stored sequentially in an array, or maybe in the form of a linked list etc... You will have to find this out. Type a few extra chat messages and see how the memory changes.

What you will do next depends on what you found. If the chat text is stored sequentially you could place a memory-breakpoint-on-write on the location where you are expecting the next message to appear. In case of a linked list things get a bit trickier - you will have to find the location of the "next" pointer of the last item in the list and place a mem breakpoint there, so that you will break when a new item is appended. The end result should be finding the code that puts a new message in the chat. A good indication that you've found the function would be seeing the new message as one of its arguments.

If you don't manage to find the outputChatBox function, you can always resort to periodically polling the chat memory and looking for changes, but this is of course less efficient.

Concerning tools I would personally recommend OllyDbg for debugging - it is imo by far the best ring 3 debugger available. You can search the game's memory by opening the Memory window (Alt-M) and pressing Ctrl-B.

For patching you will probably end up writing a little program that, using the functions VirtualAllocEx/WriteProcessMemory/CreateRemoteThread, injects your DLL. There probably exists example code for this. The .dll can then go on patching the game's code in-memory (don't forget to remove the write protection on the code area with VirtualProtect first).

Let us know what results you find .

WaxfordSqueers
January 2nd, 2009, 12:09
Quote:
[Originally Posted by arc_;78458]WaxfordSqueers, I highly doubt a game would have its chat code running in kernel mode, so Olly should be just fine for this .
You're missing my point. DirectX does not play by normal rules. It is essentially an operating system within an operating system. Under a DX environment, the mouse cursor you see on the screen is not the Windoze mouse cursor (thanks Silver), it is generated from within DX code. You can't deal with that problem normally in a Ring 3 environment.

The original poster already indicated he couldn't detect normal windoze messages using Spy++. That's typical of a DX environment because they don't use normal Windoze messages. One way to intercept the DX messages is to intecept mouse messages, but since the mouse is under control of the DX machine, you can't get at them by normal means.

I got at them by using mouse function calls that were only available using softice nms files. That meant breaking on a mouse driver call and breaking in ring 0. Then it was a matter of tracing through ring 0 code back to ring 3 code. I found a way of doing that better by tracing part way from ring 3 code into system code, finding a system function to break on, then BPing on the system function from the other end (the mouse end). You can't do that in Olly.

roxaz
January 4th, 2009, 09:37
or you can find chat packet handler and hook it. most of online games have server emulators developed for them. an emu is best reference on packets.

rookie182
January 5th, 2009, 13:22
Hey everyone, just giving an update.

I've been snooping around the game for a bit, and I found a function that gets called every time there is a message. When the game enters, the edi register has the message (or a pointer to it)?

What I've decided to do is at the very end, it calls some subroutine. So i'll use WriteProcessMemory to change it to call one of my dll functions. In there, I'll call the original subroutine, and then go nuts on the edi register.

(Wait, so can I just ReadProcessMemory on the value in the edi?)

So right now I guess I'm going to read up on all the asm stuff (I know the general concepts) and make sure I won't mess up the stack.

A few issues.
Taking the stuff from the packets sound pretty clean, but I would imagine I would have to do it pretty much the same way.
I've thought about just polling a particular memory location (if it even exists) but decided I'd rather just get called whenever the game writes a message - polling is wasteful, eh?

roxaz
January 5th, 2009, 13:48
yes, hooking packet handler would be just the same. i also should point out that edi holds a pointer to message as it is too small to contain all data. also i cant rly imagine how you would ReadProcessMemory from the location that is in edi as i suspect that memory address to be dynamic. Best way would be just to hook that function and redirect execution to your dll as you mentioned above.

Externalist
January 6th, 2009, 01:53
This might be helpful.

http://www.geocities.com/someone_special_asdf/UnitAlert.html

It's for starcraft but it generally applies to many games. Hope this helps.

roxaz
January 6th, 2009, 02:58
Quote:
[Originally Posted by Externalist;78554]This might be helpful.

http://www.geocities.com/someone_special_asdf/UnitAlert.html

It's for starcraft but it generally applies to many games. Hope this helps.


nice tut! i can offer to take a look at http://opensvn.csie.org/L2Extender This project is not for game client, but for game server whose sources are not available, only compiled binaries. Very same logic is applied to add new features and functionality. This is x64 project however, but still basics are the same so it wont be hard to convert code to x86.

rookie182
January 6th, 2009, 13:09
gaah ok, after looking over that tutorial, I see that I have the right idea. To be honest though, I really want to do the logic (there's a lot) in c, using asm only to patch the jmp/call. I have two main problems:

I know the address of the memory to patch, ida says it holds "call some_subroutine". When I double click it, I am taken to the first address of the subroutine. But that is NOT the same address that I see in the hex view of the original call. Am I not interpreting the number correctly? Is is a reference in some table (so i would need to either write the table as well, or just use jmp)? Also, is there a good listing of hex values of the opcodes? (It seemed call = 0xEA, but that's just my guess).

Problem two, I need to mix __asm blocks and c++. It would be awesome if they could share variables. I'll write the game's memory to jump to the address of my dll function. And in my function i will assign the edi register value to a char *. Does that sound plausible? And if I jumped there, I shouldn't use "return;", right?

roxaz
January 6th, 2009, 13:34
call opcode is 0xE8. ok, lets see... call sub_912AA0 = E8 DB 9C 42 00. so in hex we see call opcode and 0x429CDB, but we call 0x912AA0. this call will return at 0x4E8DC5. So here is the magic: 0x4E8DC5 (return address) + 0x429CDB (magic hex number after call opcode) = 0x912AA0 (our called func, yay!). I dunno exact term how this is called, but it does not take much brain to see that in hex calls are like relative or something. You get the idea i guess. I think there are other types of calls, but i dont remember correctly..

arc_
January 7th, 2009, 07:42
Nice to see you've made progress.

Like roxaz said, call instructions have a relative offset as operand. (if you ever write exploit code or any other asm code which needs to be position independent, you will see that this is a good thing ). If you have a call instruction at address pCall and you want it to call the code at address pTarget, the operand you need to write is pTarget - (pCall + 5).

Also, for hooking, it would be cleaner to replace the call instruction in the game by a call to your DLL code, instead of a jump. If you were to use a jump, you would need to make your DLL method __declspec(naked) which makes several things more difficult to do (e.g. local variables). Of course, be sure to specify the correct calling convention (__cdecl or __stdcall, look them up) - you want to match the calling convention of the game subroutine.

Then, at the end of your DLL routine, it would probably be easiest to call the game subroutine yourself and then return back to the game. You can do the calling with a small __asm block (mov eax, ADDR; call eax) or with a function pointer. Again don't forget about the calling convention.

Finally, using C(++) variables in __asm blocks is perfectly possible.

Code:
char* pMessage = NULL;
__asm {
mov pMessage, edi
}
printf("%s\n", pMessage);

rookie182
January 9th, 2009, 14:05
Hey everyone, things are progressing pretty well and I plan on posting the source when I'm all done, but in the mean time, I just want to post this snippet that's been a pain to find, but is rather useful for anyone else who might stumble onto this post. It demonstrates how to extract an address from the exe into a workable/viewable format.

Presumably you looked in IDA/Olly and saw something like call sub_912AA0, which is E8 DB 9C 42 00 (thanks roxaz). Now E8 is the call instruction, so what we want is the number after it.

First, use ReadProcessMemory to read 4 bytes from whatever memory location you saw the call, +1. (You don't need the E8). Then, cast the byte array like so:

Code:

DWORD * relativeAddress = *(DWORD**)bytearray;


Next, you need to reverse the bits (google 'endian' to find out why).
Code:

*relativeAddress = htonl(*relativeAddress);


Finally, if you want to see 0x00429CDB, print it using %p pointer notation:
Code:

printf("address is %p",*relativeAddress);


~Cheers