Debugger test pass on py3

This commit is contained in:
hakril
2020-02-08 00:15:41 +01:00
parent 6a74c83670
commit f403856e26
2 changed files with 47 additions and 23 deletions
+22 -17
View File
@@ -8,8 +8,8 @@ import windows.generated_def as gdef
import windows.native_exec.simple_x86 as x86
import windows.native_exec.simple_x64 as x64
from conftest import generate_pop_and_exit_fixtures, pop_proc_32, pop_proc_64
from pfwtest import *
from .conftest import generate_pop_and_exit_fixtures, pop_proc_32, pop_proc_64
from .pfwtest import *
proc32_debug = generate_pop_and_exit_fixtures([pop_proc_32], ids=["proc32dbg"], dwCreationFlags=gdef.DEBUG_PROCESS)
proc64_debug = generate_pop_and_exit_fixtures([pop_proc_64], ids=["proc64dbg"], dwCreationFlags=gdef.DEBUG_PROCESS)
@@ -46,7 +46,7 @@ def test_simple_standard_breakpoint(proc32_64_debug):
class TSTBP(windows.debug.Breakpoint):
def trigger(self, dbg, exc):
assert dbg.current_process.pid == proc32_64_debug.pid
assert dbg.current_process.read_memory(self.addr, 1) == "\xcc"
assert dbg.current_process.read_memory(self.addr, 1) == b"\xcc"
assert dbg.current_thread.context.pc == self.addr
d.current_process.exit()
@@ -85,7 +85,7 @@ def test_multiple_hwx_breakpoint(proc32_64_debug):
assert dbg.current_thread.context.pc == self.addr
assert dbg.current_thread.context.Dr7 != 0
assert TSTBP.COUNTER == self.expec_before
assert dbg.current_process.read_memory(self.addr, 1) != "\xcc"
assert dbg.current_process.read_memory(self.addr, 1) != b"\xcc"
TSTBP.COUNTER += 1
if TSTBP.COUNTER == 4:
d.current_process.exit()
@@ -126,7 +126,7 @@ def test_four_hwx_breakpoint_fail(proc32_64_debug):
proc32_64_debug.create_thread(addr, 0)
with pytest.raises(ValueError) as e:
d.loop()
assert "DRx" in e.value.message
assert "DRx" in e.value.args[0]
def test_hwx_breakpoint_are_on_all_thread(proc32_64_debug):
@@ -182,7 +182,7 @@ def test_simple_breakpoint_name_addr(proc32_64_debug, bptype):
d.loop()
assert TSTBP.COUNTER == 1
import dbg_injection
from . import dbg_injection
def test_hardware_breakpoint_name_addr(proc32_64_debug):
"""Check that name addr in HXBP are trigger in all threads"""
@@ -357,7 +357,7 @@ import threading
@python_injection
@pytest.mark.parametrize("bptype", [windows.debug.FunctionParamDumpHXBP, windows.debug.FunctionParamDumpBP])
def test_standard_breakpoint_self_remove(proc32_64_debug, bptype):
data = []
data = set()
def do_check():
proc32_64_debug.execute_python_unsafe("open(u'FILENAME1')").wait()
@@ -371,20 +371,21 @@ def test_standard_breakpoint_self_remove(proc32_64_debug, bptype):
addr = exc.ExceptionRecord.ExceptionAddress
ctx = dbg.current_thread.context
filename = self.extract_arguments(dbg.current_process, dbg.current_thread)["lpFileName"]
data.append(filename)
data.add(filename)
if filename == u"FILENAME2":
dbg.del_bp(self)
d = windows.debug.Debugger(proc32_64_debug)
d.add_bp(TSTBP("kernel32!CreateFileW"))
d.add_bp(TSTBP("kernelbase!CreateFileW"))
threading.Thread(target=do_check).start()
d.loop()
assert data == [u"FILENAME1", u"FILENAME2"]
assert data >= set([u"FILENAME1", u"FILENAME2"])
assert u"FILENAME3" not in data
@python_injection
@pytest.mark.parametrize("bptype", [windows.debug.FunctionParamDumpHXBP, windows.debug.FunctionParamDumpBP])
def test_standard_breakpoint_remove(proc32_64_debug, bptype):
data = []
data = set()
def do_check():
proc32_64_debug.execute_python_unsafe("open(u'FILENAME1')").wait()
@@ -396,19 +397,19 @@ def test_standard_breakpoint_remove(proc32_64_debug, bptype):
class TSTBP(bptype):
TARGET = windows.winproxy.CreateFileW
def trigger(self, dbg, exc):
# import pdb;pdb.set_trace()
addr = exc.ExceptionRecord.ExceptionAddress
ctx = dbg.current_thread.context
filename = self.extract_arguments(dbg.current_process, dbg.current_thread)["lpFileName"]
data.append(filename)
data.add(filename)
d = windows.debug.Debugger(proc32_64_debug)
the_bp = TSTBP("kernel32!CreateFileW")
the_bp = TSTBP("kernelbase!CreateFileW")
# import pdb;pdb.set_trace()
d.add_bp(the_bp)
threading.Thread(target=do_check).start()
d.loop()
assert data == [u"FILENAME1", u"FILENAME2"]
assert data >= set([u"FILENAME1", u"FILENAME2"])
assert u"FILENAME3" not in data
def get_generate_read_at_for_proc(target):
@@ -540,6 +541,8 @@ def test_exe_in_module_list(proc32_64_debug):
class MyDbg(windows.debug.Debugger):
def on_exception(self, exception):
exename = os.path.basename(proc32_64_debug.peb.imagepath.str)
assert exename.endswith(".exe")
exename = exename[:-len(".exe")] # Remove the .exe from the module name
this_process_modules = self._module_by_process[self.current_process.pid]
assert exename and exename in this_process_modules.keys()
self.current_process.exit()
@@ -562,6 +565,8 @@ def test_bp_exe_by_name(proc32_64_debug):
exepe = proc32_64_debug.peb.exe
entrypoint = exepe.get_OptionalHeader().AddressOfEntryPoint
exename = os.path.basename(proc32_64_debug.peb.imagepath.str)
assert exename.endswith(".exe")
exename = exename[:-len(".exe")] # Remove the .exe from the module name
d = windows.debug.Debugger(proc32_64_debug)
# The goal is to test bp of format 'exename!offset' so we craft a string based on the entrypoint
d.add_bp(TSTBP("{name}!{offset}".format(name=exename, offset=entrypoint)))
@@ -579,7 +584,7 @@ def test_keyboardinterrupt_when_bp_event(proc32_64_debug, monkeypatch):
def WaitForDebugEvent_KeyboardInterrupt(debug_event):
real_WaitForDebugEvent(debug_event)
if not debug_event.code == gdef.EXCEPTION_DEBUG_EVENT:
if not debug_event.dwDebugEventCode == gdef.EXCEPTION_DEBUG_EVENT:
return
if not debug_event.u.Exception.ExceptionRecord.ExceptionCode in [gdef.EXCEPTION_BREAKPOINT, gdef.STATUS_WX86_BREAKPOINT]:
return # Not a BP
@@ -592,7 +597,7 @@ def test_keyboardinterrupt_when_bp_event(proc32_64_debug, monkeypatch):
# This should emultate a ctrl+c on when waiting for the event
# Our goal is to set the target back to a good state :)
TEST_CODE = "\xeb\xfe\xff\xff\xff\xff\xff" # Loop + invalid instr
TEST_CODE = b"\xeb\xfe\xff\xff\xff\xff\xff" # Loop + invalid instr
addr = proc32_64_debug.virtual_alloc(0x1000)
proc32_64_debug.write_memory(addr, TEST_CODE)
d = windows.debug.Debugger(proc32_64_debug)
+25 -6
View File
@@ -19,9 +19,13 @@ from .breakpoints import *
#from windows.syswow64 import CS_32bits
from windows.winobject.exception import VectoredException
from windows.pycompat import basestring
PAGE_SIZE = 0x1000
class DebuggerError(Exception):
pass
class DEBUG_EVENT(DEBUG_EVENT):
KNOWN_EVENT_CODE = dict((x,x) for x in [EXCEPTION_DEBUG_EVENT,
@@ -102,7 +106,7 @@ class Debugger(object):
self.target = None # Remove ref to process -> GC -> CloseHandle -> process is destroyed
windows.winproxy.DebugActiveProcessStop(tpid)
return
for proc in targets:
for proc in list(targets):
self.detach(proc)
del targets
return
@@ -110,7 +114,7 @@ class Debugger(object):
raise ValueError("Detach accept only WinProcess")
self.disable_all_memory_breakpoints(target)
for bp in self.breakpoints[target.pid].values():
for bp in list(self.breakpoints[target.pid].values()):
if not bp.apply_to_target(target):
target_threads = [t for t in target.threads if t.tid in self.threads]
bp_threads = []
@@ -173,7 +177,7 @@ class Debugger(object):
def _debug_event_generator(self):
while True:
debug_event = DEBUG_EVENT()
debug_event = gdef.DEBUG_EVENT()
try:
winproxy.WaitForDebugEvent(debug_event)
except KeyboardInterrupt as e:
@@ -181,7 +185,7 @@ class Debugger(object):
# BP trigger will not be called.
# So AT LEAST quit loop with a coherent context
# Fix thread PC if we just triggered a BP
if (debug_event.code == gdef.EXCEPTION_DEBUG_EVENT and
if (debug_event.dwDebugEventCode == gdef.EXCEPTION_DEBUG_EVENT and
debug_event.u.Exception.ExceptionRecord.ExceptionCode in [gdef.EXCEPTION_BREAKPOINT, gdef.STATUS_WX86_BREAKPOINT]):
# This is a breakpoint: One of ours ?
bp_addr = debug_event.u.Exception.ExceptionRecord.ExceptionAddress
@@ -207,7 +211,9 @@ class Debugger(object):
def _add_exe_to_module_list(self, create_process_event):
"""Add the intial exe file described by create_process_event to the list of module in the process"""
exe_path = self.current_process.get_mapped_filename(create_process_event.lpBaseOfImage)
exe_name = os.path.basename(exe_path)
exe_name = os.path.basename(exe_path).lower()
if exe_name.endswith(".exe"):
exe_name = exe_name[:-len(".exe")]
#print("Exe name is {0}".format(exe_name))
self._module_by_process[self.current_process.pid][exe_name] = windows.pe_parse.GetPEFile(create_process_event.lpBaseOfImage, self.current_process)
#self._setup_pending_breakpoints_load_dll(exe_name) # Already setup in _setup_pending_breakpoints_new_process
@@ -251,7 +257,13 @@ class Debugger(object):
if api not in exports:
dbgprint("Error resolving <{0}> in <{1}>".format(addr, target), "DBG")
raise ValueError("Unknown API <{0}> in DLL {1}".format(api, dll))
return exports[api]
target_addr = exports[api]
if isinstance(target_addr, basestring):
target_string = target_addr.replace(".", "!")
dbgprint("<{0}> is export proxy to <{1}>".format(addr, target_string), "DBG")
# Possible infinite loop ?
return self._resolve(target_string, target)
return target_addr
def add_pending_breakpoint(self, bp, target):
self._pending_breakpoints_new[target].append(bp)
@@ -285,6 +297,9 @@ class Debugger(object):
raise ValueError("Cannot setup STANDARD_BP on {0}".format(target))
addr = self._resolve(bp.addr, target)
# raise DebuggerError("Could not set breakpoint {0} at <{1}>".format(bp, bp.addr))
if addr is None:
return False
dbgprint("Setting soft-BP at <{0:#x}> in <{1}>".format(addr, target), "DBG")
@@ -821,6 +836,9 @@ class Debugger(object):
del self._breakpoint_to_reput[self.current_thread.tid]
return retvalue
def _internal_on_load_dll(self, load_dll):
return None
def _handle_load_dll(self, debug_event):
"""Handle LOAD_DLL_DEBUG_EVENT"""
self._update_debugger_state(debug_event)
@@ -835,6 +853,7 @@ class Debugger(object):
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._internal_on_load_dll(load_dll) # Allow hook for symbol-debugger
self._setup_pending_breakpoints_load_dll(dll_name)
with self.DisabledMemoryBreakpoint():
try: