diff --git a/windows/debug/__init__.py b/windows/debug/__init__.py new file mode 100644 index 0000000..da6b983 --- /dev/null +++ b/windows/debug/__init__.py @@ -0,0 +1,3 @@ +from .debugger import Debugger, HXBreakpoint +from .localdbg import LocalDebugger +from .breakpoints import * \ No newline at end of file diff --git a/windows/debug/breakpoints.py b/windows/debug/breakpoints.py new file mode 100644 index 0000000..ac642ec --- /dev/null +++ b/windows/debug/breakpoints.py @@ -0,0 +1,55 @@ +from windows.generated_def.winstructs import * +from windows.generated_def import windef + +from windows.winobject.process import WinProcess, WinThread + + +STANDARD_BP = "BP" +HARDWARE_EXEC_BP = "HXBP" +MEMORY_BREAKPOINT = "MEMBP" + +class Breakpoint(object): + """An standard (Int3) breakpoint (type == ``STANDARD_BP``)""" + type = STANDARD_BP # REAL BP + def __init__(self, addr): + self.addr = addr + + def apply_to_target(self, target): + return isinstance(target, WinProcess) + + def trigger(self, dbg, exception): + """Called when breakpoint is hit""" + pass + + +class ProxyBreakpoint(Breakpoint): + def __init__(self, target, addr, type): + self.target = target + self.addr = addr + self.type = type + + def trigger(self, dbg, exception): + return self.target(dbg, exception) + + +class HXBreakpoint(Breakpoint): + """An hardware-execution breakpoint (type == ``HARDWARE_EXEC_BP``)""" + type = HARDWARE_EXEC_BP + + def apply_to_target(self, target): + return isinstance(target, WinThread) + +class MemoryBreakpoint(Breakpoint): + type = MEMORY_BREAKPOINT + + DEFAULT_PROTECT = PAGE_READONLY + DEFAULT_SIZE = 0x1000 + def __init__(self, addr, size=None, prot=None): + super(MemoryBreakpoint, self).__init__(addr) + self.size = size if size is not None else self.DEFAULT_SIZE + self.protect = size if prot is not None else self.DEFAULT_PROTECT + + + def trigger(self, dbg, exception): + """Called when breakpoint is hit""" + pass \ No newline at end of file diff --git a/windows/debug.py b/windows/debug/debugger.py similarity index 69% rename from windows/debug.py rename to windows/debug/debugger.py index 26891bd..de0797a 100644 --- a/windows/debug.py +++ b/windows/debug/debugger.py @@ -11,13 +11,12 @@ from windows.winobject.process import WinProcess, WinThread from windows.dbgprint import dbgprint from windows import winproxy from windows.generated_def.winstructs import * -from .generated_def import windef - +from windows.generated_def import windef +from .breakpoints import * from windows.winobject.exception import VectoredException - STANDARD_BP = "BP" HARDWARE_EXEC_BP = "HXBP" MEMORY_BREAKPOINT = "MEMBP" @@ -155,7 +154,6 @@ class Debugger(object): for target in targets: return _setup_method(bp, target) - def _setup_breakpoint_BP(self, bp, target): if not isinstance(target, WinProcess): raise ValueError("SETUP STANDARD_BP on {0}".format(target)) @@ -168,6 +166,15 @@ class Debugger(object): target.write_memory(addr, "\xcc") return True + def _remove_breakpoint_BP(self, bp, target): + if not isinstance(target, WinProcess): + raise ValueError("SETUP STANDARD_BP on {0}".format(target)) + addr = self._resolve(bp.addr, target) + target.write_memory(addr, self._memory_save[target.pid][addr]) + del self._memory_save[target.pid][addr] + del self.breakpoints[target.pid][addr] + return True + def _setup_breakpoint_HXBP(self, bp, target): if not isinstance(target, WinThread): raise ValueError("SETUP HXBP_BP on {0}".format(target)) @@ -288,7 +295,9 @@ class Debugger(object): thread.set_context(ctx) continue_flag = self._dispatch_breakpoint(exception, excp_addr) self._explicit_single_step[self.current_thread.tid] = self.current_thread.context.EEFlags.TF - self._pass_breakpoint(excp_addr) + if excp_addr in self.breakpoints[self.current_process.pid]: + # Setup BP if not suppressed + self._pass_breakpoint(excp_addr) return continue_flag return self.on_exception(exception) @@ -416,7 +425,7 @@ class Debugger(object): self._setup_pending_breakpoints_new_process(self.current_process) self._setup_pending_breakpoints_new_thread(self.current_thread) return self.on_create_process(create_process) - # TODO: clode hFile + # TODO: close hFile def _handle_exit_process(self, debug_event): """Handle EXIT_PROCESS_DEBUG_EVENT""" @@ -530,6 +539,23 @@ class Debugger(object): raise ValueError("Unknown target {0}".format(target)) return self._setup_breakpoint(bp, target) + def del_bp(self, bp, targets=None): + if targets is not None: + raise NotImplementedError("TODO: DEL BP with targets ?") + if bp.type != STANDARD_BP: + raise NotImplementedError("Remove non-STANDARD_BP breakpoint") + + _remove_method = getattr(self, "_remove_breakpoint_" + bp.type) + if targets is None: + if bp.type in [STANDARD_BP, MEMORY_BREAKPOINT]: #TODO: better.. + targets = self.processes.values() + else: + targets = self.threads.values() + else: + targets = [target] + for target in targets: + return _remove_method(bp, target) + def single_step(self): t = self.current_thread ctx = t.context @@ -595,287 +621,3 @@ class Debugger(object): -class Breakpoint(object): - """An standard (Int3) breakpoint (type == ``STANDARD_BP``)""" - type = STANDARD_BP # REAL BP - def __init__(self, addr): - self.addr = addr - - def apply_to_target(self, target): - return isinstance(target, WinProcess) - - def trigger(self, dbg, exception): - """Called when breakpoint is hit""" - pass - - -class ProxyBreakpoint(Breakpoint): - def __init__(self, target, addr, type): - self.target = target - self.addr = addr - self.type = type - - def trigger(self, dbg, exception): - return self.target(dbg, exception) - - -class HXBreakpoint(Breakpoint): - """An hardware-execution breakpoint (type == ``HARDWARE_EXEC_BP``)""" - type = HARDWARE_EXEC_BP - - def apply_to_target(self, target): - return isinstance(target, WinThread) - -class MemoryBreakpoint(Breakpoint): - type = MEMORY_BREAKPOINT - - DEFAULT_PROTECT = PAGE_READONLY - DEFAULT_SIZE = 0x1000 - def __init__(self, addr, size=None, prot=None): - super(MemoryBreakpoint, self).__init__(addr) - self.size = size if size is not None else self.DEFAULT_SIZE - self.protect = size if prot is not None else self.DEFAULT_PROTECT - - - def trigger(self, dbg, exception): - """Called when breakpoint is hit""" - pass - - -class LocalDebugger(object): - """A debugger interface around :func:`AddVectoredExceptionHandler`""" - def __init__(self): - self.breakpoints = {} - self._memory_save = {} - self._reput_breakpoint = {} - self._hxbp_breakpoint = defaultdict(dict) - - self.callback_vectored = winexception.VectoredException(self.callback) - winproxy.AddVectoredExceptionHandler(0, self.callback_vectored) - self.setup_hxbp_callback_vectored = winexception.VectoredException(self.setup_hxbp_callback) - self.hxbp_info = None - self.code = windows.native_exec.create_function("\xcc\xc3", [PVOID]) - self.veh_depth = 0 - self.current_exception = None - self.exceptions_stack = [None] - - @contextmanager - def NewCurrentException(self, exc): - try: - self.exceptions_stack.append(exc) - self.current_exception = exc - self.veh_depth += 1 - yield exc - finally: - self.exceptions_stack.pop() - self.current_exception = self.exceptions_stack[-1] - self.veh_depth -= 1 - - def get_exception_code(self): - """Return ExceptionCode of current exception""" - return self.current_exception[0].ExceptionRecord[0].ExceptionCode - - def get_exception_context(self): - """Return context of current exception""" - return self.current_exception[0].ContextRecord[0] - - def single_step(self): - """Make the current thread to single step""" - self.get_exception_context().EEFlags.TF = 1 - return windef.EXCEPTION_CONTINUE_EXECUTION - - def _pass_breakpoint(self, addr, single_step): - with windows.utils.VirtualProtected(addr, 1, PAGE_EXECUTE_READWRITE): - windows.current_process.write_memory(addr, self._memory_save[addr]) - self._reput_breakpoint[windows.current_thread.tid] = self.breakpoints[addr], single_step - return self.single_step() - - def callback(self, exc): - with self.NewCurrentException(exc): - return self.handle_exception(exc) - - def handle_exception(self, exc): - exp_code = self.get_exception_code() - context = self.get_exception_context() - exp_addr = context.pc - - if exp_code == EXCEPTION_BREAKPOINT and exp_addr in self.breakpoints: - res = self.breakpoints[exp_addr].trigger(self, exc) - single_step = self.get_exception_context().EEFlags.TF # single step activated by breakpoint - if exp_addr in self.breakpoints: # Breakpoint deleted itself ? - return self._pass_breakpoint(exp_addr, single_step) - return EXCEPTION_CONTINUE_EXECUTION - - if exp_code == EXCEPTION_SINGLE_STEP and windows.current_thread.tid in self._reput_breakpoint: - bp, single_step = self._reput_breakpoint[windows.current_thread.tid] - 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") - del self._reput_breakpoint[windows.current_thread.tid] - if single_step: - return self.on_exception(exc) - return windef.EXCEPTION_CONTINUE_EXECUTION - elif exp_code == EXCEPTION_SINGLE_STEP and exp_addr in self._hxbp_breakpoint[windows.current_thread.tid]: - res = self._hxbp_breakpoint[windows.current_thread.tid][exp_addr].trigger(self, exc) - context.EEFlags.RF = 1 - return EXCEPTION_CONTINUE_EXECUTION - return self.on_exception(exc) - - def on_exception(self, exc): - """Called on exception""" - if not self.get_exception_code() in winexception.exception_name_by_value: - return windef.EXCEPTION_CONTINUE_SEARCH - return windef.EXCEPTION_CONTINUE_EXECUTION - - def del_bp(self, bp): - if bp.type == STANDARD_BP: - with windows.utils.VirtualProtected(bp.addr, 1, PAGE_EXECUTE_READWRITE): - windows.current_process.write_memory(bp.addr, self._memory_save[bp.addr]) - del self._memory_save[bp.addr] - del self.breakpoints[bp.addr] - return - if bp.type == HARDWARE_EXEC_BP: - for tid in self._hxbp_breakpoint: - if bp.addr in self._hxbp_breakpoint[tid] and self._hxbp_breakpoint[tid][bp.addr] == bp: - if tid == windows.current_thread.tid: - self.remove_hxbp_self_thread(bp.addr) - else: - self.remove_hxbp_other_thread(bp.addr) - del self._hxbp_breakpoint[tid][bp.addr] - #print("Need to remove {0} in {1}".format(self._hxbp_breakpoint[tid][bp.addr], tid)) - return - raise NotImplementedError("Unknow BP type {0}".format(bp.type)) - - def add_bp(self, bp, targets=None): - """Add a breakpoint, bp is a "class:`Breakpoint` - - If the ``bp`` type is ``STANDARD_BP``, target must be None. - - If the ``bp`` type is ``HARDWARE_EXEC_BP``, target can be None (all threads), or some threads of the process - """ - if bp.type == HARDWARE_EXEC_BP: - return self.add_bp_hxbp(bp, targets) - if bp.type != STANDARD_BP: - 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") - return - - def add_bp_hxbp(self, bp, targets=None): - if bp.type != HARDWARE_EXEC_BP: - raise NotImplementedError("Add non standard-BP in LocalDebugger") - if targets is None: - targets = windows.current_process.threads - for thread in targets: - if thread.owner.pid != windows.current_process.pid: - raise ValueError("Cannot add HXBP to target in remote process {0}".format(thread)) - if thread.tid == windows.current_thread.tid: - self.setup_hxbp_self_thread(bp.addr) - else: - self.setup_hxbp_other_thread(bp.addr, thread) - self._hxbp_breakpoint[thread.tid][bp.addr] = bp - - def setup_hxbp_callback(self, exc): - with self.NewCurrentException(exc): - exp_code = self.get_exception_code() - context = self.get_exception_context() - exp_addr = context.pc - hxbp_used = self.setup_hxbp_in_context(context, self.data) - windows.current_process.write_memory(exp_addr, "\x90") - # Raising in the VEH is a bad idea.. - # So better give the information to triggerer.. - if hxbp_used is not None: - self.get_exception_context().Eax = exp_addr - else: - self.get_exception_context().Eax = 0 - return windef.EXCEPTION_CONTINUE_EXECUTION - - def remove_hxbp_callback(self, exc): - with self.NewCurrentException(exc): - exp_code = self.get_exception_code() - context = self.get_exception_context() - exp_addr = context.pc - hxbp_used = self.remove_hxbp_in_context(context, self.data) - windows.current_process.write_memory(exp_addr, "\x90") - # Raising in the VEH is a bad idea.. - # So better give the information to triggerer.. - if hxbp_used is not None: - self.get_exception_context().Eax = exp_addr - else: - self.get_exception_context().Eax = 0 - return windef.EXCEPTION_CONTINUE_EXECUTION - - def setup_hxbp_in_context(self, context, addr): - for i in range(4): - is_used = getattr(context.EDr7, "L" + str(i)) - empty_drx = str(i) - if not is_used: - context.EDr7.GE = 1 - context.EDr7.LE = 1 - setattr(context.EDr7, "L" + empty_drx, 1) - setattr(context, "Dr" + empty_drx, addr) - return i - return None - - def remove_hxbp_in_context(self, context, addr): - for i in range(4): - target_drx = str(i) - is_used = getattr(context.EDr7, "L" + str(i)) - draddr = getattr(context, "Dr" + target_drx) - - if is_used and draddr == addr: - setattr(context.EDr7, "L" + target_drx, 0) - setattr(context, "Dr" + target_drx, 0) - return i - return None - - def setup_hxbp_self_thread(self, addr): - if self.current_exception is not None: - x = self.setup_hxbp_in_context(self.get_exception_context(), addr) - if x is None: - raise ValueError("Could not setup HXBP") - return - - self.data = addr - with winexception.VectoredExceptionHandler(1, self.setup_hxbp_callback): - x = self.code() - if x is None: - raise ValueError("Could not setup HXBP") - windows.current_process.write_memory(x, "\xcc") - return - - def setup_hxbp_other_thread(self, addr, thread): - thread.suspend() - ctx = thread.context - x = self.setup_hxbp_in_context(ctx, addr) - if x is None: - raise ValueError("Could not setup HXBP in {0}".format(thread)) - thread.set_context(ctx) - thread.resume() - - def remove_hxbp_self_thread(self, addr): - if self.current_exception is not None: - x = self.remove_hxbp_in_context(self.get_exception_context(), addr) - if x is None: - raise ValueError("Could not setup HXBP") - return - self.data = addr - with winexception.VectoredExceptionHandler(1, self.remove_hxbp_callback): - x = self.code() - if x is None: - raise ValueError("Could not remove HXBP") - windows.current_process.write_memory(x, "\xcc") - return - - def remove_hxbp_other_thread(self, addr, thread): - thread.suspend() - ctx = thread.context - x = self.remove_hxbp_in_context(ctx, addr) - if x is None: - raise ValueError("Could not setup HXBP in {0}".format(thread)) - thread.set_context(ctx) - thread.resume() \ No newline at end of file diff --git a/windows/debug/localdbg.py b/windows/debug/localdbg.py new file mode 100644 index 0000000..00767e1 --- /dev/null +++ b/windows/debug/localdbg.py @@ -0,0 +1,249 @@ +from collections import defaultdict +from contextlib import contextmanager + +import windows +import windows.winobject.exception as winexception + +from windows import winproxy +from windows.generated_def import windef +from windows.generated_def.winstructs import * +from .breakpoints import * + + +class LocalDebugger(object): + """A debugger interface around :func:`AddVectoredExceptionHandler`""" + def __init__(self): + self.breakpoints = {} + self._memory_save = {} + self._reput_breakpoint = {} + self._hxbp_breakpoint = defaultdict(dict) + + self.callback_vectored = winexception.VectoredException(self.callback) + winproxy.AddVectoredExceptionHandler(0, self.callback_vectored) + self.setup_hxbp_callback_vectored = winexception.VectoredException(self.setup_hxbp_callback) + self.hxbp_info = None + self.code = windows.native_exec.create_function("\xcc\xc3", [PVOID]) + self.veh_depth = 0 + self.current_exception = None + self.exceptions_stack = [None] + + @contextmanager + def NewCurrentException(self, exc): + try: + self.exceptions_stack.append(exc) + self.current_exception = exc + self.veh_depth += 1 + yield exc + finally: + self.exceptions_stack.pop() + self.current_exception = self.exceptions_stack[-1] + self.veh_depth -= 1 + + def get_exception_code(self): + """Return ExceptionCode of current exception""" + return self.current_exception[0].ExceptionRecord[0].ExceptionCode + + def get_exception_context(self): + """Return context of current exception""" + return self.current_exception[0].ContextRecord[0] + + def single_step(self): + """Make the current thread to single step""" + self.get_exception_context().EEFlags.TF = 1 + return windef.EXCEPTION_CONTINUE_EXECUTION + + def _pass_breakpoint(self, addr, single_step): + with windows.utils.VirtualProtected(addr, 1, PAGE_EXECUTE_READWRITE): + windows.current_process.write_memory(addr, self._memory_save[addr]) + self._reput_breakpoint[windows.current_thread.tid] = self.breakpoints[addr], single_step + return self.single_step() + + def callback(self, exc): + with self.NewCurrentException(exc): + return self.handle_exception(exc) + + def handle_exception(self, exc): + exp_code = self.get_exception_code() + context = self.get_exception_context() + exp_addr = context.pc + + if exp_code == EXCEPTION_BREAKPOINT and exp_addr in self.breakpoints: + res = self.breakpoints[exp_addr].trigger(self, exc) + single_step = self.get_exception_context().EEFlags.TF # single step activated by breakpoint + if exp_addr in self.breakpoints: # Breakpoint deleted itself ? + return self._pass_breakpoint(exp_addr, single_step) + return EXCEPTION_CONTINUE_EXECUTION + + if exp_code == EXCEPTION_SINGLE_STEP and windows.current_thread.tid in self._reput_breakpoint: + bp, single_step = self._reput_breakpoint[windows.current_thread.tid] + 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") + del self._reput_breakpoint[windows.current_thread.tid] + if single_step: + return self.on_exception(exc) + return windef.EXCEPTION_CONTINUE_EXECUTION + elif exp_code == EXCEPTION_SINGLE_STEP and exp_addr in self._hxbp_breakpoint[windows.current_thread.tid]: + res = self._hxbp_breakpoint[windows.current_thread.tid][exp_addr].trigger(self, exc) + context.EEFlags.RF = 1 + return EXCEPTION_CONTINUE_EXECUTION + return self.on_exception(exc) + + def on_exception(self, exc): + """Called on exception""" + if not self.get_exception_code() in winexception.exception_name_by_value: + return windef.EXCEPTION_CONTINUE_SEARCH + return windef.EXCEPTION_CONTINUE_EXECUTION + + def del_bp(self, bp): + if bp.type == STANDARD_BP: + with windows.utils.VirtualProtected(bp.addr, 1, PAGE_EXECUTE_READWRITE): + windows.current_process.write_memory(bp.addr, self._memory_save[bp.addr]) + del self._memory_save[bp.addr] + del self.breakpoints[bp.addr] + return + if bp.type == HARDWARE_EXEC_BP: + for tid in self._hxbp_breakpoint: + if bp.addr in self._hxbp_breakpoint[tid] and self._hxbp_breakpoint[tid][bp.addr] == bp: + if tid == windows.current_thread.tid: + self.remove_hxbp_self_thread(bp.addr) + else: + self.remove_hxbp_other_thread(bp.addr) + del self._hxbp_breakpoint[tid][bp.addr] + #print("Need to remove {0} in {1}".format(self._hxbp_breakpoint[tid][bp.addr], tid)) + return + raise NotImplementedError("Unknow BP type {0}".format(bp.type)) + + def add_bp(self, bp, targets=None): + """Add a breakpoint, bp is a "class:`Breakpoint` + + If the ``bp`` type is ``STANDARD_BP``, target must be None. + + If the ``bp`` type is ``HARDWARE_EXEC_BP``, target can be None (all threads), or some threads of the process + """ + if bp.type == HARDWARE_EXEC_BP: + return self.add_bp_hxbp(bp, targets) + if bp.type != STANDARD_BP: + 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") + return + + def add_bp_hxbp(self, bp, targets=None): + if bp.type != HARDWARE_EXEC_BP: + raise NotImplementedError("Add non standard-BP in LocalDebugger") + if targets is None: + targets = windows.current_process.threads + for thread in targets: + if thread.owner.pid != windows.current_process.pid: + raise ValueError("Cannot add HXBP to target in remote process {0}".format(thread)) + if thread.tid == windows.current_thread.tid: + self.setup_hxbp_self_thread(bp.addr) + else: + self.setup_hxbp_other_thread(bp.addr, thread) + self._hxbp_breakpoint[thread.tid][bp.addr] = bp + + def setup_hxbp_callback(self, exc): + with self.NewCurrentException(exc): + exp_code = self.get_exception_code() + context = self.get_exception_context() + exp_addr = context.pc + hxbp_used = self.setup_hxbp_in_context(context, self.data) + windows.current_process.write_memory(exp_addr, "\x90") + # Raising in the VEH is a bad idea.. + # So better give the information to triggerer.. + if hxbp_used is not None: + self.get_exception_context().Eax = exp_addr + else: + self.get_exception_context().Eax = 0 + return windef.EXCEPTION_CONTINUE_EXECUTION + + def remove_hxbp_callback(self, exc): + with self.NewCurrentException(exc): + exp_code = self.get_exception_code() + context = self.get_exception_context() + exp_addr = context.pc + hxbp_used = self.remove_hxbp_in_context(context, self.data) + windows.current_process.write_memory(exp_addr, "\x90") + # Raising in the VEH is a bad idea.. + # So better give the information to triggerer.. + if hxbp_used is not None: + self.get_exception_context().Eax = exp_addr + else: + self.get_exception_context().Eax = 0 + return windef.EXCEPTION_CONTINUE_EXECUTION + + def setup_hxbp_in_context(self, context, addr): + for i in range(4): + is_used = getattr(context.EDr7, "L" + str(i)) + empty_drx = str(i) + if not is_used: + context.EDr7.GE = 1 + context.EDr7.LE = 1 + setattr(context.EDr7, "L" + empty_drx, 1) + setattr(context, "Dr" + empty_drx, addr) + return i + return None + + def remove_hxbp_in_context(self, context, addr): + for i in range(4): + target_drx = str(i) + is_used = getattr(context.EDr7, "L" + str(i)) + draddr = getattr(context, "Dr" + target_drx) + + if is_used and draddr == addr: + setattr(context.EDr7, "L" + target_drx, 0) + setattr(context, "Dr" + target_drx, 0) + return i + return None + + def setup_hxbp_self_thread(self, addr): + if self.current_exception is not None: + x = self.setup_hxbp_in_context(self.get_exception_context(), addr) + if x is None: + raise ValueError("Could not setup HXBP") + return + + self.data = addr + with winexception.VectoredExceptionHandler(1, self.setup_hxbp_callback): + x = self.code() + if x is None: + raise ValueError("Could not setup HXBP") + windows.current_process.write_memory(x, "\xcc") + return + + def setup_hxbp_other_thread(self, addr, thread): + thread.suspend() + ctx = thread.context + x = self.setup_hxbp_in_context(ctx, addr) + if x is None: + raise ValueError("Could not setup HXBP in {0}".format(thread)) + thread.set_context(ctx) + thread.resume() + + def remove_hxbp_self_thread(self, addr): + if self.current_exception is not None: + x = self.remove_hxbp_in_context(self.get_exception_context(), addr) + if x is None: + raise ValueError("Could not setup HXBP") + return + self.data = addr + with winexception.VectoredExceptionHandler(1, self.remove_hxbp_callback): + x = self.code() + if x is None: + raise ValueError("Could not remove HXBP") + windows.current_process.write_memory(x, "\xcc") + return + + def remove_hxbp_other_thread(self, addr, thread): + thread.suspend() + ctx = thread.context + x = self.remove_hxbp_in_context(ctx, addr) + if x is None: + raise ValueError("Could not setup HXBP in {0}".format(thread)) + thread.set_context(ctx) + thread.resume() \ No newline at end of file