Fuzzing engine with vtrace
Ever since I first started building my first fuzz-like tools, I always felt that having a solid monitoring engine was a must. While developing
Egurra,
and motivated by the learnings from
Gray Hat Python
by Justin Seitz, I leaned pretty straightforwardly towards
PyDbg.
Unfortunately the component in charge of loading the debuggee in each iteration did so using the
load()
method. This entry point kept failing in an inconsistent fashion, as also confirmed by
other
users. Even the creator, Pedram Amini itself, acknowledged so in the official documentation (source):
To Do: This routines needs to be further tested ... I nomally just attach.Hence, looking for other alternatives two names stuck out for me:
- PyDbgEng: Python wrapper around the official windows debugging engine. Also, current underlying engine for the Peach fuzzer.
- vtrace: VDB is a debugger written using the vtrace API built by Invisigoth from Kenshoto.
def fuzz(exe_path,format):
print "[*]"
print "[*] Starting fuzzer"
print "[*]"
try:
it = 0
while 1:
print "[*]"
print "[*] running iteration %d" % it
print "[*]"
mutate(format)
me = getTrace()
handler = VerboseNotifier(format)
me.registerNotifier(NOTIFY_SIGNAL,handler)
thread = threading.Thread(target=proc,args=(me,exe_path,format))
thread.setDaemon(0)
thread.start()
time.sleep(5)
if me.isRunning():
print "[*]"
print "[*] killing process %d " % me.getPid()
print "[*]"
me.kill()
time.sleep(1)
it += 1
except KeyboardInterrupt:
print "[*]"
print "[*] Closing fuzzing session, %d iterations completed." % it
print "[*]"
sys.exit(0)In this block we instantiate a Trace entity calling
getTrace()
. In the next two lines, we register a handler for SIGNAL events inside the debugged process, which we'll cover deeply latter on. In this context,
formatrefers
to the file format currently being fuzzed. Apart from that, the rest of the code is standard Python threading code: Launch a debugging thread and wait for 5 seconds and then check if the process is still running (hence, no crash) and kill it if that's the case.
In the following code, we will take a quick glance at the
proc
function that will launch the debugged app:
def proc(dbg,exe_path,format):
dbg.execute(exe_path+" test.%s" % format)
dbg.run()No voodoo here either, just load the executable and let it run.
Finally we will cover the most juicy aspect of all this process, the signaling and exception handling. For this matter, althought not the most elegant and most correct solution, I opted for tweaking directly some code in the vtrace libs. The following tweaks happened inside
vtrace/notifiers.py:
class VerboseNotifier(Notifier):
def __init__(self,format):
self.format = format
def notify(self, event, trace):
dict = trace.getMeta("Win32Event")
if dict['ExceptionCode'] == 0xC0000005L:
print "[*] Access violation spotted!"
stamp = time.localtime()
fd = open("crashes\\crash-%s.log" % stamp, "w")
fd.write("ESP: 0x%08x" % trace.getRegisterByName('esp'))
fd.write("\n")
fd.write("EIP: 0x%08x" % trace.getProgramCounter())
fd.write("\n")
fd.write(repr(trace.getMeta("Win32Event")))
fd.close()
shutil.copy("test.%s" % self.format, "crashes\\%s.%s" % (stamp,self.format))
trace.kill()
else:
print "[*] First chance...passing over."
trace.setMode("RunForever", True)
VerboseNotifier()
is, as the name implies, a very informative type of Notifier. It simply spits out generic information regarding every event that happens inside the debugged process.
In this particular case we are interested in catching
ACCESS_VIOLATION
exceptions only. Every time a event happens inside the debugged process, the
notify()
routine will be referenced with the parameters properly populated. All we need to do is check whether the event was
ACCESS_VIOLATION
exception or not. If this is the case, we will log both the crash and the sample file for latter analysis. Yet again, the
formatparameter
refers to the file format being fuzzed, pure convenience.
Althought we focused on a particular use case here, vtrace contains A LOT of functionality and could definitely be used in a lot of different scenarios.
Happy hunting!
References:
- atlas wandering
- DEFCON 16: VulnCatcher: Fun with Vtrace and Programmatic Debugging (Youtube Video)
- vtrace (GoogleCode mirror)
- PyDbgEng