def main(argv): # Parse the command line arguments options = parse_cmdline(argv) # Create the event handler object eventHandler = Tracer() eventHandler.options = options # Create the debug object debug = Debug(eventHandler, bHostileCode=options.hostile) try: # Attach to the targets for pid in options.attach: debug.attach(pid) for argv in options.console: debug.execv(argv, bConsole=True, bFollow=options.follow) for argv in options.windowed: debug.execv(argv, bConsole=False, bFollow=options.follow) # Make sure the debugees die if the debugger dies unexpectedly debug.system.set_kill_on_exit_mode(True) # Run the debug loop debug.loop() # Stop the debugger finally: if not options.autodetach: debug.kill_all(bIgnoreExceptions=True) debug.stop()
def main( argv ): # Parse the command line arguments options = parse_cmdline(argv) # Create the event handler object eventHandler = Tracer() eventHandler.options = options # Create the debug object debug = Debug(eventHandler, bHostileCode = options.hostile) try: # Attach to the targets for pid in options.attach: debug.attach(pid) for argv in options.console: debug.execv(argv, bConsole = True, bFollow = options.follow) for argv in options.windowed: debug.execv(argv, bConsole = False, bFollow = options.follow) # Make sure the debugees die if the debugger dies unexpectedly debug.system.set_kill_on_exit_mode(True) # Run the debug loop debug.loop() # Stop the debugger finally: if not options.autodetach: debug.kill_all(bIgnoreExceptions = True) debug.stop()
def analyze_crash(cmd): """ This is called with the command line (including the filename) which caused the crash before. It is a late analysis routine which sorts the crashes. """ global file_info global victim_filename global crash_filename # TODO: This may not always be the case victim_filename, crash_filename = cmd print "=== [*] Analyzing %s" % crash_filename file_binary = fileops.get_base64_contents(crash_filename) if file_binary: file_info = (crash_filename, file_binary) # Instance a Debug object, passing it the event handler callback. debug = Debug(crash_event_handler, bKillOnExit = True) try: # Start a new process for debugging. debug.execv(cmd) # Wait for the debugee to finish. debug.loop() # Stop the debugger. finally: debug.stop()
class Process(object): def __init__(self, api_hooks=None): System.request_debug_privileges() self.api_hooks = api_hooks self.hooks = [] self.debugger = None def _loop(self): try: self.debugger.loop() except KeyboardInterrupt: self.debugger.stop() def hook_function(self, address, pre_callback=None, post_callback=None, signature=None): if not pre_callback and not post_callback: return self.hooks.append((address, pre_callback, post_callback, signature)) def start(self, path, kill_process_on_exit=True, anti_anti_debugger=False, blocking=True): def function(): os.chdir(os.path.dirname(path)) self.debugger = Debug(HookingEventHandler(self.hooks, self.api_hooks), bKillOnExit=kill_process_on_exit, bHostileCode=anti_anti_debugger) self.debugger.execv([path]) self._loop() if blocking: function() start_new_thread(function) def attach(self, pid, kill_process_on_exit=False, anti_anti_debugger=False, blocking=True): def function(): self.debugger = Debug(HookingEventHandler(self.hooks, self.api_hooks), bKillOnExit=kill_process_on_exit, bHostileCode=anti_anti_debugger) self.debugger.attach(pid) self._loop() if blocking: function() start_new_thread(function)
def extract_payload(file_path): """ Function that'll handle winappdbg debug :param file_path: path of QuantLoader :return: bool """ debug = Debug(QHandler()) try: debug.execv([file_path]) debug.loop() finally: debug.stop()
def simple_debugger(argv): # Instance a Debug object. debug = Debug() try: # Start a new process for debugging. debug.execv(argv) # Launch the interactive debugger. debug.interactive() # Stop the debugger. finally: debug.stop() return
def simple_debugger(argv): # Instance a Debug object, passing it the MyEventHandler instance debug = Debug(MyEventHandler()) try: debug.execv(argv) debug.loop() # Stop the debugger finally: debug.stop()
def simple_debugger( argv ): # Instance a Debug object, passing it the event handler callback. debug = Debug( my_event_handler, bKillOnExit = True ) try: # Start a new process for debugging. debug.execv( argv ) # Wait for the debugee to finish. debug.loop() # Stop the debugger. finally: debug.stop()
def simple_debugger(argv): # Instance a Debug object, passing it the event handler callback. debug = Debug(my_event_handler, bKillOnExit=True) try: # Start a new process for debugging. debug.execv(argv) # Wait for the debugee to finish. debug.loop() # Stop the debugger. finally: debug.stop()
def simple_debugger( argv ): # Instance a Debug object. debug = Debug() try: # Start a new process for debugging. debug.execv( argv ) # Launch the interactive debugger. debug.interactive() # Stop the debugger. finally: debug.stop()
def DebugProgram(filepath): #Instance a Debug object. debug_args = list() debug_args.insert(0,PROGRAM_PATH) debug_args.insert(len(debug_args),filepath) debug = Debug(AccessViolationHandlerWINAPPDBG, bKillOnExit = True) #debug.system.load_dbghelp("C:\\Program Files\\Debugging Tools for Windows (x86)\\dbghelp.dll") System.fix_symbol_store_path(symbol_store_path = "C:\\ProgramData\\Dbg\\sym",remote = True,force = True) #enter local symbol path here if you have downloaded symbols System.set_kill_on_exit_mode(True) try: # The execution time limit is 5 seconds. maxTime = time() + 5 # Start a new process for debugging. debug.execv(debug_args) # Wait for the debugee to finish. #debug.loop() # Loop while calc.exe is alive and the time limit wasn't reached. while debug and time() < maxTime: try: # Get the next debug event. debug.wait(1000) # 1 second accuracy # Show the current time on screen. #print time() # If wait() times out just try again. # On any other error stop debugging. except WindowsError, e: if e.winerror in (win32.ERROR_SEM_TIMEOUT, win32.WAIT_TIMEOUT): continue raise # Dispatch the event and continue execution. try: debug.dispatch() finally: debug.cont() # Stop the debugger. finally: debug.stop()
def simple_debugger(argv): # Instance a Debug object, passing it the event handler callback. debug = Debug(my_event_handler, bKillOnExit=True) timer = threading.Timer(2.0, killProc, [ os.path.basename(argv[0]), ]) try: # Start a new process for debugging. debug.execv(argv) timer.start() # Wait for the debugee to finish. debug.loop() # Stop the debugger. finally: debug.stop() print " [*]kill timer" timer.cancel() # cancle是每一轮fuzzing之后都会执行?
def analyzeCrashes(): global threads, curr_input if not os.path.exists(crash_dir): logger.info('[!] ' + datetime.now().strftime("%Y:%m:%d::%H:%M:%S") + ' There are no crashing inputs to analyze!') return if len(threads) == 0: popup = PopUpKiller() popup_tid = thread.start_new_thread(popup.POPUpKillerThread, ()) threads.append(popup_tid) for file in os.listdir(crash_dir): try: if file == "": continue curr_input = '{0}\\{1}'.format(crash_dir, file) logger.debug('[+] Generating symlink to {0}'.format(curr_input)) if symlink(curr_input, refFile) == 1: #make symbolic link continue #cmd = [PROG_NAME, PROG_ARGUMENTS, wordFile] cmd = [PROG_NAME, wordFile] logger.debug('[+]', datetime.now().strftime("%Y:%m:%d::%H:%M:%S"), 'Executing : ', cmd) debug = Debug(AccessViolationHandlerWINAPPDBG, bKillOnExit=True) proc = debug.execv(cmd) wordGuard_tid = thread.start_new_thread(StillRunningWINAPPDBG, (proc, )) threads.append(wordGuard_tid) debug.loop() except: pass finally: try: logger.debug( '[+] Removing symlink from {0}'.format(curr_input)) os.remove(refFile) except: pass
def launchWord(queue): global exec_count, curr_input, event fail_count = 0 logger.debug('[+] ' + datetime.now().strftime("%Y:%m:%d::%H:%M:%S") + ' Word Thread started..') word = win32com.client.DispatchEx("word.Application") logger.debug('[+]', datetime.now().strftime("%Y:%m:%d::%H:%M:%S"), 'Using debugger : ', DEBUGGER) #wordGuard_tid = thread.start_new_thread(wordGuard, ()) #cmd = [PROG_NAME, PROG_ARGUMENTS, wordFile] cmd = [PROG_NAME, wordFile] #logger.debug('[+]',datetime.now().strftime("%Y:%m:%d::%H:%M:%S"),'Executing : ',cmd) debug = Debug(AccessViolationHandlerWINAPPDBG, bKillOnExit=True) proc = debug.execv(cmd) debug.loop() while (fail_count < 10 and fail_count >= 0): try: filename = queue.get(False) curr_input = '{0}'.format(filename) exec_count += 1 logger.debug('[+] Generating symlink to {0}'.format(curr_input)) if symlink(curr_input, refFile) == 1: #make symbolic link continue #If it is a directory, continue try: logger.debug('[+] Updating Word via COM') if (word.Selection.Fields.Update() == 0 ): #update document fields pretty_print(exec_count, '.') except Exception as e: if e is None or not isinstance(e, tuple): pass try: if 'The remote procedure call failed.' in e: logger.debug('[!] We have a crash!') pretty_print(exec_count, '!') if not os.path.exists(crash_dir): os.mkdir(crash_dir) os.system("cp {0} {1} > NUL".format( curr_input, crash_dir)) fail_count = -1 else: logger.debug('[?] We have a hang?') pretty_print(exec_count, '?') ForceKillOffice() fail_count = -1 sleep(2) except: pass finally: logger.debug( '[+] Removing symlink from {0}'.format(curr_input)) queue.task_done() try: os.remove(refFile) sleep(0.1) except: pass except Queue.Empty: fail_count += 1 continue try: word.Quit() ForceKillOffice() except: pass
def createDebugger(self, command): debug = Debug(self.debuggerEventHandler, bKillOnExit=True) argv = command.split() debug.execv(argv) debug.loop()
print "CreateFileW: %s" % (fname) # The post_ functions are called upon exiting the API def post_CreateFileW(self, event, retval): if retval: print 'Suceeded (handle value: %x)' % (retval) else: print 'Failed!' if __name__ == "__main__": if len(sys.argv) < 2 or not os.path.isfile(sys.argv[1]): print "\nUsage: %s <File to monitor> [arg1, arg2, ...]\n" % sys.argv[0] sys.exit() # Instance a Debug object, passing it the MyEventHandler instance debug = Debug(MyEventHandler()) try: # Start a new process for debugging p = debug.execv(sys.argv[1:], bFollow=True) # Wait for the debugged process to finish debug.loop() # Stop the debugger finally: debug.stop()
class WinBasic: debugger = None mainProc = None alwaysCatchExceptions = [ win32.STATUS_ACCESS_VIOLATION, win32.STATUS_ILLEGAL_INSTRUCTION, win32.STATUS_ARRAY_BOUNDS_EXCEEDED, ] def __init__(self, killOnExit=True): self.debugger = Debug(bKillOnExit=killOnExit) self.mainProcs = [] def run(self, executable, children=True): tmp = self.debugger.execv(executable, bFollow=children) self.mainProcs.append(tmp) return tmp.get_pid() def attachPid(self, pid): self.mainProcs.append(self.debugger.attach(pid)) def attachImg(self, img): self.debugger.system.scan_processes() for (process, name) in self.debugger.system.find_processes_by_filename(img): self.attachPid(process.get_pid()) def close(self, kill=True, taskkill=True, forced=True): pids = self.debugger.get_debugee_pids() self.debugger.detach_from_all(True) for pid in pids: if kill: try: proc = self.debugger.system.get_process(pid) proc.kill() except: pass # Taskkill if taskkill and not forced: subprocess.call(["taskkill", "/pid", str(pid)], stdout=subprocess.PIPE, stderr=subprocess.PIPE) if taskkill and forced: subprocess.call(["taskkill", "/f", "/pid", str(pid)], stdout=subprocess.PIPE, stderr=subprocess.PIPE) def waitForCrash(self, waitTime=4, checkAlive=False): event = None endDebuging = False endTime = time() + waitTime while time() < endTime: if checkAlive: for proc in self.mainProcs: if not proc.is_alive(): return None try: event = self.debugger.wait(1000) except WindowsError, e: if e.winerror in (win32.ERROR_SEM_TIMEOUT, win32.WAIT_TIMEOUT): continue raise crash = self.handler(event) if crash != None: return crash else: try: self.debugger.dispatch() except: pass finally: self.debugger.cont() return None
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # This line is needed in Python 2.5 to use the "with" statement. from __future__ import with_statement from winappdbg import Debug import sys # Instance a Debug object, set the kill on exit property to True. debug = Debug( bKillOnExit = True ) # The user can stop debugging with Control-C. try: print "Hit Control-C to stop debugging..." # Start a new process for debugging. debug.execv( sys.argv[ 1 : ] ) # Wait for the debugee to finish. debug.loop() # If the user presses Control-C... except KeyboardInterrupt: print "Interrupted by user." # Stop debugging. This kills all debugged processes. debug.stop()
class Coverage: verbose = False bbFiles = {} bbFilesBreakpints = [] bbFilesData = {} bbOriginalName = {} modules = [] fileOutput = None #Construct def __init__(self): self.debugger = Debug(bKillOnExit=True) def setVerbose(self, val): self.verbose = val #cuts after . def cutDot(self, input): if input.find(".") == -1: return input return input[0:input.find(".")] #load basic blocks def loadBB(self, baseBbDir): self.bbFiles = {} count = 0 for bbFile in os.listdir(baseBbDir): f = open(baseBbDir + "/" + bbFile, "r") fname = f.readline().strip().lower() fnameOrig = fname if ".dll" not in fname and ".exe" not in fname: #Stupid hack to avoid problems in loading libs with other extensions then .dll fname = self.cutDot(fname) + ".dll" self.bbOriginalName[fname] = fnameOrig self.bbFiles[fname] = count self.bbFilesBreakpints.append({}) rvaHighest = 0 for line in f: rva = int(line[0:8], 16) val = int(line[18:20], 16) self.bbFilesBreakpints[count][rva] = val if rva > rvaHighest: rvaHighest = rva self.bbFilesData[fname] = [rvaHighest + 10, count] if self.verbose: print "Loaded breakpoints for %s with index %02X" % (fname, count) count += 1 f.close() #Register module (original exe image or dll) def registerModule(self, filename, baseaddr): filename = filename.lower() if ".dll" not in filename and ".exe" not in filename: #Stupid hack to avoid problems in loading libs with other extensions then .dll filename = self.cutDot(filename) + ".dll" if filename not in self.bbFiles: return if self.verbose: print " Image %s has breakpoints defined" % filename self.modules.append([ baseaddr, baseaddr + self.bbFilesData[filename][0], self.bbFilesData[filename][1] ]) if self.verbose: print " Image has breakpoints from %08X to %08X with index %02X" % ( baseaddr, baseaddr + self.bbFilesData[filename][0], self.bbFilesData[filename][1]) #Handle a breakpoint def breakpoint(self, location): index = None for i in xrange(len(self.modules)): if location >= self.modules[i][0] and location <= self.modules[i][ 1]: index = i break if index == None: return None rva = location - self.modules[index][0] index = self.modules[index][2] if rva not in self.bbFilesBreakpints[index]: return None self.fileOutput.write("%02X|%08X\n" % (index, rva)) return self.bbFilesBreakpints[index][rva] def startFileRec(self, filename): self.modules = [] self.fileOutput = open(filename, "w") for image in self.bbFiles: self.fileOutput.write( "%s|%02X\n" % (self.bbOriginalName[image], self.bbFiles[image])) def endFileRec(self): self.fileOutput.close() #Start program def start(self, execFile, waitTime=6, recFilename="output.txt", kill=True): self.startFileRec(recFilename) mainProc = self.debugger.execv(execFile, bFollow=True) event = None endTime = time() + waitTime while time() < endTime: if not mainProc.is_alive(): break try: event = self.debugger.wait(1000) except WindowsError, e: if e.winerror in (win32.ERROR_SEM_TIMEOUT, win32.WAIT_TIMEOUT): continue raise if event.get_event_code() == win32.LOAD_DLL_DEBUG_EVENT: module = event.get_module() if self.verbose: print "DLL %s loaded on base %08X" % (module.get_name(), module.get_base()) self.registerModule( self.cutDot(module.get_name()) + ".dll", module.get_base()) elif event.get_event_code() == win32.CREATE_PROCESS_DEBUG_EVENT: tmp = event.get_filename().split("\\") modName = tmp[len(tmp) - 1] if self.verbose: print "Process %s loaded on base %08X" % ( modName, event.raw.u.CreateProcessInfo.lpBaseOfImage) self.registerModule( modName, event.raw.u.CreateProcessInfo.lpBaseOfImage) elif event.get_event_code( ) == win32.EXCEPTION_DEBUG_EVENT and event.get_exception_code( ) == win32.STATUS_BREAKPOINT: pc = event.get_thread().get_pc() - 1 val = self.breakpoint(pc) if val != None: event.get_process().write(pc, chr(val)) event.get_thread().set_pc(pc) endTime = time() + waitTime try: self.debugger.dispatch() except: pass finally: self.debugger.cont() self.endFileRec() if kill: self.kill()
def action_0( event ): global debug aThread = event.get_thread() aProcess = event.get_process() r_eax = aThread.get_register("Eax") r_ecx = aThread.get_register("Ecx") r_edx = aThread.get_register("Edx") debug.dont_break_at(aProcess.get_pid() , 0x0043F90F) words = open('dic.txt', "r").readlines() #lengthall print "[+] Words Loaded:",len(words) try: debug = Debug() # Start a new process for debugging p = debug.execv( ['TrueCrypt.exe', '/v', 'test.tc', '/lx', '/p', "".ljust(WORD_SIZE) ,'/q', '/s']) debug.break_at(p.get_pid() , 0x0043F90F, action_0) #save state debug.break_at(p.get_pid() , 0x0043F929, action_1) #save buffer addres debug.break_at(p.get_pid() , 0x0043F93E, action_2) #check result, restore state, change eip # Wait for the debugee to finish t1 = time.clock() debug.loop() finally: debug.stop() print 'Finished in ' + repr(time.clock() - t1) + ' seconds!'
class WinBasic: debugger = None mainProc = None alwaysCatchExceptions=[win32.STATUS_ACCESS_VIOLATION, win32.STATUS_ILLEGAL_INSTRUCTION, win32.STATUS_ARRAY_BOUNDS_EXCEEDED] def __init__(self, killOnExit = True): self.debugger = Debug(bKillOnExit = killOnExit) self.mainProcs = [] def run(self, executable, children = True): tmp = self.debugger.execv(executable, bFollow = children ) self.mainProcs.append(tmp) return tmp.get_pid() def attachPid(self, pid): self.mainProcs.append(self.debugger.attach(pid)) def attachImg(self, img): self.debugger.system.scan_processes() for ( process, name ) in self.debugger.system.find_processes_by_filename( img ): self.attachPid(process.get_pid()) def close(self, kill = True, taskkill = True, forced = True): pids = self.debugger.get_debugee_pids() self.debugger.detach_from_all( True ) for pid in pids: if kill: try: proc = self.debugger.system.get_process(pid) proc.kill() except: pass #Taskkill if taskkill and not forced: subprocess.call(["taskkill", "/pid", str(pid)], stdout=subprocess.PIPE, stderr=subprocess.PIPE) if taskkill and forced: subprocess.call(["taskkill", "/f", "/pid", str(pid)], stdout=subprocess.PIPE, stderr=subprocess.PIPE) def waitForCrash(self, waitTime = 4, checkAlive = False): event = None endDebuging = False endTime = time() + waitTime while time() < endTime: if checkAlive: for proc in self.mainProcs: if not proc.is_alive(): return None try: event = self.debugger.wait(1000) except WindowsError, e: if e.winerror in (win32.ERROR_SEM_TIMEOUT, win32.WAIT_TIMEOUT): continue raise crash = self.handler(event) if crash != None: return crash else: try: self.debugger.dispatch() except: pass finally: self.debugger.cont() return None
def read_genkey(event): global current_key process = event.get_process() thread = event.get_thread() registers = thread.get_context() keyAddr = registers['Eax'] value = process.read(keyAddr, 80) print "%s : %s" % (hex(current_key), value.encode("hex")) current_key += 1 sys.stdout.flush() process.kill() class MyEventHandler(EventHandler): def create_process(self, event): pid = event.get_pid() event.debug.break_at(pid, 0x0040284E, change_key) event.debug.break_at(pid, 0x00403593, read_genkey) debug = Debug(MyEventHandler(), bKillOnExit=True) current_key = 0x00 while current_key < 0x100: try: debug.execv(["cryptochief.exe"]) debug.loop() except: pass
class WinAppDbgTarget(ServerTarget): def __init__(self, name, process_path, process_args=[], sql_crash_db='sqlite:///crashes.sqlite', logger=None): ''' :param name: name of the object :param process_path: path to the target executable :param process_args: arguments to pass to the process :param attach: try to attach if process path :param sql_crash_db: sql alchemy connection string to crash db (default:sqlite:///crashes.sqlite) :param logger: logger for this object (default: None) ''' super(WinAppDbgTarget, self).__init__(name, logger) assert (process_path) assert (os.path.exists(process_path)) self._process_path = process_path self._process_name = os.path.basename(process_path) self._process_args = process_args self._process = None self._sql_crash_db = sql_crash_db self._crash_event_complete = threading.Event() self._server_is_up = threading.Event() self._crash_event_complete.set() self._debug = Debug(lambda x: _my_event_handler(self, x), bKillOnExit=True) def _debug_server(self): ''' debugger thread ''' try: self._process = None # Start a new process for debugging. argv = [self._process_path] + self._process_args self.logger.debug('debugger starting server: %s' % argv) try: self._process = self._debug.execv(argv, bFollow=True) except WindowsError: self.logger.error('debug_server received exception', traceback.fmt_exc()) self._pid = self._process.get_pid() self.logger.info('process started. pid=%d' % self._pid) # Wait for the debugee to finish. self._server_is_up.set() self._debug.loop() except: self.logger.error('Got an exception in _debug_server') self.logger.error(traceback.format_exc()) # Stop the debugger. finally: self._debug.stop() self._process = None self._pid = -1 self._crash_event_complete.set() def _start_server_thread(self): ''' start the server thread ''' self._server_is_up.clear() self.server_thread = FuncThread(self._debug_server) self.server_thread.start() self.logger.info('waiting for server to be up') self._server_is_up.wait() self.logger.info('server should be up') def _kill_all_processes(self): ''' kill all processes with the same name :return: True if all matching processes were killed properly, False otherwise ''' res = True # Lookup the currently running processes. self._debug.system.scan_processes() # For all processes that match the requested filename... for (process, name) in self._debug.system.find_processes_by_filename( self._process_name): process_pid = process.get_pid() self.logger.info('found process %s (%d) - trying to kill it' % (name, process_pid)) try: process.kill() self.logger.info('successfully killed %s (%d)' % (name, process_pid)) except: self.logger.error('failed to kill %s (%d) [%s]' % (name, process_pid, traceback.format_exc())) res = False return res def teardown(self): self._stop_process() self._process = None super(WinAppDbgTarget, self).teardown() def pre_test(self, test_number): # we need kill all process before fuzzing super(WinAppDbgTarget, self).pre_test(test_number) self._stop_process() def post_test(self, test_num): self.logger.debug('in') time.sleep(1) self.logger.debug('after sleep') res = self._crash_event_complete.wait() self.logger.debug('after wait') if not res: self.report.failed('incomplete crash detected') super(WinAppDbgTarget, self).post_test(test_num) self.logger.debug('out') def _send_to_target(self, data): ''' this is the key off windbgtarget :param data: data is the file path ''' self.logger.info('send called') ''' starting ''' self._process_args = [data] # this may need implement self._start_server_thread() def _stop_process(self): ''' Stop the process (if running) ''' return self._kill_all_processes() def _stop_process_old(self): ''' :return: True if process was killed, False otherwise ''' if self._is_victim_alive(): self._process.kill() time.sleep(0.5) if self._is_victim_alive(): self._process.kill() time.sleep(0.5) if self._is_victim_alive(): raise Exception('Failed to kill client process') self._debug.stop() return True else: self._debug.stop() return False def _restart(self): ''' restart the process ''' self._stop_process() self.server_thread.join(1) time.sleep(3) self._server_is_up.clear() self._start_server_thread() def _is_victim_alive(self): ''' check if process running ''' if self._process: self.logger.debug('process pid: %d' % self._pid) is_alive = self._process.is_alive() is_debugee_started = self._debug.is_debugee_started(self._pid) self.logger.debug('is_alive = %s' % is_alive) self.logger.debug('is_debugee_started = %s' % is_debugee_started) return (is_alive and is_debugee_started) else: self.logger.debug('_process is None') return False
class Coverage: verbose = False bbFiles = {} bbFilesBreakpints = [] bbFilesData = {} bbOriginalName = {} modules = [] fileOutput = None #Construct def __init__(self): self.debugger = Debug( bKillOnExit = True ) def setVerbose(self, val): self.verbose = val #cuts after . def cutDot(self, input): if (input.find(".") == -1): return input return input[0:input.find(".")] #load basic blocks def loadBB(self, baseBbDir): self.bbFiles = {} count = 0 print "baseBbDir:"+baseBbDir for bbFile in os.listdir(baseBbDir): print "bbFile:" + bbFile f = open(baseBbDir + "/" + bbFile, "r") fname = f.readline().strip().lower() #fname = f.readline().strip() fnameOrig = fname if ".dll" not in fname and ".exe" not in fname: #Stupid hack to avoid problems in loading libs with other extensions then .dll fname = self.cutDot(fname) + ".dll" self.bbOriginalName[fname] = fnameOrig self.bbFiles[fname] = count self.bbFilesBreakpints.append({}) rvaHighest = 0 for line in f: try: rva = int(line[0:8], 16) val = int(line[18:20], 16) self.bbFilesBreakpints[count][rva] = val if rva > rvaHighest: rvaHighest = rva except Exception: continue self.bbFilesData[fname] = [rvaHighest + 10, count] if self.verbose: print "Loaded breakpoints for %s with index %02X" % (fname, count) count += 1 f.close() #Register module (original exe image or dll) def registerModule(self, filename, baseaddr): filename = filename.lower() if ".dll" not in filename and ".exe" not in filename: #Stupid hack to avoid problems in loading libs with other extensions then .dll filename = self.cutDot(filename) + ".dll" if filename not in self.bbFiles: return if self.verbose: print " Image %s has breakpoints defined" % filename self.modules.append([baseaddr,baseaddr+self.bbFilesData[filename][0], self.bbFilesData[filename][1]]) if self.verbose: print " Image has breakpoints from %08X to %08X with index %02X" % (baseaddr,baseaddr+self.bbFilesData[filename][0],self.bbFilesData[filename][1]) #Handle a breakpoint def breakpoint(self, location): index = None for i in xrange(len(self.modules)): if location>=self.modules[i][0] and location<=self.modules[i][1]: index = i break if index == None: return None rva = location - self.modules[index][0] index = self.modules[index][2] if rva not in self.bbFilesBreakpints[index]: return None self.fileOutput.write("%02X|%08X\n" % (index, rva)) return self.bbFilesBreakpints[index][rva] def startFileRec(self, filename): self.modules = [] self.fileOutput = open(filename, "w") for image in self.bbFiles: self.fileOutput.write("%s|%02X\n" % (self.bbOriginalName[image], self.bbFiles[image])) def endFileRec(self): self.fileOutput.close() #Start program def start(self, execFile, waitTime = 6, recFilename = "output.txt", kill = True): self.startFileRec(recFilename) mainProc = self.debugger.execv( execFile, bFollow = True ) event = None endTime = time() + waitTime while time() < endTime: if not mainProc.is_alive(): break try: event = self.debugger.wait(1000) except WindowsError, e: if e.winerror in (win32.ERROR_SEM_TIMEOUT, win32.WAIT_TIMEOUT): continue raise if event.get_event_code() == win32.LOAD_DLL_DEBUG_EVENT: module = event.get_module() if self.verbose: print "DLL %s loaded on base %08X" % (module.get_name(), module.get_base()) self.registerModule(self.cutDot(module.get_name())+".dll", module.get_base()) elif event.get_event_code() == win32.CREATE_PROCESS_DEBUG_EVENT: tmp = event.get_filename().split("\\") modName = tmp[len(tmp)-1] if self.verbose: print "Process %s loaded on base %08X" % (modName, event.raw.u.CreateProcessInfo.lpBaseOfImage) self.registerModule(modName,event.raw.u.CreateProcessInfo.lpBaseOfImage) elif event.get_event_code() == win32.EXCEPTION_DEBUG_EVENT and event.get_exception_code() == win32.STATUS_BREAKPOINT: pc = event.get_thread().get_pc()-1 val = self.breakpoint(pc) if val != None: event.get_process().write(pc, chr(val)) event.get_thread().set_pc(pc) endTime = time() + waitTime try: self.debugger.dispatch() except: pass finally: self.debugger.cont() self.endFileRec() if kill: self.kill()
debug = Debug( myevent ) try: if options.pid: debug.attach(options.pid) print_threads_and_modules(options.pid, debug) elif options.program: procs = list_processes(options.program) if len(procs) == 0: print "[E] no matching process" elif len(procs) == 1: debug.attach(procs[0].get_pid()) print_threads_and_modules(procs[0].get_pid(), debug) else: print "[E] ambigious" elif options.command: p = debug.execv( options.command, bFollow = True ) # Wait for the debugee to finish debug.loop() # Stop the debugger finally: debug.stop() #report = open("%s/report.html" % dir, 'a') #if report: report.close()
class Monitor: def __init__(self): self.runtime = 3 self.event = None self.debug = None self.loop_cnt = 0 self.seed_name = None self.mutated_name = None self.pid = None self.access_vi = False def debug_loop(self, e): code = e.get_event_code() self.event = e if code == win32.EXCEPTION_DEBUG_EVENT and e.is_last_chance(): try: crash = Crash(e) crash.fetch_extra_data(e) dump_log = crash.fullReport(False) except: pass crash_type = dump_log.split('\n')[2].split(':')[1] dirname = '/' + crash_type + '_' + str(time.time()) os.mkdir('./logs' + dirname) original_seed = copyfile(r"seed/%s" % self.seed_name, r"logs%s/%s" % (dirname, "original_seed")) mutated_seed = copyfile(r"./%s" % self.mutated_name, r"logs%s/%s" % (dirname, "mutated_bin")) crash_path = "./logs" + dirname + "/crash_dump.txt" f = open(crash_path, 'w') f.write(dump_log) f.close() print "[***] Exception Occurred -> saved in \"%s\" folder" % dirname self.access_vi = True e.get_process().kill() self.debug.stop() def monitor_debug(self): counter = 0 while counter < self.runtime: time.sleep(1) counter += 1 print time.sleep(1) if not self.access_vi: print "[**] No Exception Occurred, stop the debugger process" self.debug.stop() def start_debug(self): self.debug = Debug( self.debug_loop, bKillOnExit=True ) # If True debugged processes are killed when the debugger is stopped. self.debug.execv( command_line ) # execute target program (prameter command_line --> target program, mutate file) self.debug.loop() def start(self, loop_cnt, seed, mutated): self.loop_cnt = loop_cnt # fuzzing loop self.seed_name = seed # seed file self.mutated_name = mutated # mutate file self.access_vi = False # print "[**] Debugger Activated " #pid = raw_input("Enter the PID of the process to attach to: ") #debug.attach(int(pid)) dbg_thread = threading.Thread(target=self.start_debug) dbg_thread.setDaemon(0) dbg_thread.start() counter = 0 while self.pid == None: # waiting for process 5 second if counter < 5: time.sleep(1) counter = counter + 1 if counter >= 5: break monitor_thread = threading.Thread(target=self.monitor_debug) # retry monitor_thread.setDaemon(0) monitor_thread.start()
class WinAppDbgController(BaseController): ''' WinAppDbgController controls a server process by starting it on setup making sure it stays up. It uses winappdbg to attach to the target processes. ''' def __init__(self, name, process_path, process_args=[], sql_crash_db='sqlite:///crashes.sqlite', logger=None): ''' :param name: name of the object :param process_path: path to the target executable :param process_args: arguments to pass to the process :param attach: try to attach if process path :param sql_crash_db: sql alchemy connection string to crash db (default:sqlite:///crashes.sqlite) :param logger: logger for this object (default: None) ''' super(WinAppDbgController, self).__init__(name, logger) assert(process_path) assert(os.path.exists(process_path)) self._process_path = process_path self._process_name = os.path.basename(process_path) self._process_args = process_args self._process = None self._sql_crash_db = sql_crash_db self._crash_event_complete = threading.Event() self._server_is_up = threading.Event() self._crash_event_complete.set() self._debug = Debug(lambda x: _my_event_handler(self, x), bKillOnExit=True) def _debug_server(self): ''' debugger thread ''' try: self._process = None # Start a new process for debugging. argv = [self._process_path] + self._process_args self.logger.debug('debugger starting server: %s' % argv) try: self._process = self._debug.execv(argv, bFollow=True) except WindowsError: self.logger.error('debug_server received exception', traceback.fmt_exc()) self._pid = self._process.get_pid() self.logger.info('process started. pid=%d' % self._pid) # Wait for the debugee to finish. self._server_is_up.set() self._debug.loop() except: self.logger.error('Got an exception in _debug_server') self.logger.error(traceback.format_exc()) # Stop the debugger. finally: self._debug.stop() self._process = None self._pid = -1 self._crash_event_complete.set() def _start_server_thread(self): ''' start the server thread ''' self._server_is_up.clear() self.server_thread = FuncThread(self._debug_server) self.server_thread.start() self.logger.info('waiting for server to be up') self._server_is_up.wait() self.logger.info('server should be up') def _kill_all_processes(self): ''' kill all processes with the same name :return: True if all matching processes were killed properly, False otherwise ''' res = True # Lookup the currently running processes. self._debug.system.scan_processes() # For all processes that match the requested filename... for (process, name) in self._debug.system.find_processes_by_filename(self._process_name): process_pid = process.get_pid() self.logger.info('found process %s (%d) - trying to kill it' % (name, process_pid)) try: process.kill() self.logger.info('successfully killed %s (%d)' % (name, process_pid)) except: self.logger.error('failed to kill %s (%d) [%s]' % (name, process_pid, traceback.format_exc())) res = False return res def setup(self): ''' Called at the beginning of a fuzzing session. Will start the server up. ''' self._stop_process() self._start_server_thread() def teardown(self): self._stop_process() self._process = None super(WinAppDbgController, self).teardown() def pre_test(self, test_number): super(WinAppDbgController, self).pre_test(test_number) if not self._is_victim_alive(): self.logger.error('victim is dead, restarting...') # self.report.failed('server is down during pre_test - failure it probably from previous test (%d)' % (test_number-1)) self._restart() self._crash_event_complete.set() else: self.logger.debug('victim is alive (pid=%d)' % self._pid) def post_test(self): self.logger.debug('in') time.sleep(1) self.logger.debug('after sleep') res = self._crash_event_complete.wait() self.logger.debug('after wait') if not res: self.report.failed('incomplete crash detected') super(WinAppDbgController, self).post_test() self.logger.debug('out') def _stop_process(self): ''' Stop the process (if running) ''' return self._kill_all_processes() def _stop_process_old(self): ''' :return: True if process was killed, False otherwise ''' if self._is_victim_alive(): self._process.kill() time.sleep(0.5) if self._is_victim_alive(): self._process.kill() time.sleep(0.5) if self._is_victim_alive(): raise Exception('Failed to kill client process') self._debug.stop() return True else: self._debug.stop() return False def _restart(self): ''' restart the process ''' self._stop_process() self.server_thread.join(1) time.sleep(3) self._server_is_up.clear() self._start_server_thread() def _is_victim_alive(self): ''' check if process running ''' if self._process: self.logger.debug('process pid: %d' % self._pid) is_alive = self._process.is_alive() is_debugee_started = self._debug.is_debugee_started(self._pid) self.logger.debug('is_alive = %s' % is_alive) self.logger.debug('is_debugee_started = %s' % is_debugee_started) return (is_alive and is_debugee_started) else: self.logger.debug('_process is None') return False
# Specify a dictionary here words = open("dic.txt", "r").readlines() print "[+] Words Loaded: ", len(words) # Specify a key file keyfile = "pwsafe.key" try: debug = Debug() # Start a new process for debugging # Allocate 20 bytes for the words if os.path.isfile(keyfile): print "[+] Keyfile Loaded: '" + keyfile + "'" aProcess = debug.execv(["KeePass.exe", "Database.kdb", "-keyfile:" + keyfile, "-pw:".ljust(WORD_SIZE + 4)]) else: print "[+] Specified keyfile '" + keyfile + "' does not exist, ignoring argument" aProcess = debug.execv(["KeePass.exe", "Database.kdb", "-pw:".ljust(WORD_SIZE + 4)]) # Set the breakpoints debug.break_at(aProcess.get_pid(), 0x004DC395, action_0) debug.break_at(aProcess.get_pid(), 0x004D77A0, action_1) debug.break_at(aProcess.get_pid(), 0x004D6684, action_2) debug.break_at(aProcess.get_pid(), 0x004DC39A, action_3) # Wait for the debugee to finish t1 = time.clock() debug.loop() finally:
debug = Debug(myevent) try: if options.pid: debug.attach(options.pid) print_threads_and_modules(options.pid, debug) elif options.program: procs = list_processes(options.program) if len(procs) == 0: print "[E] no matching process" elif len(procs) == 1: debug.attach(procs[0].get_pid()) print_threads_and_modules(procs[0].get_pid(), debug) else: print "[E] ambigious" elif options.command: p = debug.execv(options.command, bFollow=True) # Wait for the debugee to finish debug.loop() # Stop the debugger finally: debug.stop() #report = open("%s/report.html" % dir, 'a') #if report: report.close()
class WinAppDbgTarget(ServerTarget): def __init__(self, name, process_path, process_args=[], sql_crash_db="sqlite:///crashes.sqlite", logger=None): """ :param name: name of the object :param process_path: path to the target executable :param process_args: arguments to pass to the process :param sql_crash_db: sql alchemy connection string to crash db (default:sqlite:///crashes.sqlite) :param logger: logger for this object (default: None) """ super(WinAppDbgTarget, self).__init__(name, logger) assert process_path assert (os.path.exists(process_path)) self._process_path = process_path self._process_name = os.path.basename(process_path) self._process_args = process_args self._process = None self._sql_crash_db = sql_crash_db self._crash_event_complete = threading.Event() self._server_is_up = threading.Event() self._crash_event_complete.set() self._debug = Debug(lambda x: _my_event_handler(self, x), bKillOnExit=True) def _debug_server(self): """ debugger thread """ try: self._process = None # Start a new process for debugging. argv = [self._process_path] + self._process_args self.logger.debug("debugger starting server: %s" % argv) try: self._process = self._debug.execv(argv, bFollow=True) except WindowsError: self.logger.error("debug_server received exception", traceback.fmt_exc()) self._pid = self._process.get_pid() self.logger.info("process started. pid=%d" % self._pid) # Wait for the debugee to finish. self._server_is_up.set() self._debug.loop() except: self.logger.error("Got an exception in _debug_server") self.logger.error(traceback.format_exc()) # Stop the debugger. finally: self._debug.stop() self._process = None self._pid = -1 self._crash_event_complete.set() def _start_server_thread(self): """ start the server thread """ self._server_is_up.clear() self.server_thread = FuncThread(self._debug_server) self.server_thread.start() self.logger.info("waiting for server to be up") self._server_is_up.wait() self.logger.info("server should be up") def _kill_all_processes(self): """ kill all processes with the same name :return: True if all matching processes were killed properly, False otherwise """ res = True # Lookup the currently running processes. self._debug.system.scan_processes() # For all processes that match the requested filename... for (process, name) in self._debug.system.find_processes_by_filename( self._process_name): process_pid = process.get_pid() self.logger.info("found process %s (%d) - trying to kill it" % (name, process_pid)) try: process.kill() self.logger.info("successfully killed %s (%d)" % (name, process_pid)) except: self.logger.error("failed to kill %s (%d) [%s]" % (name, process_pid, traceback.format_exc())) res = False return res def teardown(self): self._stop_process() self._process = None super(WinAppDbgTarget, self).teardown() def pre_test(self, test_number): super(WinAppDbgTarget, self).pre_test(test_number) if not self._is_victim_alive(): self.logger.error("victim is dead, restarting...") # self.report.failed("server is down during pre_test - failure it probably from previous test (%d)" % (test_number-1)) self._restart() self._crash_event_complete.set() else: self.logger.debug("victim is alive (pid=%d)" % self._pid) def post_test(self, test_num): self.logger.debug("in") time.sleep(1) self.logger.debug("after sleep") res = self._crash_event_complete.wait() self.logger.debug("after wait") if not res: self.report.failed("incomplete crash detected") super(WinAppDbgTarget, self).post_test(test_num) self.logger.debug("out") def _send_to_target(self, data): """ this is the key off windbgtarget :param data: data is the file path """ self.logger.info("send called") """ starting """ self._process_args = [] # this may need implement self._start_server_thread() def _stop_process(self): """ Stop the process (if running) """ return self._kill_all_processes() def _stop_process_old(self): """ :return: True if process was killed, False otherwise """ if self._is_victim_alive(): self._process.kill() time.sleep(0.5) if self._is_victim_alive(): self._process.kill() time.sleep(0.5) if self._is_victim_alive(): raise Exception("Failed to kill client process") self._debug.stop() return True else: self._debug.stop() return False def _restart(self): """ restart the process """ self._stop_process() # self.server_thread.join(1) time.sleep(3) self._server_is_up.clear() self._start_server_thread() def _is_victim_alive(self): """ check if process running """ if self._process: self.logger.debug("process pid: %d" % self._pid) is_alive = self._process.is_alive() is_debugee_started = self._debug.is_debugee_started(self._pid) self.logger.debug("is_alive = %s" % is_alive) self.logger.debug("is_debugee_started = %s" % is_debugee_started) return is_alive and is_debugee_started else: self.logger.debug("_process is None") return False
def StartFuzzer(self): # Main fuzzing loop print '[+]', datetime.now().strftime( "%Y:%m:%d::%H:%M:%S"), 'Using debugger : ', self.conf.DEBUGGER popup = PopUpKiller() thread.start_new_thread(popup.POPUpKillerThread, ()) thread.start_new_thread(self.TempDirCleanThread, ()) sleep(1) if self.OpenXMLFormat: print '[+]', datetime.now().strftime( "%Y:%m:%d::%H:%M:%S" ), 'Loading base files in memory from : ', self.conf.open_xml_office_files off = OfficeFileProcessor( UNPACKED_OFFICE_PATH=self.conf.open_xml_office_files, TEMP_PATH=self.conf.fuzztempfolder, oxml=True, PACKED_OFFICE_PATH=self.conf.packed_open_xml_office_files) ALL_DOCS_IN_MEMORY = off.LoadFilesInMemory() if (len(ALL_DOCS_IN_MEMORY)) == 0: print '[+]', datetime.now().strftime( "%Y:%m:%d::%H:%M:%S" ), 'No Open XML files provided as base file @', self.conf.open_xml_office_files exit() mut = Mutator( OpenXML=True, handlers=self.conf.FILE_FORMAT_HANDLERS, files_to_be_fuzzed=self.conf.FILES_TO_BE_FUZZED, no_of_files_to_be_fuzzed=self.conf.NUMBER_OF_FILES_TO_MUTATE, auto_id_file_type=self.conf.AUTO_IDENTIFY_INTERNAL_FILE_FORAMT, all_handlers=self.conf.ALL_MUTATION_SCRIPTS, all_inmem_docs=ALL_DOCS_IN_MEMORY ) # Passing file format handler and type print '[+]', datetime.now().strftime( "%Y:%m:%d::%H:%M:%S"), 'Starting Fuzzing' while 1: self.CurrentTestCaseName = choice(ALL_DOCS_IN_MEMORY.keys( )) # randomly select one office file loaded in memory. fuzzed_office_dict = mut.Mutate( ALL_DOCS_IN_MEMORY[self.CurrentTestCaseName], self.CurrentTestCaseName ) # fuzzed_office_dict only have xml strings in it. off.Pack2OfficeDoc2( self.CurrentTestCaseName, fuzzed_office_dict ) # Packed the fuzzed file back to wordfile. # TODO : One check can be implemented whether the files provided has proper handler application PROG_NAME = self.conf.APP_LIST[self.CurrentTestCaseName.split( '.')[-1]] # Find the program name arg = os.getcwd( ) + '\\' + self.conf.fuzztempfolder + '\\' + self.CurrentTestCaseName # if self.debugger == 'pydbg': dbg = pydbg() dbg.set_callback( EXCEPTION_ACCESS_VIOLATION, self.AccessViolationHandlerPYDBG) # AV handler dbg.set_callback(EXCEPTION_GUARD_PAGE, self.AccessViolationHandlerPYDBG ) # Guard Page AV handler thread.start_new_thread(self.StillRunningPYDBG, (dbg, )) # Killer Thread Started extra_arg = " ".join(self.extra_cmd_arg) dbg.load(PROG_NAME, extra_arg + ' ' + arg, show_window=True) dbg.run() if self.debugger == 'winappdbg': self.extra_cmd_arg = list( self.basic_cmd_arg) # Reset it to basic self.extra_cmd_arg.insert(0, PROG_NAME) self.extra_cmd_arg.insert(len(self.extra_cmd_arg), arg) debug = Debug(self.AccessViolationHandlerWINAPPDBG, bKillOnExit=True) proc = debug.execv(self.extra_cmd_arg) thread.start_new_thread(self.StillRunningWINAPPDBG, (proc, )) debug.loop() sleep(self.conf.FUZZ_LOOP_DELAY) else: print '[+] ' + datetime.now().strftime( "%Y:%m:%d::%H:%M:%S" ) + ' Loading Binary files files in memory from : ', self.conf.binary_office_files off = OfficeFileProcessor( UNPACKED_OFFICE_PATH=self.conf.binary_office_files, TEMP_PATH=self.conf.fuzztempfolder, oxml=False, PACKED_OFFICE_PATH=self.conf.packed_open_xml_office_files) ALL_DOCS_IN_MEMORY = off.LoadFilesInMemory() if (len(ALL_DOCS_IN_MEMORY)) == 0: print '[+]', datetime.now().strftime( "%Y:%m:%d::%H:%M:%S" ), ' No Binary files provided as base file @', self.conf.binary_office_files exit() mut = Mutator( OpenXML=False, handlers=self.conf.FILE_FORMAT_HANDLERS, files_to_be_fuzzed=self.conf.FILES_TO_BE_FUZZED, no_of_files_to_be_fuzzed=self.conf.NUMBER_OF_FILES_TO_MUTATE, auto_id_file_type=self.conf.AUTO_IDENTIFY_INTERNAL_FILE_FORAMT, all_handlers=self.conf.ALL_MUTATION_SCRIPTS, all_inmem_docs=ALL_DOCS_IN_MEMORY) print '[+]', datetime.now().strftime( "%Y:%m:%d::%H:%M:%S"), 'Starting Fuzzing' while 1: #print 'loop start ' self.CurrentTestCaseName = choice(ALL_DOCS_IN_MEMORY.keys( )) # randomly select one office file loaded in memory. fuzzed_office_bin = mut.Mutate( ALL_DOCS_IN_MEMORY[self.CurrentTestCaseName], self.CurrentTestCaseName ) # fuzzed_office_dict only have xml strings in it. off.Pack2OfficeDoc2(self.CurrentTestCaseName, fuzzed_office_bin) PROG_NAME = self.conf.APP_LIST[self.CurrentTestCaseName.split( '.')[-1]] # FInd the program name arg = os.getcwd( ) + '\\' + self.conf.fuzztempfolder + '\\' + self.CurrentTestCaseName # if self.debugger == 'pydbg': dbg = pydbg() dbg.set_callback( EXCEPTION_ACCESS_VIOLATION, self.AccessViolationHandlerPYDBG) # AV handler dbg.set_callback(EXCEPTION_GUARD_PAGE, self.AccessViolationHandlerPYDBG ) # Guard Page AV handler thread.start_new_thread(self.StillRunningPYDBG, (dbg, )) # Killer Thread Started extra_arg = " ".join(self.extra_cmd_arg) dbg.load(PROG_NAME, extra_arg + ' ' + arg, show_window=True) dbg.run() if self.debugger == 'winappdbg': self.extra_cmd_arg = list( self.basic_cmd_arg) # Reset it to basic self.extra_cmd_arg.insert(0, PROG_NAME) # Add progname self.extra_cmd_arg.insert(len(self.extra_cmd_arg), arg) debug = Debug(self.AccessViolationHandlerWINAPPDBG, bKillOnExit=True) proc = debug.execv(self.extra_cmd_arg) thread.start_new_thread(self.StillRunningWINAPPDBG, (proc, )) debug.loop() sleep(self.conf.FUZZ_LOOP_DELAY)
print "CreateFileW: %s" % (fname) # The post_ functions are called upon exiting the API def post_CreateFileW(self, event, retval): if retval: print 'Suceeded (handle value: %x)' % (retval) else: print 'Failed!' if __name__ == "__main__": if len(sys.argv) < 2 or not os.path.isfile(sys.argv[1]): print "\nUsage: %s <File to monitor> [arg1, arg2, ...]\n" % sys.argv[0] sys.exit() # Instance a Debug object, passing it the MyEventHandler instance debug = Debug( MyEventHandler() ) try: # Start a new process for debugging p = debug.execv(sys.argv[1:], bFollow=True) # Wait for the debugged process to finish debug.loop() # Stop the debugger finally: debug.stop()