pydbg reverseme solution
July 7, 2010 1 Comment
Last week I wrote a keygen here.
This is an almost identical problem, but the binary has been patched to allow debugging (I may do this programmaticly as well, but not yet). I wanted to solve this with programmatic debugging. Here is the exe:
Ice9pch3.
The code simply sets a breakpoint and prints the key to the screen. Also it patches the process memory so that the serial is valid.
import sys import ctypes from pydbg import * from pydbg.defines import * print "This is a very stupid keygen that uses a debug method and grabs the key from memory" print "prints out the valid key, and writes it to memory" print "Basically, pydbg 'hello, world'" print "-------------" if len(sys.argv) != 2: print "Error. USAGE: keygen.py C:fullpathice" sys.exit(-1) def handler_breakpoint(mdbg): valid_str = "" #the valid serial is at 004030C8 addr = 0x004030C8 while 1: tmp = mdbg.read(addr, 1) addr += 1 if tmp != "x00": valid_str = valid_str + tmp else: break print "The valid string is: ", valid_str print "Writing this to memory..." #write this to memory at 004030b4 #def write (self, address, data, length=0) wdata = ctypes.create_string_buffer(valid_str) mdbg.write(0x00403198, wdata, len(valid_str)) #checking the write #print mdbg.read(0x00403198, len(valid_str) + 1) return DBG_CONTINUE dbg = pydbg() dbg.set_callback(EXCEPTION_BREAKPOINT, handler_breakpoint) dbg.load(sys.argv[1]) dbg.debug_event_iteration() #at 004011FF in execution, #def bp_set (self, address, description="", restore=True, handler=None): dbg.bp_set(0x004011F5) dbg.debug_event_loop()
Updated solution. I change a register now to circumvent the isdebuggerpresent call.
import sys import ctypes from pydbg import * from pydbg.defines import * print "This is a very stupid keygen that uses a debug method and grabs the key from memory" print "prints out the valid key, and writes it to memory" print "Basically, pydbg 'hello, world'" print "-------------" if len(sys.argv) != 2: print "Error. USAGE: keygen.py C:fullpathice" sys.exit(-1) def handler_breakpoint(mdbg): if mdbg.get_register("EIP") == 0x004011F5: valid_str = "" #the valid serial is at 004030C8 addr = 0x004030C8 while 1: tmp = mdbg.read(addr, 1) addr += 1 if tmp != "x00": valid_str = valid_str + tmp else: break print "The valid string is: ", valid_str print "Writing this to memory..." #write this to memory at 004030b4 #def write (self, address, data, length=0) #wdata = ctypes.create_string_buffer(valid_str) mdbg.write(0x00403198, valid_str, len(valid_str)) #checking the write #print mdbg.read(0x00403198, len(valid_str) + 1) if mdbg.get_register("EIP") == 0x40106e: mdbg.set_register("EAX", 0) return DBG_CONTINUE dbg = pydbg() dbg.set_callback(EXCEPTION_BREAKPOINT, handler_breakpoint) dbg.load(sys.argv[1]) dbg.debug_event_iteration() #0x40106e is the point where we can circumvent the isdebugger present call dbg.bp_set(0x40106e) #at 004011FF in execution, #breakpoing for reading writing final compare dbg.bp_set(0x004011F5) dbg.debug_event_loop()
In this case it was unecessary to use the create_string_buffer function. Simpler would be to:
mdbg.write(0×00403198, valid_str, len(valid_str))