mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
Fix test + Fix a Use-After-CloseHandle in debugger + add dbgprint on HANDLE
This commit is contained in:
+20
-10
@@ -2,6 +2,7 @@ import windows
|
||||
import windows.winproxy as winproxy
|
||||
|
||||
from windows.winobject import WinProcess, WinThread
|
||||
from windows.dbgprint import dbgprint
|
||||
|
||||
import windows.native_exec.simple_x86 as x86
|
||||
import windows.native_exec.simple_x64 as x64
|
||||
@@ -126,13 +127,11 @@ class Debugger(object):
|
||||
all_threads.append(target)
|
||||
else:
|
||||
raise ValueError("Unknow HXBP target type for <{0}>".format(target))
|
||||
|
||||
for target_thread in all_threads:
|
||||
x = self._hardware_breakpoint[target_thread.tid]
|
||||
if all(pos in x for pos in range(4)):
|
||||
raise ValueError("Cannot put {0} in {1} (DRx full)".format(bp, target_thread))
|
||||
empty_drx = str([pos for pos in range(4) if pos not in x][0])
|
||||
#print("Empty DRx = {0}".format(empty_drx))
|
||||
ctx = target_thread.context
|
||||
ctx.EDr7.GE = 1
|
||||
ctx.EDr7.LE = 1
|
||||
@@ -140,7 +139,6 @@ class Debugger(object):
|
||||
setattr(ctx.EDr7, "L" + empty_drx, 1)
|
||||
setattr(ctx, "Dr" + empty_drx, bp.addr)
|
||||
x[int(empty_drx)] = bp
|
||||
|
||||
target_thread.set_context(ctx)
|
||||
|
||||
|
||||
@@ -153,6 +151,12 @@ class Debugger(object):
|
||||
for bp, expected_target in pending_todo:
|
||||
# Valid addr ? (in non-loaded module: raise / pass ?)
|
||||
if expected_target is None or expected_target.pid == target.pid:
|
||||
if isinstance(target, WinThread):
|
||||
x = self._hardware_breakpoint[target.tid]
|
||||
# Ignore BP on thread_create that have already been
|
||||
# put by the process_create event
|
||||
if bp in x.values():
|
||||
continue
|
||||
_setup_method = getattr(self, "_setup_breakpoint_" + bp.type)
|
||||
_setup_method(bp, [target])
|
||||
# TODO REMOVE PENDING HERE if target is not None..
|
||||
@@ -206,13 +210,7 @@ class Debugger(object):
|
||||
self.on_exception(exception)
|
||||
|
||||
|
||||
def _handle_create_thread(self, debug_event):
|
||||
"""Handle CREATE_THREAD_DEBUG_EVENT"""
|
||||
create_thread = debug_event.u.CreateThread
|
||||
self.current_thread = WinThread._from_handle(create_thread.hThread)
|
||||
self.threads[self.current_thread.tid] = self.current_thread
|
||||
self._setup_pending_breakpoints(self.current_thread)
|
||||
self.on_create_thread(create_thread)
|
||||
|
||||
|
||||
def _handle_create_process(self, debug_event):
|
||||
"""Handle CREATE_PROCESS_DEBUG_EVENT"""
|
||||
@@ -232,10 +230,21 @@ class Debugger(object):
|
||||
self._update_debugger_state(debug_event)
|
||||
exit_process = debug_event.u.ExitProcess
|
||||
self.on_exit_process(exit_process)
|
||||
del self.threads[self.current_thread.tid]
|
||||
del self.processes[self.current_process.pid]
|
||||
# Hack IT, ContinueDebugEvent will close the HANDLE for us
|
||||
# Should we make another handle instead ?
|
||||
dbgprint("Removing handle {0} for {1} (will be closed by continueDebugEvent".format(hex(self.current_process._handle), self.current_process), "HANDLE")
|
||||
del self.current_process._handle
|
||||
del self.current_thread._handle
|
||||
|
||||
def _handle_create_thread(self, debug_event):
|
||||
"""Handle CREATE_THREAD_DEBUG_EVENT"""
|
||||
create_thread = debug_event.u.CreateThread
|
||||
self.current_thread = WinThread._from_handle(create_thread.hThread)
|
||||
self.threads[self.current_thread.tid] = self.current_thread
|
||||
self._setup_pending_breakpoints(self.current_thread)
|
||||
self.on_create_thread(create_thread)
|
||||
|
||||
def _handle_exit_thread(self, debug_event):
|
||||
"""Handle EXIT_THREAD_DEBUG_EVENT"""
|
||||
@@ -245,6 +254,7 @@ class Debugger(object):
|
||||
del self.threads[self.current_thread.tid]
|
||||
# Hack IT, ContinueDebugEvent will close the HANDLE for us
|
||||
# Should we make another handle instead ?
|
||||
dbgprint("Removing handle {0} for {1} (will be closed by continueDebugEvent".format(hex(self.current_thread._handle), self.current_thread), "HANDLE")
|
||||
del self.current_thread._handle
|
||||
|
||||
def _handle_load_dll(self, debug_event):
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
from mytest import WindowsTestCase, WindowsAPITestCase, pop_calc_32, pop_calc_64, Calc32, Calc64
|
||||
from mytest import WindowsTestCase, WindowsAPITestCase, DebuggerTestCase, pop_calc_32, pop_calc_64, Calc32, Calc64
|
||||
|
||||
__all__ = ["WindowsTestCase", "WindowsAPITestCase"]
|
||||
__all__ = ["WindowsTestCase", "WindowsAPITestCase", "DebuggerTestCase"]
|
||||
|
||||
@@ -28,21 +28,21 @@ process_64bit_only = unittest.skipIf(not is_process_64_bits, "Test for 64bits pr
|
||||
|
||||
|
||||
if is_windows_32_bits:
|
||||
def pop_calc_32(dwCreationFlags):
|
||||
def pop_calc_32(dwCreationFlags=0):
|
||||
return windows.utils.create_process(r"C:\Windows\system32\calc.exe", dwCreationFlags=dwCreationFlags, show_windows=True)
|
||||
|
||||
def pop_calc_64(dwCreationFlags):
|
||||
def pop_calc_64(dwCreationFlags=0):
|
||||
raise WindowsError("Cannot create calc64 in 32bits system")
|
||||
else:
|
||||
def pop_calc_32(dwCreationFlags):
|
||||
def pop_calc_32(dwCreationFlags=0):
|
||||
return windows.utils.create_process(r"C:\Windows\syswow64\calc.exe", dwCreationFlags=dwCreationFlags, show_windows=True)
|
||||
|
||||
if is_process_32_bits:
|
||||
def pop_calc_64(dwCreationFlags):
|
||||
def pop_calc_64(dwCreationFlags=0):
|
||||
with windows.utils.DisableWow64FsRedirection():
|
||||
return windows.utils.create_process(r"C:\Windows\system32\calc.exe", dwCreationFlags=dwCreationFlags, show_windows=True)
|
||||
else:
|
||||
def pop_calc_64(dwCreationFlags):
|
||||
def pop_calc_64(dwCreationFlags=0):
|
||||
return windows.utils.create_process(r"C:\Windows\system32\calc.exe", dwCreationFlags=dwCreationFlags, show_windows=True)
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ def Calc64(exit_code=0):
|
||||
calc.exit(exit_code)
|
||||
|
||||
|
||||
|
||||
@contextmanager
|
||||
def Calc32(exit_code=0):
|
||||
try:
|
||||
@@ -425,7 +426,6 @@ class DebuggerTestCase(unittest.TestCase):
|
||||
def trigger(self, dbg, exc):
|
||||
TEST_CASE.assertNotEqual(len(dbg.current_process.threads), 1)
|
||||
for t in dbg.current_process.threads:
|
||||
print(hex(t.context.Dr7))
|
||||
TEST_CASE.assertNotEqual(t.context.Dr7, 0)
|
||||
if data[0] == 0: #First time we got it ! create new thread
|
||||
data[0] = 1
|
||||
|
||||
@@ -26,6 +26,7 @@ import windows.pe_parse as pe_parse
|
||||
|
||||
|
||||
|
||||
|
||||
class AutoHandle(object):
|
||||
"""An abstract class that allow easy handle creation/destruction/wait"""
|
||||
# Big bypass to prevent missing reference at programm close..
|
||||
@@ -45,6 +46,7 @@ class AutoHandle(object):
|
||||
if hasattr(self, "_handle"):
|
||||
return self._handle
|
||||
self._handle = self._get_handle()
|
||||
dbgprint("Open handle {0} for {1}".format(hex(self._handle), self), "HANDLE")
|
||||
return self._handle
|
||||
|
||||
def wait(self, timeout=INFINITE):
|
||||
@@ -53,6 +55,7 @@ class AutoHandle(object):
|
||||
|
||||
def __del__(self):
|
||||
if hasattr(self, "_handle") and self._handle:
|
||||
dbgprint("Closing Handle {0} for {1}".format(hex(self._handle), self), "HANDLE")
|
||||
self.CLOSE_FUNCTION(self._handle)
|
||||
|
||||
|
||||
@@ -235,8 +238,10 @@ class WinThread(THREADENTRY32, AutoHandle):
|
||||
thread = [t for t in System().threads if t.tid == tid][0]
|
||||
# set AutoHandle _handle
|
||||
thread._handle = handle
|
||||
dbgprint("Thread {0} from handle {1}".format(thread, hex(handle)), "HANDLE")
|
||||
return thread
|
||||
except IndexError:
|
||||
dbgprint("DeadThread from handle {0}".format(hex(handle)), "HANDLE")
|
||||
return DeadThread(handle, tid)
|
||||
|
||||
class DeadThread(AutoHandle):
|
||||
@@ -518,6 +523,7 @@ class WinProcess(PROCESSENTRY32, Process):
|
||||
pid = winproxy.GetProcessId(handle)
|
||||
proc = [p for p in windows.system.processes if p.pid == pid][0]
|
||||
proc._handle = handle
|
||||
dbgprint("Process {0} from handle {1}".format(proc, hex(handle)), "HANDLE")
|
||||
return proc
|
||||
|
||||
|
||||
@@ -738,6 +744,9 @@ class WinProcess(PROCESSENTRY32, Process):
|
||||
"""Exit the process"""
|
||||
return winproxy.TerminateProcess(self.handle, code)
|
||||
|
||||
|
||||
|
||||
|
||||
# Create ProcessToken and Thread Token objects ?
|
||||
class Token(AutoHandle):
|
||||
def __init__(self, handle):
|
||||
|
||||
Reference in New Issue
Block a user