def __init__(self, connection_string, set_initial_bp=True, event_callbacks_sink=None, output_callbacks_sink=None, dbg_eng_dll_path=None, symbols_path=None): PyDbgEng.__init__(self, event_callbacks_sink, output_callbacks_sink, dbg_eng_dll_path, symbols_path) self.force_quit_flag = False self.is_deleted = False # sanity check before setting initial bp if (event_callbacks_sink != None and isinstance(event_callbacks_sink, IDebugEventCallbacksSink) and set_initial_bp): if (not (event_callbacks_sink.GetInterestMask() & DbgEng.DEBUG_EVENT_EXCEPTION)): raise DebuggerException( "requested initial break, but 'exception' method is not implemented." ) self.dbg_eng_log( "KernelAttacher.__init__: setting engine options with initial break" ) self.idebug_control.SetEngineOptions( DbgEng.DEBUG_ENGOPT_INITIAL_BREAK) # attach to kernel self.dbg_eng_log( "KernelAttacher.__init__: about to attach to kernel with connection string %s" % connection_string) self.idebug_client.AttachKernel( ConnectOptions=connection_string, Flags=DbgEng.DEBUG_ATTACH_KERNEL_CONNECTION)
def add(self, dbg, address, num_args, entry_hook=None, exit_hook=None): if (entry_hook == None and exit_hook == None): raise DebuggerException("no entry or exit hooks") # create a new hook instance and activate it. h = hook(address, num_args, entry_hook, exit_hook) h.hook(dbg) self.hooks.append(h)
def read_virtual_memory(self, address, length): read_buf = create_string_buffer(length) bytes_read = c_ulong(0) self.idebug_data_spaces.ReadVirtual(address, read_buf, length, byref(bytes_read)) if (bytes_read.value != length): raise DebuggerException( "read_virtual_memory(): ReadVirtual() failed") return read_buf.raw
def create_idebug_client(dbgeng_dll): # DebugCreate() prototype debug_create_prototype = WINFUNCTYPE( HRESULT, POINTER(IID), POINTER(POINTER(DbgEng.IDebugClient))) debug_create_func = debug_create_prototype(("DebugCreate", dbgeng_dll)) # call DebugCreate() idebug_client = POINTER(DbgEng.IDebugClient)() idebug_client_ptr = POINTER(POINTER( DbgEng.IDebugClient))(idebug_client) hr = debug_create_func(DbgEng.IDebugClient._iid_, idebug_client_ptr) if (hr != S_OK): raise DebuggerException("DebugCreate() failed with %x" % hr) # return debug_client of type POINTER(DbgEng.IDebugClient) return idebug_client
def event_loop_with_user_callback(self, user_callback, user_callback_pool_interval_ms): if (user_callback_pool_interval_ms <= 0): raise DebuggerException( "UserModeSession.event_loop_with_user_callback(): invalid user_callback_pool_interval_ms" ) while (True): if (self.wait_for_event(user_callback_pool_interval_ms) == False): self.dbg_eng_log( "UserModeSession.event_loop_with_user_callback: wait_for_event() done. breaking loop." ) break # call user callback if (user_callback(self) == True): # user requested to quit event loop self.dbg_eng_log( "UserModeSession.event_loop_with_user_callback: user callback returned true. breaking loop." ) break
def event_loop_with_quit_event(self, quit_event): ''' in kernel debugging session IDebugControl.WaitForEvent() must be called with an 'infinite' timeout value. this is why we have to create thread that checks the given given quit event. once set it will force a debugger break. ''' if (self.is_deleted): raise DebuggerException("called when object is deleted") # sanity check on quit_event #if (not isinstance(quit_event, threading._Event)): # raise DebuggerException("invalid type for quit event") # is already set? if (quit_event.is_set()): # no job for us return # create abort event abort_quit_waiter_event = Event() # start quit thread quit_waiter = KernelAttacher.QuitEventWaiter( quit_event=quit_event, abort_event=abort_quit_waiter_event, top=self) # event loop self.__event_loop_with_forced_break_check(quit_event) # stop quit waiter thread self.dbg_eng_log( "KernelAttacher.event_loop: waiting for quit_waiter to end") abort_quit_waiter_event.set() quit_waiter.join() # dont wait for garbage collection, and force delete on self self.__del__()
def get_dbg_eng_dir_from_registry(): import win32api, win32con try: hkey = win32api.RegOpenKey(win32con.HKEY_CURRENT_USER, "Software\\Microsoft\\DebuggingTools") except: # Lets try a few common places before failing. pgPaths = [ "c:\\", os.environ["SystemDrive"] + "\\", os.environ["ProgramFiles"], ] if "ProgramW6432" in os.environ: pgPaths.append(os.environ["ProgramW6432"]) if "ProgramFiles(x86)" in os.environ: pgPaths.append(os.environ["ProgramFiles(x86)"]) dbgPaths = [ "Debuggers", "Debugger", "Debugging Tools for Windows", "Debugging Tools for Windows (x64)", "Debugging Tools for Windows (x86)", ] for p in pgPaths: for d in dbgPaths: testPath = os.path.join(p, d) if os.path.exists(testPath): return testPath raise DebuggerException( "Failed to locate Microsoft Debugging Tools in the registry. Please make sure its installed" ) val, type = win32api.RegQueryValueEx(hkey, "WinDbg") return val
def get_current_tid(self): raise DebuggerException( "PyDbgEng.get_current_tid() must be implemented")
def get_handle_data(self, handle): raise DebuggerException( "PyDbgEng.get_handle_data() must be implemented")
def event_loop_with_quit_event(self, quit_event): print "%%% About to throw exception: event_loop_with_quit_event %%%" raise DebuggerException( "PyDbgEng.event_loop_with_quit_event() must be implemented")
def event_loop_with_user_callback(self, user_callback, user_callback_pool_interval_ms): raise DebuggerException( "PyDbgEng.event_loop_with_user_callback() must be implemented")
def __init__(self, event_callbacks_sink=None, output_callbacks_sink=None, dbg_eng_dll_path=None, symbols_path=None): import sys self.dbg_eng_log = lambda msg: None # sys.stdout.write("DBGENG_LOG> " + msg + "\n") #self.dbg_eng_log = lambda msg: sys.stdout.write("> " + msg + "\n") if (dbg_eng_dll_path == None): finder = DbgEngDllFinder() dbg_eng_dll_path = finder.get_dbg_eng_dir_from_registry() self.dbg_eng_log("PyDbgEng.__init__: got dbg_eng_dll_path %s" % dbg_eng_dll_path) # load dbgeng dlls self.dbg_eng_log("PyDbgEng.__init__: loading dbgeng dlls") self.dbghelp_dll = windll.LoadLibrary(dbg_eng_dll_path + "\\dbghelp.dll") self.dbgeng_dll = windll.LoadLibrary(dbg_eng_dll_path + "\\dbgeng.dll") # create main interfaces self.dbg_eng_log("PyDbgEng.__init__: creating interfaces") creator = IDebugClientCreator() try: self.idebug_client = creator.create_idebug_client(self.dbgeng_dll) except: # Try registering it import os, sys os.system("%s %s -regserver" % (sys.executable, self.findDbgEngEvent())) self.idebug_client = creator.create_idebug_client(self.dbgeng_dll) pass self.idebug_control = self.idebug_client.QueryInterface( interface=DbgEng.IDebugControl) self.idebug_data_spaces = self.idebug_client.QueryInterface( interface=DbgEng.IDebugDataSpaces3) self.idebug_registers = self.idebug_client.QueryInterface( interface=DbgEng.IDebugRegisters) self.idebug_symbols = self.idebug_client.QueryInterface( interface=DbgEng.IDebugSymbols) self.idebug_system_objects = self.idebug_client.QueryInterface( interface=DbgEng.IDebugSystemObjects) if (symbols_path != None): self.idebug_symbols.SetSymbolPath(symbols_path) # create event sink if (event_callbacks_sink != None): # sanity check on sink if (not isinstance(event_callbacks_sink, IDebugEventCallbacksSink)): raise DebuggerException( "Invalid sink object (event_callbacks_sink)") self.event_callbacks_sink = event_callbacks_sink self.dbg_eng_log( "PyDbgEng.__init__: registering event callbacks proxy") # Updated code to work with latest comtypes and remove native code needs # Eddington 5/3/2008 PyDbgEng.fuzzyWuzzy = self # HACK! from DbgEngEvent import DbgEngEventCallbacks event_proxy = DbgEngEventCallbacks() event_proxy.IUnknown_AddRef(event_proxy) self.new_event_callbacks = event_proxy self.old_event_callbacks = self.idebug_client.GetEventCallbacks() self.idebug_client.SetEventCallbacks(Callbacks=event_proxy) # create output sink if (output_callbacks_sink != None): # sanity check on sink if (not isinstance(output_callbacks_sink, IDebugOutputCallbacksSink)): raise DebuggerException( "Invalid sink object (output_callbacks_sink)") self.dbg_eng_log( "PyDbgEng.__init__: registering output callbacks proxy") # Updated code to work with latest comtypes and remove native code needs # Eddington 5/3/2008 PyDbgEng.fuzzyWuzzy = self # HACK! from DbgEngEvent import DbgEngEventCallbacks output_proxy = DbgEngEventCallbacks() output_proxy.IUnknown_AddRef(output_proxy) self.new_output_callbacks = output_proxy self.output_callbacks_sink = output_callbacks_sink self.old_event_callbacks = self.idebug_client.GetEventCallbacks() self.idebug_client.SetOutputCallbacks(Callbacks=output_proxy)
def GetInterestMask(self): raise DebuggerException( "IDebugEventCallbacksSink.GetInterestMask() must be implemented")