from ctypes import *
from . import client
from . import control
from . import symbols
from .probe_process import probe_state
from .utils import *
class STARTUPINFOA(Structure):
_fields_ = [
("cb", c_ulong),
("lpReserved", c_char_p),
("lpDesktop", c_char_p),
("lpTitle", c_char_p),
("dwX", c_ulong),
("dwY", c_ulong),
("dwXSize", c_ulong),
("dwYSize", c_ulong),
("dwXCountChars", c_ulong),
("dwYCountChars", c_ulong),
("dwFillAttribute", c_ulong),
("wShowWindow", c_ushort),
("cbReserved2", c_ushort),
("lpReserved2", c_char_p),
("hStdInput", c_void_p),
("hStdOutput", c_void_p),
("hStdError", c_void_p),
]
class PROCESS_INFORMATION(Structure):
_fields_ = [
("hProcess", c_void_p),
("hThread", c_void_p),
("dwProcessId", c_ulong),
("dwThreadId", c_ulong),
]
def fetch_local_function_syms(Symbols, prefix):
syms = Symbols.get_all_functions()
def is_sym_in_src_dir(sym):
name, data = sym
symdata = Symbols.GetLineByOffset(data.Offset)
if symdata is not None:
srcfile, line = symdata
if prefix in srcfile:
return True
return False
syms = [x for x in syms if is_sym_in_src_dir(x)]
return syms
def break_on_all_but_main(Control, Symbols, main_offset):
mainfile, _ = Symbols.GetLineByOffset(main_offset)
prefix = "\\".join(mainfile.split("\\")[:-1])
for name, rec in fetch_local_function_syms(Symbols, prefix):
if name == "main":
continue
bp = Control.AddBreakpoint2(offset=rec.Offset, enabled=True)
return
def setup_everything(binfile):
from . import client
from . import symbols
Client = client.Client()
Client.Control.SetEngineOptions(0x20)
Client.CreateProcessAndAttach2(binfile)
sym_opts = Client.Symbols.GetSymbolOptions()
sym_opts |= symbols.SymbolOptionFlags.SYMOPT_LOAD_LINES
Client.Symbols.SetSymbolOptions(sym_opts)
res = Client.Control.WaitForEvent(timeout=1000)
if res == S_FALSE:
client.TerminateProcesses()
raise Exception("Debuggee did not start in a timely manner")
Client.Control.Execute("l+t")
Client.Control.SetExpressionSyntax(cpp=True)
module_name = Client.Symbols.get_exefile_module_name()
offset = Client.Symbols.GetOffsetByName("{}!main".format(module_name))
breakpoint = Client.Control.AddBreakpoint2(offset=offset, enabled=True)
Client.Control.SetExecutionStatus(control.DebugStatus.DEBUG_STATUS_GO)
res = Client.Control.WaitForEvent(timeout=5000)
if res == S_FALSE:
client.TerminateProcesses()
raise Exception("Debuggee did not reach main function in a timely manner")
break_on_all_but_main(Client.Control, Client.Symbols, offset)
filts = Client.Control.GetNumberEventFilters()
for x in range(filts[0], filts[0] + filts[1]):
Client.Control.SetExceptionFilterSecondCommand(x, "qd")
return Client
def step_once(client):
client.Control.Execute("p")
try:
client.Control.WaitForEvent()
except Exception as e:
if (
client.Control.GetExecutionStatus()
== control.DebugStatus.DEBUG_STATUS_NO_DEBUGGEE
):
return None
raise e
client.Control.GetExecutionStatus()
return probe_state(client)
def main_loop(client):
res = True
while res is not None:
res = step_once(client)
def cleanup(client):
client.TerminateProcesses()