mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
Debugger test pass on py3
This commit is contained in:
+22
-17
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user