First of all, i want to say that this is not to be used for cheating in online games, or give me an advantage over other players, it is striclty for learning purposes, and games are fun.

I have in a long time wanted to get a bit more in depth with the memory, reading assembly and reverse engineering. So i have fired up good old Quake for a fun exercise, to give myself ammo.

So i have used a memory searcher and found the dynamic address in memory that holds my ammo count. With the same tool i have found the address of the instruction.

42ABED  89 34 38    mov dword ptr [eax+edi], esi // Instruction

4E7E4A4  // 23.f Dynamic address of the ammo count
ESI = 41B80000
EAX = 4A4
EDI = 4E7E000

Surrounding assembly code:

0042ABDC  | mov dword ptr ds:[edi],eax              | edi:DbgUiRemoteBreakin
0042ABDE  | jmp glquake.42A6DF                      |
0042ABE3  | mov eax,dword ptr ds:[edi]              | edi:DbgUiRemoteBreakin
0042ABE5  | mov edi,dword ptr ds:[80B874]           |
0042ABEB  | mov esi,dword ptr ds:[esi]              | esi:DbgUiRemoteBreakin
0042ABED  | mov dword ptr ds:[eax+edi],esi          |
0042ABF0  | jmp glquake.42A6DF                      |
0042ABF5  | mov edi,dword ptr ds:[edi]              | edi:DbgUiRemoteBreakin
0042ABF7  | mov eax,dword ptr ds:[80B874]           |
0042ABFC  | add edi,eax                             |
0042ABFE  | mov eax,dword ptr ds:[esi]              | esi:DbgUiRemoteBreakin

So after a lot of reading forums i think i have understood some of it;

ESI is what that holds my ammo, it is the hexadecimal representation of 23, which in fact is correct according to my notes.

EAX + EDI is my dynamic address for the ammo count.

4A4 + 4E7E000 = 4E7E4A4

So i took a wild guess here, if i write a byte array to the address of the instruction, would it set my ammo? sadly not and here is what i did:


float ammoToGive = 100.0F;
Process gameProcess = Process.GetProcesses().Where(x => x.ProcessName.ToLower().Contains("glquake")).FirstOrDefault();
IntPtr processHandle = WinApi.OpenProcess(0x1F0FFF, false, gameProcess.Id);
int bytesWritten = 0;
byte[] buffer = BitConverter.GetBytes(ammoToGive);
WinApi.WriteProcessMemory((int)processHandle, 0x42ABED, buffer, (UInt32)buffer.Length, ref bytesWritten);

So when firing of this the game crashed.. Apparently there is more to this and i cant seem to fully understand how this instruction works. What would the next steps for me be?

Is the address for the instruction the wrong place to send this? If so, how would i get the correct address in memory to send this to?

  • 0x42abed contains an instruction 0042ABED | mov dword ptr ds:[eax+edi],esi | you are corrupting the whole program before writing try reading and displaying write only when you are confident you are writing to the right place read edi , or read [80B874] read eax add them up and read what it contains and print it when you are sure it synces with what you are seeing physically write to that address
    – blabb
    May 10, 2016 at 18:25

2 Answers 2


Firstly, i doubt that quake uses a float variable for the ammo count; floats are much slower than integers, and there's not really a need for a floating point value. So if you had 23 ammo, and the scanner found a 23.0 float variable, you probably have the wrong location.

Secondly, the address that the ammo count gets written to is the sum of eax and edi, where eax looks like an input variable, and edx like a pointer that's stored in some global constant. Maybe that pointer gets initialized by malloc(). It may be different every time you run the program. Next run, there's something at the same address that's completely unrelated, and your program crashes because you overwrite that other thing.

Probably the best thing you can do is run the program under a debugger like WinDBG or Ollydebug, set a breakpoint at that location, and check if it really gets hit if and only if your ammo count changes (you pick up an ammo pack or fire a shot in game). Try changing the variable at that address from the debugger. If that works, start the program a few times, find out how the address changes and how to find the correct one, then code that in your C# program.

If, as you say in your comment, the debugger shows that eax is always 4A4 at this point, i'd change the C# program to read the content of 80B874, add 4A4, read the float there, and display it, along with the content of 80B874. Start quake, run your program, play for a few minutes, run your program again. Stop quake and repeat from start a few times. Analyze if/when the content of 80B874 changes and if the ammo count is correct. Once you have your program at the point that it displays the correct ammo count, every time, start changing the ammo count.

  • Hi Guntram thanks for taking your time to answer. Yes i doubt myself that this is a float it makes no sense, it should be an integer, but after a lot of testing i found this float value (search by type) which is synced with the ammo count, i have even edited it and it is changing my ammo count. Either way, i am using a debugger, x32dbg to be exact. I use CrySearch to just get to the first address an pointer and work my way from there with x32dbg, but i am completely new to this so i need a little help get going, it is a lot to take in. EAX is always 4A4. May 10, 2016 at 14:21

I highly recommend reading through the following tutorial on creating a game trainer with C#.


You can just use it for a template initially for testing until you understand everything about it, including what differs from your current solution. It's a relatively short tutorial, but it should give you a lot of ancillary research to follow through with.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.