Posts Tagged ‘ptrace’

Memory Debugging or a “Universal Game Trainer” with Python and ptrace

by apoc · juli 26 2010 · leave a comment

Reading and writing other process memory can have many different purposes: besides debugging, this technique is probably most frequently known to be used by game trainers, to alter different values of a running game (like the value of health or money).

Most (if not all) of the game trainers available, are developed for Windows and only for a specific game, but there are some universal trainers, that could be used to locate and change values in memory of any game or application and with kcheat and Tursiops there are some solutions for Linux.
I’ve developed a proof of concept to locate and change any byte value using python and the ptrace bindings. ptrace is a Unix system call for controlling other processes, it is for instance used by the gdb debugger.

The following code creates a debugging instance and attaches the other process by PID:

from ptrace.debugger.debugger import PtraceDebugger
 
dbg = PtraceDebugger()
process = dbg.addProcess(1234, False)

Now the process instance can be used to inspect and manipulate the process. To manipulate the memory it is important to know the virtual memory mappings (‘areas’) of the process:

from ptrace.debugger.memory_mapping import readProcessMappings
 
memory_mapping = readProcessMappings(process)

Now the list contains MemoryMapping instances, describing the virtual memory areas of the process. We are interested in their location and permission (Quickref: mapping.start, mapping.end, mapping.permissions). The trainer should only be searching within memory mappings with “rw” permissions.

Last but not least, the reading and writing from/to memory methods:

value = process.readBytes(0x11223344, 1) # this reads 1 byte
process.writeBytes(0x11223344, value) # writes len(value) bytes

After that you can close the debugger instance by:

dbg.quit()

I encountered some difficulties with closing/detaching the debugging process, it seems that the process is only really detached if the script is terminated, as a workaround I forked the memory search process, to circumvent that in my proof of concept trainer.

That’s it! If you’re interested, you can checkout my proof of concept for a universal game trainer: pycheat.py (GPLv3) It can locate and change byte values (char) in other processes memory:

% python pycheat.py 8169
pycheat: universal game trainer v0.1
process id: 8169
highest address: 0xffffff
 
searching for address by byte value: 23
search memory area[0x00DB8000-0x00DC0000] address[0x00DBD989] value[0x17 (023)]    
 
found 5926 occurrences, change value to: 33
search memory area[0x00DB8000-0x00DC0000] address[0x00DBFD88] value[0x21 (033)]    
 
found 1 occurrence! correct address for this value is 0x00C4335A
change value in memory at 0x00C4335A to: 99
done.

First you enter the known value, the trainer is searching it inside the memory, chances are high, that there are many occurrences of it, so you change the value inside the game and repeat the search with the new one. After ~2-4 iterations the correct location should be found and you can manipulate it.

edit: smaller changes

Tagged: , , , ,