Fix test + Fix a Use-After-CloseHandle in debugger + add dbgprint on HANDLE

This commit is contained in:
Clement Rouault
2016-01-26 14:50:21 +01:00
parent 7c35615319
commit 010453e96d
4 changed files with 37 additions and 18 deletions
+20 -10
View File
@@ -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):
+2 -2
View File
@@ -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"]
+6 -6
View File
@@ -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
+9
View File
@@ -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):