3

I read some data from a process (address: 0x58F03C) by using the WINAPI function ReadProcessMemory:

DWORD proc_id;
GetWindowThreadProcessId(hwnd, &proc_id);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, proc_id);
int value=0;

while (1)
{
    ReadProcessMemory(hProcess, (LPVOID)0x58F03C, &value, sizeof(value), 0);
    cout << "val: " << value << endl;
}

Since the address changes every time I restart the process I wondered if there is a way to always get the same address? There must be one because I see a lot of "Trainer-Programs" which are able to do that. How do they obtain the right address value to read from / write to?

Currently I obtain it by scanning for a value with the CheatEngine and perform a next scan for changed value.

Thanks.

Matt
  • 22,721
  • 17
  • 71
  • 112
arminb
  • 2,036
  • 3
  • 24
  • 43
  • unless the executable requires a fixed base address this is never going to be possible. as suggested in some answers think about relative addressing from the base address. – jheriko May 20 '12 at 12:02

2 Answers2

2

You are encountering dynamic memory allocation. In the CheatEngine world, these are called 'pointers'.

Consider some data (for example a uint32_t/DWORD) inside memory which was malloc'd. If you find the address of the data, there is no guarantee that the next time you launch the process, the address will be the same. This is because the memory returned by malloc could be based at a different point in memory.

The trick used to defeat dynamic memory allocation is to find a static heap address which can lead you to the address of the value you are interested in. The CheatEngine tutorial shows you how this is done. The same applies for multi-level pointers. At a higher level, this corresponds to dynamically allocated memory which holds a pointer to some other dynamically allocated memory, and so on.

The method used in CheatEngine to get pointers works approximately like this:

  • Set an access hardware breakpoint at the address of the data value you are interested in
  • When code accesses it, the hardware breakpoint will show you what the code looks like

The code will typically look something like this:

mov eax, 0x1234ABCD 
dec dword ptr ds:[eax+0x85]

This might correspond to some code which decrements your HP when hit by an enemy. 0x1234ABCD is the pointer in this case and 0x85 the offset. In C code, this might have happened:

struct some_struct* blah = malloc(...);
...
blah->HP--;

0x1234ABCD would be the address of blah. The HP value lives somewhere inside the block pointed to by blah. The offset into the memory block is 0x85. Then if you were writing a trainer, you would read the DWORD (QWORD if 64 bit) at 0x1234ABCD and add 0x85 to the value. This would give you the address of the HP value.

Mike Kwan
  • 24,123
  • 12
  • 63
  • 96
0

This will work if the address is in the executable's portion of the data section where preallocated variables live (not suitable for heap and stack)...

Take a look at the "Enumerating All Modules For a Process" example on MSDN.

It uses EnumProcessModules() to get module handles. Those are image base addresses.

You can obtain the image base address for the executable and adjust your address by it.

Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
  • @MikeKwan: Do you think Windows relocates sections of a PE image by different amounts, that is, does not move the thing as a whole? – Alexey Frunze May 20 '12 at 04:08
  • certainly it does. Think about ASLR. That's why you should use `GetModuleHandle` to dynamically get the base of the module, because that can change too. – Mike Kwan May 20 '12 at 11:16
  • @MikeKwan: All I can see is that ASLR affects the image base address, heap, stack and PEB. See [this article](http://technet.microsoft.com/en-us/magazine/2007.04.vistakernel.aspx) and [this article](http://en.wikipedia.org/wiki/Address_space_layout_randomization#Microsoft_Windows) and [this](http://en.wikipedia.org/wiki/Portable_Executable#Relocations) for example. – Alexey Frunze May 20 '12 at 11:45