mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
LocalDebugger sample + fix
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
import ctypes
|
||||
import windows
|
||||
import windows.debug
|
||||
from windows.generated_def.winstructs import *
|
||||
|
||||
ct = windows.current_thread
|
||||
t = [t for t in windows.current_process.threads if t.tid == ct.tid][0]
|
||||
|
||||
|
||||
|
||||
class YoloDebugger(windows.debug.LocalDebugger):
|
||||
def __init__(self, single_step_count):
|
||||
super(YoloDebugger, self).__init__()
|
||||
self.single_step_count = single_step_count
|
||||
|
||||
def on_exception(self, exc):
|
||||
code = self.get_exception_code()
|
||||
context = self.get_exception_context()
|
||||
print("EXCEPTION !!!! Got a {0} at 0x{1:x}".format(code, context.pc))
|
||||
if self.single_step_count:
|
||||
self.single_step_count -= 1
|
||||
return self.single_step()
|
||||
|
||||
|
||||
class YoloHXBP(windows.debug.HXBreakpoint):
|
||||
def trigger(self, dbg, exc):
|
||||
context = dbg.get_exception_context()
|
||||
print("GOT AN HXBP <3 at 0x{0:x}".format(context.pc))
|
||||
windows.current_process.write_memory(self.addr, "\x90\x90")
|
||||
return dbg.single_step()
|
||||
|
||||
print("Your main thread is {0}".format(windows.current_thread.tid))
|
||||
|
||||
|
||||
d = YoloDebugger(5)
|
||||
# Infinite loop + nop + ret
|
||||
|
||||
addr = windows.native_exec.native_function.allocator.write_code("\xeb\xfe\x90\x90\x90\x90\xc3")
|
||||
func_type = ctypes.CFUNCTYPE(PVOID)
|
||||
func = func_type(addr)
|
||||
|
||||
print("Code addr = 0x{0:x}".format(addr))
|
||||
|
||||
t = windows.current_process.create_thread(addr, 0)
|
||||
|
||||
d.add_bp(YoloHXBP(addr))
|
||||
|
||||
t.wait()
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import ctypes
|
||||
import windows
|
||||
import windows.test
|
||||
|
||||
from windows.generated_def.winstructs import *
|
||||
|
||||
remote_code = """
|
||||
import windows
|
||||
from windows.generated_def.winstructs import *
|
||||
|
||||
windows.utils.create_console()
|
||||
|
||||
class YOLOHXBP(windows.debug.HXBreakpoint):
|
||||
def trigger(self, dbg, exc):
|
||||
p = windows.current_process
|
||||
arg_pos = 2
|
||||
context = dbg.get_exception_context()
|
||||
esp = context.Esp
|
||||
unicode_string_addr = p.read_ptr(esp + (arg_pos + 1) * 4)
|
||||
wstring_addr = p.read_ptr(unicode_string_addr + 4)
|
||||
dll_loaded = p.read_wstring(wstring_addr)
|
||||
print("I AM LOADING <{0}>".format(dll_loaded))
|
||||
|
||||
d = windows.debug.LocalDebugger()
|
||||
|
||||
exp = windows.current_process.peb.modules[1].pe.exports
|
||||
#windows.utils.FixedInteractiveConsole(locals()).interact()
|
||||
ldr = exp["LdrLoadDll"]
|
||||
d.add_bp(YOLOHXBP(ldr))
|
||||
print("By from {0}".format(windows.current_thread.tid))
|
||||
|
||||
"""
|
||||
|
||||
c = windows.test.pop_calc_32(dwCreationFlags=CREATE_SUSPENDED)
|
||||
c.execute_python(remote_code)
|
||||
c.threads[0].resume()
|
||||
|
||||
import time
|
||||
time.sleep(2)
|
||||
c.exit()
|
||||
+95
-9
@@ -423,8 +423,14 @@ class Debugger(object):
|
||||
|
||||
# Public callback
|
||||
def on_exception(self, exception):
|
||||
"""Called on exception event other that known breakpoint"""
|
||||
pass
|
||||
"""Called on exception event other that known breakpoint
|
||||
|
||||
The default behaviour is to return ``DBG_CONTINUE`` for the known exception code
|
||||
and ``DBG_EXCEPTION_NOT_HANDLED`` else
|
||||
"""
|
||||
if not exception.ExceptionRecord.ExceptionCode in windows.exception.exception_name_by_value:
|
||||
return DBG_EXCEPTION_NOT_HANDLED
|
||||
return DBG_CONTINUE
|
||||
|
||||
def on_create_process(self, create_process):
|
||||
"""Called on create_process event"""
|
||||
@@ -499,10 +505,16 @@ class LocalDebugger(object):
|
||||
self.breakpoints = {}
|
||||
self._memory_save = {}
|
||||
self._reput_breakpoint = {}
|
||||
self._hxbp_breakpoint = defaultdict(dict)
|
||||
|
||||
self.callback_vectored = VectoredException(self.callback)
|
||||
windows.winproxy.AddVectoredExceptionHandler(0, self.callback_vectored)
|
||||
|
||||
self.setup_hxbp_callback_vectored = VectoredException(self.setup_hxbp_callback)
|
||||
self.hxbp_info = None
|
||||
|
||||
self.code = windows.native_exec.create_function("\xcc\xc3", [PVOID])
|
||||
|
||||
def get_exception_code(self):
|
||||
return self.current_exception[0].ExceptionRecord[0].ExceptionCode
|
||||
|
||||
@@ -522,10 +534,11 @@ class LocalDebugger(object):
|
||||
def callback(self, exc):
|
||||
self.current_exception = exc
|
||||
exp_code = self.get_exception_code()
|
||||
exp_addr = self.get_exception_context().get_pc()
|
||||
context = self.get_exception_context()
|
||||
exp_addr = context.pc
|
||||
|
||||
if exp_code == EXCEPTION_BREAKPOINT and exp_addr in self.breakpoints:
|
||||
continue_value = self.breakpoints[exp_addr].trigger(self, exc)
|
||||
res = self.breakpoints[exp_addr].trigger(self, exc)
|
||||
single_step = self.get_exception_context().EEFlags.TF # single step activated by breakpoint
|
||||
return self._pass_breakpoint(exp_addr, single_step)
|
||||
|
||||
@@ -538,17 +551,90 @@ class LocalDebugger(object):
|
||||
if single_step:
|
||||
return self.on_exception(exc)
|
||||
return windef.EXCEPTION_CONTINUE_EXECUTION
|
||||
return self.on_exception(exc)
|
||||
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
|
||||
res = self.on_exception(exc)
|
||||
return EXCEPTION_CONTINUE_EXECUTION
|
||||
|
||||
def on_exception(self, exc):
|
||||
if not self.get_exception_code() in windows.exception.exception_name_by_value:
|
||||
return windef.EXCEPTION_CONTINUE_SEARCH
|
||||
return windef.EXCEPTION_CONTINUE_EXECUTION
|
||||
|
||||
def add_bp(self, bp):
|
||||
def add_bp(self, bp, targets=None):
|
||||
if bp.type == HARDWARE_EXEC_BP:
|
||||
return self.add_bp_hxbp(bp, targets)
|
||||
if bp.type != STANDARD_BP:
|
||||
raise NotImplementedError("Add non standard-BP in LocalKernelDebugger")
|
||||
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
|
||||
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):
|
||||
self.current_exception = 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 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 setup_hxbp_self_thread(self, addr):
|
||||
self.data = addr
|
||||
with windows.exception.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()
|
||||
@@ -316,19 +316,20 @@ class VectoredException(object):
|
||||
return windef.EXCEPTION_CONTINUE_SEARCH
|
||||
|
||||
|
||||
class WithExceptionHandler(object):
|
||||
def __init__(self, handler):
|
||||
class VectoredExceptionHandler(object):
|
||||
def __init__(self, pos, handler):
|
||||
self.handler = VectoredException(handler)
|
||||
self.pos = pos
|
||||
|
||||
def __enter__(self):
|
||||
self.value = windows.winproxy.AddVectoredExceptionHandler(0, self.handler)
|
||||
self.value = windows.winproxy.AddVectoredExceptionHandler(self.pos, self.handler)
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
windows.winproxy.RemoveVectoredExceptionHandler(self.value)
|
||||
return False
|
||||
|
||||
class DumpContextOnException(WithExceptionHandler):
|
||||
class DumpContextOnException(VectoredExceptionHandler):
|
||||
def __init__(self, exit=False):
|
||||
self.exit = exit
|
||||
super(DumpContextOnException, self).__init__(self.print_context_result)
|
||||
|
||||
@@ -475,7 +475,7 @@ class Process(AutoHandle):
|
||||
|
||||
class CurrentThread(AutoHandle):
|
||||
"""The current thread"""
|
||||
@utils.fixedpropety
|
||||
@property #It's not a fixedpropety because executing thread might change
|
||||
def tid(self):
|
||||
"""Thread ID
|
||||
|
||||
|
||||
Reference in New Issue
Block a user