#!c:\python\python.exe

"""
In Memory Fuzzer 0.02a
"""

import time
import random
import utils
import struct

from pydbg import *
from pydbg.defines import *

snapshot_hook  = 0x00413495
restore_hook   = 0x00413604
snapshot_taken = False
hit_count      = 0
address        = 0

########################################################################################################################
### callback handlers.
########################################################################################################################

def handle_bp (dbg):
    global snapshot_hook, restore_hook, snapshot_taken, hit_count, address

    if dbg.exception_address == snapshot_hook:
        hit_count += 1
        print "snapshot / mutate hook point hit #%d" % hit_count

        # if a process snapshot has not yet been taken, take one now.
        if not snapshot_taken:
            start = time.time()
            print "taking process snapshot...",
            dbg.process_snapshot()
            end = time.time() - start
            print "done. completed in %.03f seconds" % end
            #context_list = dbg.dump_context_list(stack_depth=4, print_dots=True)
            print dbg.dump_context(stack_depth=4, print_dots=True)
            #print dbg.hex_dump(dbg.read_process_memory(dbg.context.Eax, 20))
            snapshot_taken = True

        if hit_count > 1:
            if address:
                print "freeing last chunk at %08x" % address
                dbg.virtual_free(address, 1000, MEM_DECOMMIT)

            print "allocating chunk of memory to hold mutation"
            address = dbg.virtual_alloc(None, 1000, MEM_COMMIT, PAGE_READWRITE)
            print "memory allocated at %08x" % address
            print "generating mutant...",
            mutant = struct.pack('hllll',random.randint(0, 255),0,2,2,0)
            print "done. generating mutant"
            print "writing mutant into target memory space"
            dbg.write(address, mutant)
            print "modifying function argument to point to mutant"
            dbg.write(dbg.context.Esp + 4, dbg.flip_endian(address))
            print dbg.hex_dump(dbg.read_process_memory(address,16))
            print "continuing execution...\n"
            dbg.bp_set(restore_hook)

    if dbg.exception_address == restore_hook:
        start = time.time()
        print "restoring process snapshot...",
        dbg.process_restore()
        end = time.time() - start
        print "done. completed in %.03f seconds" % end
        dbg.bp_set(restore_hook)

    return DBG_CONTINUE


def handle_av (dbg):
    print "***** ACCESS VIOLATION *****"

    crash_bin = utils.crash_binning.crash_binning()
    crash_bin.record_crash(dbg)

    print crash_bin.crash_synopsis()
    dbg.terminate_process()


########################################################################################################################


dbg = pydbg()

dbg.set_callback(EXCEPTION_BREAKPOINT,       handle_bp)
dbg.set_callback(EXCEPTION_ACCESS_VIOLATION, handle_av)

found_target = False
for (pid, proc_name) in dbg.enumerate_processes():
    if proc_name.lower() == "applemobiledeviceservice.exe":
        found_target = True
        break

if found_target:
    dbg.attach(pid)
    dbg.bp_set(snapshot_hook)
    dbg.bp_set(restore_hook)
    print "attached to %d. debugger active." % pid
    for addr in dbg.breakpoints.keys():
        print "bp at %08x" % addr
    dbg.run()
else:
    print "target not found."

