Add context_syswow/set_syswow_context + debugger able to handle BP in 64b part of syswow process

This commit is contained in:
Clement Rouault
2016-07-20 18:21:28 +02:00
parent 53acf21a2f
commit f54a64670e
7 changed files with 60 additions and 5 deletions
+4 -1
View File
@@ -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)
+3
View File
@@ -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)
+1
View File
@@ -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
+22 -2
View File
@@ -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:
+1
View File
@@ -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
View File
@@ -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:
+22
View File
@@ -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