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.
Althought PyDbgEng has the richest documentation of the two, I'll cover the latter one for the rest of this article because I got the most consistent results with it. vtrace comes with no documentation at all, aside from the source code itself. This inevitably forces us to take a look at the source in order to get some clues as to what is what and how to build anything useful out of it. Appart from the code, atlas's atlasutils came very handy for example reference. The main class that will support the meat of our debugging entity is the Trace class stored in the vtrace folder. Let's see it in action:
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: