Commit <a l'arrache> for a quick implem of del_bp on standard BP

This commit is contained in:
Clement Rouault
2016-07-08 16:21:57 +02:00
parent 4069c0892a
commit 2f06e9e844
4 changed files with 339 additions and 290 deletions
+3
View File
@@ -0,0 +1,3 @@
from .debugger import Debugger, HXBreakpoint
from .localdbg import LocalDebugger
from .breakpoints import *
+55
View File
@@ -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
+32 -290
View File
@@ -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()
+249
View File
@@ -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()