From d24e62e319ebdbfb56442db70030fa8b9da1d011 Mon Sep 17 00:00:00 2001 From: Clement Rouault Date: Fri, 19 May 2017 15:39:32 +0200 Subject: [PATCH] Add PrintBP + few fix in Debugger + simple string-address resolution in localdebugger --- TODO | 8 ++++++++ windows/debug/breakpoints.py | 12 ++++++++++-- windows/debug/debugger.py | 29 ++++++++++++++++------------- windows/debug/localdbg.py | 35 +++++++++++++++++++++++++++++++---- 4 files changed, 65 insertions(+), 19 deletions(-) diff --git a/TODO b/TODO index 8bb2d03..697fdf4 100644 --- a/TODO +++ b/TODO @@ -20,6 +20,14 @@ TODO: - if I have a ntdll32 and ntdll64: both would have the same name in the list.. + - Il y a un truc fucked-up avec le add_bp(target=XXX) + - j'attends a avoir un thread/process mais je fait des check sur TID/PID.. + - Ecrire un test et fix.. + + - windows.alpc | windows.rpc + - Clean + doc + samples + + - remotectypes - pretty sur I can get rid of PointerToStruct64/PointerToStruct32 diff --git a/windows/debug/breakpoints.py b/windows/debug/breakpoints.py index 4ab485f..b007d15 100644 --- a/windows/debug/breakpoints.py +++ b/windows/debug/breakpoints.py @@ -70,7 +70,7 @@ class X64ArgumentRetriever(object): def get_arg(self, nb, proc, thread): if nb < len(self.REG_ARGS): return getattr(thread.context, self.REG_ARGS[nb]) - return proc.read_dword(thread.context.sp + 8 + (8 * nb)) + return proc.read_qword(thread.context.sp + 8 + (8 * nb)) ## Behaviour breakpoint ! class FunctionParamDumpBP(Breakpoint): @@ -157,4 +157,12 @@ class FunctionBP(FunctionCallBP, FunctionParamDumpBP): - Extract the arguments of the functions - Break at the return of the function - """ \ No newline at end of file + """ + +class PrintBP(Breakpoint): + def __init__(self, addr, format): + super(PrintBP, self).__init__(addr) + self.format = format + + def trigger(self, dbg, exc): + print(self.format.format(dbg=dbg, exc=exc, ctx=dbg.current_thread.context)) \ No newline at end of file diff --git a/windows/debug/debugger.py b/windows/debug/debugger.py index 3fee70f..955662e 100644 --- a/windows/debug/debugger.py +++ b/windows/debug/debugger.py @@ -133,7 +133,7 @@ class Debugger(object): self.current_process = None self.current_thread = None - if target.pid == self.target.pid: + if self.target and target.pid == self.target.pid: self.target = None windows.winproxy.DebugActiveProcessStop(target.pid) @@ -254,7 +254,7 @@ class Debugger(object): def _setup_breakpoint_BP(self, bp, target): if not isinstance(target, WinProcess): - raise ValueError("SETUP STANDARD_BP on {0}".format(target)) + raise ValueError("Cannot setup STANDARD_BP on {0}".format(target)) addr = self._resolve(bp.addr, target) if addr is None: @@ -621,12 +621,12 @@ class Debugger(object): if self.current_process.bitness == 32 and pe.bitness == 64: name_sufix = "64" - if not load_dll.lpImageName: - return pe.export_name + name_sufix - try: - addr = self.current_process.read_ptr(load_dll.lpImageName) - except: - addr = None + addr = None + if load_dll.lpImageName: + try: + addr = self.current_process.read_ptr(load_dll.lpImageName) + except: + pass if not addr: pe = windows.pe_parse.GetPEFile(load_dll.lpBaseOfDll, self.current_process) @@ -659,6 +659,7 @@ class Debugger(object): self.current_process = WinProcess._from_handle(proc_handle.value) self.current_thread = WinThread._from_handle(thread_handle.value) + dbgprint("New process: {0}".format(self.current_process), "DBG") self.threads[self.current_thread.tid] = self.current_thread self._explicit_single_step[self.current_thread.tid] = False @@ -710,8 +711,10 @@ class Debugger(object): thread_handle = HANDLE() cp_handle = windows.current_process.handle winproxy.DuplicateHandle(cp_handle, create_thread.hThread, cp_handle, ctypes.byref(thread_handle), dwOptions=DUPLICATE_SAME_ACCESS) - self.current_thread = WinThread._from_handle(thread_handle.value) - self.threads[self.current_thread.tid] = self.current_thread + new_thread = WinThread._from_handle(thread_handle.value) + self.threads[new_thread.tid] = new_thread + # The new thread is on the thread pool: we can now update the debugger state + self._update_debugger_state(debug_event) self._explicit_single_step[self.current_thread.tid] = False self._breakpoint_to_reput[self.current_thread.tid] = [] self._hardware_breakpoint[self.current_thread.tid] = {} @@ -818,10 +821,10 @@ class Debugger(object): elif target is not None: # Check that targets are accepted if target not in self.processes.values() + self.threads.values(): - if target == self.target: # Original target (that have not been lauched yet) + # if target == self.target: # Original target (that have not been lauched yet) return self.add_pending_breakpoint(bp, target) - else: - raise ValueError("Unknown target {0}".format(target)) + # else: + # raise ValueError("Unknown target {0}".format(target)) return self._setup_breakpoint(bp, target) def del_bp(self, bp, targets=None): diff --git a/windows/debug/localdbg.py b/windows/debug/localdbg.py index 7c7fe18..559c98d 100644 --- a/windows/debug/localdbg.py +++ b/windows/debug/localdbg.py @@ -32,6 +32,7 @@ class LocalDebugger(object): self.veh_depth = 0 self.current_exception = None self.exceptions_stack = [None] + self.current_process = windows.current_process @contextmanager def NewCurrentException(self, exc): @@ -64,6 +65,31 @@ class LocalDebugger(object): self._reput_breakpoint[windows.current_thread.tid] = self.breakpoints[addr], single_step return self.single_step() + def _local_resolve(self, addr): + if not isinstance(addr, basestring): + return addr + dll, api = addr.split("!") + dll = dll.lower() + modules = {m.name[:-len(".dll")] if m.name.endswith(".dll") else m.name : m for m in windows.current_process.peb.modules} + mod = None + if dll in modules: + mod = [modules[dll]] + if not mod: + return None + # TODO: optim exports are the same for whole system (32 vs 64 bits) + # I don't have to reparse the exports each time.. + # Try to interpret api as an int + try: + api_int = int(api, 0) + return mod[0].baseaddr + api_int + except ValueError: + pass + exports = mod[0].pe.exports + if api not in exports: + dbgprint("Error resolving <{0}> in local process".format(addr, target), "DBG") + raise ValueError("Unknown API <{0}> in DLL {1}".format(api, dll)) + return exports[api] + def callback(self, exc): with self.NewCurrentException(exc): return self.handle_exception(exc) @@ -134,10 +160,11 @@ class LocalDebugger(object): raise NotImplementedError("Unknow BP type {0}".format(bp.type)) if targets is not None: raise ValueError("LocalDebugger: STANDARD_BP doest not support targets {0}".format(targets)) - self.breakpoints[bp.addr] = bp - self._memory_save[bp.addr] = windows.current_process.read_memory(bp.addr, 1) - with windows.utils.VirtualProtected(bp.addr, 1, PAGE_EXECUTE_READWRITE): - windows.current_process.write_memory(bp.addr, "\xcc") + addr = self._local_resolve(bp.addr) + self.breakpoints[addr] = bp + self._memory_save[addr] = windows.current_process.read_memory(addr, 1) + with windows.utils.VirtualProtected(addr, 1, PAGE_EXECUTE_READWRITE): + windows.current_process.write_memory(addr, "\xcc") return def add_bp_hxbp(self, bp, targets=None):