As I said before, we will use a python library in order to implement the debugger. The best way to implement a debugger in python is...
pydbg
! This library is part of Paimei
, a reverse engineering framework created by Pedram Amini and is available for Windows and OS X since a few months. This Swiss army knife will be use a lot of times in this blog and I encourage you to read the documentation and play with it. Here is an extract of the documentation:PyDbg exposes most of the expected debugger functionality and then some. Hardware / software / memory breakpoints, process / module / thread enumeration and instrumentation, system DLL tracking, memory reading/writing and intelligent dereferencing, stack and SEH unwinding, exception and event handling, endian manipulation routines, memory snapshot and restore functionality, disassembly (libdasm) engine, and more...
The first step in the script will be to retrieve the table from the file. I won't explain this code as it would be useless:
def getJmpTable(filename):
jmpTable = {}
f = open(filename, 'r')
for line in f:
elem = line.rsplit(' ')
jmpTable[elem[0].rstrip('L')] = elem[1].rstrip('\n')
return jmpTable
As
pydbg
is well written, it is really easy to implement the debugger. The first step is to set a callback for the desired exception, which in our case is the breakpoint exception.
dbg = pydbg()
dbg.set_callback(EXCEPTION_BREAKPOINT, brkHandler)
Then we just have to load the binary into
pydbg
and launch the process:
dbg.load(os.sys.argv[1])
dbg.debug_event_loop()
Before describing our breakpoint exception's handler, I have to explain something about
pydbg
. If you look into the source code at pydbg.py:1528
(I'm looking at the OS X version while writting this post) you will see a call to bp_is_ours
. This check is a little bit anoying in our case as we want to have our callback call for the breakpoints (int3
instructions) even if they are not set by pydbg
. Here you have two options:- modify pydbg code
- consider that this is only a POC... and use a loop to set the breakpoints from the table
The next step is to retrieve the context of the thread who triggered the exception and check if
eip
is corresponding to an address in the table. If it is the case, eip
is modified and the context is restored.
def brkHandler(pydbg):
if pydbg.first_breakpoint:
return DBG_CONTINUE
ctx = pydbg.get_thread_context(pydbg.open_thread(pydbg.dbg.dwThreadId))
eip = hex(ctx.Eip).rstrip('L')
if jmpTable.has_key(eip):
ctx.Eip = int(jmpTable[eip], 16)
pydbg.set_thread_context(ctx, pydbg.open_thread(pydbg.dbg.dwThreadId))
return DBG_CONTINUE
That's it, that's all. As you can see it is quite easy to use pefile, pydasm and pydbg in order to implement some POC or help while reverse engineering softwares.
To conclude, two links (hurry up to get the French one before such content become illegal in France...):
No comments:
Post a Comment