Advertisement
AndrewHaxalot

pycheat.py

Dec 6th, 2013
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.30 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # small universal game trainer proof of concept
  3. # - search byte location in memory by value
  4. # - modify byte location in memory
  5. # Copyright (C) 2010  Matthias -apoc- Hecker <apoc@sixserv.org>
  6. #
  7. # This program is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation, either version 3 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19.  
  20. # http://bitbucket.org/haypo/python-ptrace/overview
  21. from ptrace.debugger.debugger import PtraceDebugger
  22. from ptrace.debugger.memory_mapping import readProcessMappings
  23. import sys
  24. import logging
  25. import os
  26. import pickle
  27.  
  28. #logging.basicConfig(level=logging.DEBUG)
  29.  
  30. if len(sys.argv) != 2:
  31.     print "Usage: %s <PID>" % sys.argv[0]
  32.     sys.exit()
  33.  
  34. pid = int(sys.argv[1])
  35. max_memory = 0x00FFFFFF
  36.  
  37. locations_file = "pycheat_locations.tmp"
  38. open(locations_file, "w").close() # truncate file
  39.  
  40. print "pycheat: universal game trainer v0.1"
  41. print "process id: %d" % pid
  42. print "highest address: %#x" % max_memory
  43.  
  44. def write_locations(locations):
  45.     global locations_file
  46.     tmpfile = open(locations_file, "w")
  47.     pickle.dump(locations, tmpfile)
  48.     tmpfile.close()
  49.    
  50. def read_locations():
  51.     global locations_file
  52.     try:
  53.         tmpfile = open(locations_file, "r")
  54.         locations = pickle.load(tmpfile)
  55.         return locations
  56.     except:
  57.         return None
  58.     else:
  59.         tmpfile.close()
  60.  
  61. def search_memory_locations(pid, max_memory, search_value):
  62.     child_pid = os.fork()
  63.     if child_pid == 0: # search within forked process:
  64.         locations = list()
  65.         prev_locations = read_locations()
  66.  
  67.         dbg = PtraceDebugger()
  68.         process = dbg.addProcess(pid, False)
  69.         memory_mappings = readProcessMappings(process)
  70.  
  71.         print "\x1B[?25l", # deactivate cursor (^_^)
  72.         for memory_mapping in memory_mappings:
  73.             # only search in read/writable memory areas within range...
  74.             if "rw" in memory_mapping.permissions and memory_mapping.end <= max_memory:
  75.                 for loc in range(memory_mapping.start, memory_mapping.end):
  76.                     value = process.readBytes(loc, 1)
  77.                     if value[0] == search_value:
  78.                         print "search memory area[0x%08X-0x%08X] address[0x%08X] value[0x%02X (%03d)]   \r" % (memory_mapping.start, memory_mapping.end, loc, ord(value), ord(value)),
  79.  
  80.                         if prev_locations and len(prev_locations) > 0 and not loc in prev_locations:
  81.                             continue # skip prev not found locations
  82.  
  83.                         locations.append(loc)
  84.         print "\x1B[?25h", # activate cursor
  85.         dbg.quit()
  86.         write_locations(locations)
  87.         sys.exit()
  88.  
  89.     return child_pid # don't really need this
  90.  
  91. def change_memory(pid, location, value):
  92.     dbg = PtraceDebugger()
  93.     process = dbg.addProcess(pid, False)
  94.     process.writeBytes(location, value)
  95.     dbg.quit()
  96.  
  97. locations = None # loop until the correct (uniqe) location is found
  98. while not locations or len(locations) != 1:
  99.     print
  100.     if locations and len(locations) != 1:
  101.         print "found %d occurrences, change value to:" % len(locations),
  102.     else:
  103.         print "searching for address by byte value:",
  104.     search_value = "%c" % int(raw_input())
  105.  
  106.     # this forks the process and search within memory...
  107.     search_memory_locations(pid, max_memory, search_value)
  108.  
  109.     # wait until the forked process returns/quits
  110.     os.wait()
  111.  
  112.     # for communication with forked process a pickle tmp file is used
  113.     locations = read_locations()
  114.  
  115. found_location = locations[0]
  116.  
  117. print
  118. print "found 1 occurrence! correct address for this value is 0x%08X" % (found_location)
  119. print "change value in memory at 0x%08X to:" % (found_location),
  120. change_value = "%c" % int(raw_input())
  121.  
  122. change_memory(pid, found_location, change_value)
  123. print "done."
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement