mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
Add context_syswow/set_syswow_context + debugger able to handle BP in 64b part of syswow process
This commit is contained in:
@@ -19,4 +19,7 @@ Since 0.2:
|
||||
* Remove OptionExport from winproxy
|
||||
* MemoryBP + single_step for windows.debug.Debugger
|
||||
* Possibility to delete breakpoints in windows.debug.Debugger
|
||||
* Add Context.func_result as abstract register for EAX/RAX
|
||||
* Add Context.func_result as abstract register for EAX/RAX
|
||||
* Can retrieve 64b context of syswow thread via context_syswow/set_syswow_context
|
||||
* Debugger handle breakpoint in 64b part of syswow process
|
||||
* ReadSyswow64Process is now a Process (allows to parse exports of remote PEB64 of syswow process)
|
||||
@@ -20,6 +20,9 @@ TODO:
|
||||
- registry
|
||||
- test !
|
||||
|
||||
- processes
|
||||
- TEST / DOC of Process.context_syswow
|
||||
|
||||
|
||||
- Injection
|
||||
- death of process in execute_python raise a WindowsError with explicit message (change sample in readme)
|
||||
|
||||
@@ -223,6 +223,7 @@
|
||||
|
||||
#define CONTEXT_FULL CONTEXT_I386 | CONTEXT_FULL
|
||||
#define CONTEXT_ALL CONTEXT_I386 | CONTEXT_ALL
|
||||
#define CONTEXT_XSTATE (CONTEXT_I386 | 0x00000040L)
|
||||
|
||||
|
||||
#define PAGE_NOACCESS 0x01
|
||||
|
||||
@@ -14,6 +14,7 @@ from windows.generated_def.winstructs import *
|
||||
from windows.generated_def import windef
|
||||
from .breakpoints import *
|
||||
|
||||
#from windows.syswow64 import CS_32bits
|
||||
from windows.winobject.exception import VectoredException
|
||||
|
||||
|
||||
@@ -386,11 +387,18 @@ class Debugger(object):
|
||||
|
||||
|
||||
def _handle_exception_breakpoint(self, exception, excp_addr):
|
||||
excp_bitness = self.get_exception_bitness(exception)
|
||||
if excp_addr in self.breakpoints[self.current_process.pid]:
|
||||
thread = self.current_thread
|
||||
ctx = thread.context
|
||||
if self.current_process.bitness == 32 and excp_bitness == 64:
|
||||
ctx = thread.context_syswow
|
||||
else:
|
||||
ctx = thread.context
|
||||
ctx.pc -= 1
|
||||
thread.set_context(ctx)
|
||||
if self.current_process.bitness == 32 and excp_bitness == 64:
|
||||
thread.set_syswow_context(ctx)
|
||||
else:
|
||||
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
|
||||
if excp_addr in self.breakpoints[self.current_process.pid]:
|
||||
@@ -597,6 +605,11 @@ class Debugger(object):
|
||||
load_dll = debug_event.u.LoadDll
|
||||
dll = self._get_loaded_dll(load_dll)
|
||||
dll_name = os.path.basename(dll).lower()
|
||||
if dll_name.endswith(".dll"):
|
||||
dll_name = dll_name[:-4]
|
||||
if dll_name.endswith(".dll64"):
|
||||
dll_name = dll_name[:-6] + "64" # Crade..
|
||||
#print("Load {0} -> {1}".format(dll, dll_name))
|
||||
self._module_by_process[self.current_process.pid][dll_name] = windows.pe_parse.GetPEFile(load_dll.lpBaseOfDll, self.current_process)
|
||||
self._setup_pending_breakpoints_load_dll(dll_name)
|
||||
with self.DisabledMemoryBreakpoint():
|
||||
@@ -746,6 +759,13 @@ class Debugger(object):
|
||||
finally:
|
||||
self.restore_all_memory_breakpoints_verif_remove(data, target)
|
||||
|
||||
def get_exception_bitness(self, exc):
|
||||
if windows.current_process.bitness == 32:
|
||||
return 32
|
||||
if exc.ExceptionRecord.ExceptionCode in [STATUS_WX86_BREAKPOINT, STATUS_WX86_SINGLE_STEP]:
|
||||
return 32
|
||||
return 64
|
||||
|
||||
# Public callback
|
||||
def on_exception(self, exception):
|
||||
"""Called on exception event other that known breakpoint or requested single step. ``exception`` is one of the following type:
|
||||
|
||||
@@ -222,6 +222,7 @@ CONTEXT_FULL = Flag("CONTEXT_FULL", ( CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEX
|
||||
CONTEXT_ALL = Flag("CONTEXT_ALL", ( CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | CONTEXT_EXTENDED_REGISTERS ))
|
||||
CONTEXT_FULL = Flag("CONTEXT_FULL", CONTEXT_I386 | CONTEXT_FULL)
|
||||
CONTEXT_ALL = Flag("CONTEXT_ALL", CONTEXT_I386 | CONTEXT_ALL)
|
||||
CONTEXT_XSTATE = Flag("CONTEXT_XSTATE", ( CONTEXT_I386 | 0x00000040 ))
|
||||
PAGE_NOACCESS = Flag("PAGE_NOACCESS", 0x01)
|
||||
PAGE_READONLY = Flag("PAGE_READONLY", 0x02)
|
||||
PAGE_READWRITE = Flag("PAGE_READWRITE", 0x04)
|
||||
|
||||
+7
-2
@@ -159,16 +159,21 @@ def get_current_process_syswow_peb():
|
||||
return windows.winobject.process.RemotePEB64(peb_addr, CurrentProcessReadSyswow())
|
||||
|
||||
|
||||
class ReadSyswow64Process(object):
|
||||
class ReadSyswow64Process(process.Process):
|
||||
def __init__(self, target):
|
||||
self.target = target
|
||||
self.bitness = target.bitness
|
||||
self._bitness = target.bitness
|
||||
|
||||
def _get_handle(self):
|
||||
return self.target.handle
|
||||
|
||||
def read_memory(self, addr, size):
|
||||
buffer_addr = ctypes.create_string_buffer(size)
|
||||
winproxy.NtWow64ReadVirtualMemory64(self.target.handle, addr, buffer_addr, size)
|
||||
return buffer_addr[:]
|
||||
|
||||
#read_string = process.Process.read_string
|
||||
|
||||
|
||||
def get_syswow_ntdll_exports():
|
||||
if get_syswow_ntdll_exports.value is not None:
|
||||
|
||||
@@ -110,6 +110,19 @@ class WinThread(THREADENTRY32, AutoHandle):
|
||||
winproxy.GetThreadContext(self.handle, x)
|
||||
return x
|
||||
|
||||
@property
|
||||
def context_syswow(self):
|
||||
if not self.owner.is_wow_64:
|
||||
raise ValueError("Not a syswow process")
|
||||
x = exception.ECONTEXT64.new_aligned()
|
||||
x.ContextFlags = CONTEXT_ALL
|
||||
if windows.current_process.bitness == 64:
|
||||
winproxy.GetThreadContext(self.handle, x)
|
||||
else:
|
||||
windows.syswow64.NtGetContextThread_32_to_64(self.handle, x)
|
||||
return x
|
||||
|
||||
|
||||
def set_context(self, context):
|
||||
"""Set the thread context to ``context``"""
|
||||
if self.owner.bitness == windows.current_process.bitness:
|
||||
@@ -118,6 +131,15 @@ class WinThread(THREADENTRY32, AutoHandle):
|
||||
return winproxy.Wow64SetThreadContext(self.handle, context)
|
||||
return windows.syswow64.NtSetContextThread_32_to_64(self.handle, ctypes.byref(context))
|
||||
|
||||
|
||||
def set_syswow_context(self, context):
|
||||
if not self.owner.is_wow_64:
|
||||
raise ValueError("Not a syswow process")
|
||||
if windows.current_process.bitness == 64:
|
||||
return winproxy.SetThreadContext(self.handle, context)
|
||||
return windows.syswow64.NtSetContextThread_32_to_64(self.handle, ctypes.byref(context))
|
||||
|
||||
|
||||
@property
|
||||
def start_address(self):
|
||||
"""The start address of the thread
|
||||
|
||||
Reference in New Issue
Block a user