Working / testing the debugger

This commit is contained in:
Clement Rouault
2016-01-25 19:11:51 +01:00
parent cf89d25486
commit 7c35615319
5 changed files with 477 additions and 113 deletions
+5
View File
@@ -4,6 +4,11 @@ TODO:
- Extend Registry feature (write)
- remove pe_parse.transform_ctypes_fields (use utils.transform_ctypes_fields)
- DBG
- Verif multiple bp at same place..
- Verif multiple pending at same place
- Clean / (rethink?) vectored_exception (+rename exception.py? context.py?)
- Test !! (bp, BP_HX, bp on only on process, bp_hx on only one thread..)
FIXME:
- WMI
+162 -59
View File
@@ -9,6 +9,11 @@ import windows.native_exec.simple_x64 as x64
from windows.generated_def.winstructs import *
from .generated_def import windef
from collections import defaultdict
STANDARD_BP = "BP"
HARDWARE_EXEC_BP = "HXBP"
class DEBUG_EVENT(DEBUG_EVENT):
KNOWN_EVENT_CODE = dict((x,x) for x in [EXCEPTION_DEBUG_EVENT,
@@ -33,9 +38,17 @@ class Debugger(object):
self.current_process = None
self.current_thread = None
# List of breakpoints
self.breakpoints = {}
self._pending_breakpoints = {} #Breakpoints to put in new process
self._break_metadata = {}
self._pending_breakpoints = {} #Breakpoints to put in new process / threads
# Values rewritten by "\xcc"
self._memory_save = defaultdict(dict)
# Dict of {tid : {drx taken : BP}}
self._hardware_breakpoint = defaultdict(dict)
# Breakpoints to reput..
self._breakpoint_to_reput = {}
def _init_dispatch_handlers(self):
@@ -73,43 +86,89 @@ class Debugger(object):
def _dispatch_breakpoint(self, exception, addr):
bp = self.breakpoints[addr]
return bp(self, exception)
bp.trigger(self, exception)
return bp
# Breakpoint stuff
#def _setup_breakpoint(self, bp, target):
# if bp.type != 0:
# raise NotImplementedError("BP TYPE != 0 (TODO)")
# if target is None:
# targets = self.processes.items()
# # Raise on multiple pending at same addr ?
# # We will add the pending breakpoint to other new processes
# self._pending_breakpoints[bp.addr] = (bp, target)
# else:
# targets = [(target.pid, target)]
#
# for pid, process in targets:
# self._break_metadata[pid][bp.addr] = process.read_memory(bp.addr, 1)
# #print("Write BP: {0} at {1}".format(process, addr))
# process.write_memory(bp.addr, "\xcc")
# return
def _setup_breakpoint_BP(self, bp, targets):
for target in targets:
if not isinstance(target, WinProcess):
raise ValueError("Cannot put standard breakpoint on target {0} (not a process)".format(target))
self._memory_save[target.pid][bp.addr] = target.read_memory(bp.addr, 1)
#print("Write BP: {0} at {1}".format(process, addr))
target.write_memory(bp.addr, "\xcc")
def _setup_breakpoint_HXBP(self, bp, targets):
all_threads = []
for target in targets:
if isinstance(target, WinProcess):
for t in target.threads:
all_threads.append(t)
elif isinstance(target, WinThread):
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
setattr(ctx.EDr7, "L" + empty_drx, 1)
setattr(ctx, "Dr" + empty_drx, bp.addr)
x[int(empty_drx)] = bp
target_thread.set_context(ctx)
def _setup_breakpoint(self, addr, type, target):
if type != 0:
raise NotImplementedError("BP TYPE != 0 (TODO)")
if target is None:
targets = self.processes.items()
# Raise on multiple pending ?
self._pending_breakpoints[addr] = (addr, type, target)
else:
targets = [(target.pid, target)]
for pid, process in targets:
self._break_metadata[pid] = process.read_memory(addr, 1)
print("Write BP: {0} at {1}".format(process, addr))
process.write_memory(addr, "\xcc")
return
def _setup_pending_breakpoints(self, target):
for addr, (bp_info) in self._pending_breakpoints.items():
# TODO: good format of data ? (dict and we just use values)
# TODO: need to handle threads ?
# TODO: handle target/expected_target is a thread :)
# Can it happen ?
pending_todo = list(self._pending_breakpoints.values())
for bp, expected_target in pending_todo:
# Valid addr ? (in non-loaded module: raise / pass ?)
expected_target = bp_info[2]
if expected_target is None or expected_target.pid == target.pid:
self._setup_breakpoint(bp_info[0], bp_info[1], target)
print("BP PLACED IN {0}".format(target))
_setup_method = getattr(self, "_setup_breakpoint_" + bp.type)
_setup_method(bp, [target])
# TODO REMOVE PENDING HERE if target is not None..
def _activate_single_step(self, thread):
raise NotImplementedError("TODO")
regs = self.get_context(thread)
def _pass_breakpoint(self, addr):
process = self.current_process
thread = self.current_thread
process.write_memory(addr, self._memory_save[process.pid][addr])
regs = thread.context
regs.EFlags |= (1 << 8)
self.set_context(thread, regs)
def _desactivate_single_step(self, thread):
regs = self.get_context(thread)
raise NotImplementedError("TODO")
regs.EFlags &= ~(1 << 8)
self.set_context(thread, regs)
regs.Eip -= 1
thread.set_context(regs)
self._breakpoint_to_reput[thread.tid] = addr #Register pending breakpoint for next single step
# debug event handlers
def _handle_unknown_debug_event(self, debug_event):
raise NotImplementedError("dwDebugEventCode = {0}".format(debug_event.dwDebugEventCode))
@@ -124,9 +183,25 @@ class Debugger(object):
excp_code = exception.ExceptionRecord.ExceptionCode
excp_addr = exception.ExceptionRecord.ExceptionAddress
print("Exception {0} at {1}".format(excp_code, hex(excp_addr)))
if excp_code == EXCEPTION_BREAKPOINT and excp_addr in self.breakpoints:
self._dispatch_breakpoint(exception, excp_addr)
self._pass_breakpoint(excp_addr)
return
elif excp_code == EXCEPTION_SINGLE_STEP:
if self.current_thread.tid in self._breakpoint_to_reput:
addr = self._breakpoint_to_reput[self.current_thread.tid]
del self._breakpoint_to_reput[self.current_thread.tid]
# Re-put the breakpoint
self.current_process.write_memory(addr, "\xcc")
elif excp_addr in self.breakpoints:
# Verif that's not a standard BP ?
bp = self.breakpoints[excp_addr]
bp.trigger(self, exception)
ctx = self.current_thread.context
ctx.EEFlags.RF = 1
self.current_thread.set_context(ctx)
else:
self.on_exception(exception)
else: # Do not trigger self.on_exception if breakpoint was registered
self.on_exception(exception)
@@ -136,6 +211,7 @@ class Debugger(object):
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):
@@ -195,8 +271,45 @@ class Debugger(object):
rip_info = debug_event.u.RipInfo
self.on_rip(rip_info)
# Public callback
# Public API
def loop(self):
for debug_event in self._debug_event_generator():
self._dispatch_debug_event(debug_event)
self._finish_debug_event(debug_event, windef.DBG_CONTINUE)
if not self.processes:
# No More process to debug
break
def add_bp(self, bp, addr=None, type=None, target=None):
"""TODO: use type for hardware breakpoints"""
if getattr(bp, "addr", None) is None:
if addr is None or type is None:
raise ValueError("SUCK YOUR NONE")
bp = ProxyBreakpoint(bp, addr, type)
else:
if addr is not None or type is not None:
raise ValueError("Given <addr|type> by parameters but BP object have them")
del addr
del type
if target is None:
# Raise on multiple pending at same addr ?
# We will add the pending breakpoint to other new processes
if bp.addr in self._pending_breakpoints:
raise ValueError("Pending breakpoint already at {0}".format(hex(bp.addr)))
self._pending_breakpoints[bp.addr] = (bp, target)
targets = self.processes.values()
if targets is None:
return
else:
targets = [target]
if bp.addr in self.breakpoints:
raise ValueError("Breakpoint already at {0}".format(hex(bp.addr)))
self.breakpoints[bp.addr] = bp
_setup_method = getattr(self, "_setup_breakpoint_" + bp.type)
_setup_method(bp, targets)
return True
# Public callback
def on_exception(self, exception):
pass
@@ -224,36 +337,26 @@ class Debugger(object):
def on_rip(self, rip_info):
pass
# Public API
def loop(self):
for x, debug_event in enumerate(self._debug_event_generator()):
self._dispatch_debug_event(debug_event)
self._finish_debug_event(debug_event, windef.DBG_CONTINUE)
if not self.processes:
# No More process to debug
break
def add_bp(self, bp, addr=None, target=None):
"""TODO: use type for hardware breakpoints"""
call_target = bp
if getattr(bp, "addr", None) is not None:
addr = bp.addr
call_target = bp.trigger
# if addr is not None: raise ?
# Non object breakpoint
if addr is None:
raise ValueError("No address: need a valid <bp.addr> or <addr> parameter")
self.breakpoints[addr] = call_target
self._setup_breakpoint(addr, bp.type, target)
return True
class Breakpoint(object):
type = 0 # REAL BP
type = "BP" # REAL BP
def __init__(self, addr):
self.addr = addr
def trigger(self, exception):
def trigger(self, dbg, exception):
pass
class ProxyBreakpoint(Breakpoint):
def __init__(self, target, addr, type):
self.target = target
self.addr = addr
self.type = type
def trigger(self, dbg, exception):
return self.target(dbg, exception)
class HXBreakpoint(Breakpoint):
type = HARDWARE_EXEC_BP
+156 -9
View File
@@ -8,9 +8,12 @@ from contextlib import contextmanager
sys.path.append(".")
import unittest
import windows
import windows.debug
import windows.native_exec.simple_x86 as x86
import windows.native_exec.simple_x64 as x64
from windows.generated_def.winstructs import *
is_process_32_bits = windows.current_process.bitness == 32
is_process_64_bits = windows.current_process.bitness == 64
@@ -25,22 +28,22 @@ process_64bit_only = unittest.skipIf(not is_process_64_bits, "Test for 64bits pr
if is_windows_32_bits:
def pop_calc_32():
return windows.utils.create_process(r"C:\Windows\system32\calc.exe", show_windows=True)
def pop_calc_32(dwCreationFlags):
return windows.utils.create_process(r"C:\Windows\system32\calc.exe", dwCreationFlags=dwCreationFlags, show_windows=True)
def pop_calc_64():
def pop_calc_64(dwCreationFlags):
raise WindowsError("Cannot create calc64 in 32bits system")
else:
def pop_calc_32():
return windows.utils.create_process(r"C:\Windows\syswow64\calc.exe", show_windows=True)
def pop_calc_32(dwCreationFlags):
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():
def pop_calc_64(dwCreationFlags):
with windows.utils.DisableWow64FsRedirection():
return windows.utils.create_process(r"C:\Windows\system32\calc.exe", show_windows=True)
return windows.utils.create_process(r"C:\Windows\system32\calc.exe", dwCreationFlags=dwCreationFlags, show_windows=True)
else:
def pop_calc_64():
return windows.utils.create_process(r"C:\Windows\system32\calc.exe", show_windows=True)
def pop_calc_64(dwCreationFlags):
return windows.utils.create_process(r"C:\Windows\system32\calc.exe", dwCreationFlags=dwCreationFlags, show_windows=True)
@contextmanager
@@ -298,10 +301,154 @@ class WindowsAPITestCase(unittest.TestCase):
windows.winproxy.CreateFileA("NONEXISTFILE.FILE")
class DebuggerTestCase(unittest.TestCase):
def debuggable_calc_32(self):
return windows.utils.create_process(r"C:\python27\python.exe", dwCreationFlags=DEBUG_PROCESS | CREATE_NEW_CONSOLE, show_windows=True)
def test_init_breakpoint_callback(self):
TEST_CASE = self
class MyDbg(windows.debug.Debugger):
def on_exception(self, exception):
TEST_CASE.assertEqual(exception.ExceptionRecord.ExceptionCode, EXCEPTION_BREAKPOINT)
self.current_process.exit()
calc = pop_calc_32(dwCreationFlags=DEBUG_PROCESS)
d = MyDbg(calc)
d.loop()
def test_simple_standard_breakpoint(self):
TEST_CASE = self
class TSTBP(windows.debug.Breakpoint):
def trigger(self, dbg, exc):
TEST_CASE.assertEqual(dbg.current_process.pid, calc.pid)
TEST_CASE.assertEqual(dbg.current_process.read_memory(self.addr, 1), "\xcc")
TEST_CASE.assertEqual(dbg.current_thread.context.pc - 1, self.addr)
d.current_process.exit()
calc = pop_calc_32(dwCreationFlags=DEBUG_PROCESS)
d = windows.debug.Debugger(calc)
d.add_bp(TSTBP(windows.current_process.peb.modules[1].pe.exports["LdrLoadDll"]))
d.loop()
def test_simple_hwx_breakpoint(self):
TEST_CASE = self
class TSTBP(windows.debug.HXBreakpoint):
def trigger(self, dbg, exc):
TEST_CASE.assertEqual(dbg.current_process.pid, calc.pid)
TEST_CASE.assertEqual(dbg.current_thread.context.pc, self.addr)
TEST_CASE.assertNotEqual(dbg.current_thread.context.Dr7, 0)
d.current_process.exit()
calc = pop_calc_32(dwCreationFlags=DEBUG_PROCESS)
d = windows.debug.Debugger(calc)
d.add_bp(TSTBP(windows.current_process.peb.modules[1].pe.exports["LdrLoadDll"]))
d.loop()
def test_multiple_hwx_breakpoint(self):
TEST_CASE = self
data = [0]
class TSTBP(windows.debug.HXBreakpoint):
def __init__(self, addr, expec_before):
self.addr = addr
self.expec_before = expec_before
def trigger(self, dbg, exc):
TEST_CASE.assertEqual(dbg.current_process.pid, calc.pid)
TEST_CASE.assertEqual(dbg.current_thread.context.pc, self.addr)
TEST_CASE.assertNotEqual(dbg.current_thread.context.Dr7, 0)
TEST_CASE.assertEqual(data[0], self.expec_before)
TEST_CASE.assertNotEqual(dbg.current_process.read_memory(self.addr, 1), "\xcc")
data[0] += 1
if data[0] == 4:
d.current_process.exit()
calc = pop_calc_32(dwCreationFlags=DEBUG_PROCESS)
d = windows.debug.Debugger(calc)
addr = calc.virtual_alloc(0x1000)
calc.write_memory(addr, "\x90" * 8)
d.add_bp(TSTBP(addr, 0))
d.add_bp(TSTBP(addr + 1, 1))
d.add_bp(TSTBP(addr + 2, 2))
d.add_bp(TSTBP(addr + 3, 3))
calc.create_thread(addr, 0)
d.loop()
# Used to verif we actually called the Breakpoints
TEST_CASE.assertEqual(data[0], 4)
def test_four_hwx_breakpoint_fail(self):
TEST_CASE = self
data = [0]
class TSTBP(windows.debug.HXBreakpoint):
def __init__(self, addr, expec_before):
self.addr = addr
self.expec_before = expec_before
def trigger(self, dbg, exc):
raise NotImplementedError("Should fail before")
calc = pop_calc_32(dwCreationFlags=DEBUG_PROCESS)
d = windows.debug.Debugger(calc)
addr = calc.virtual_alloc(0x1000)
calc.write_memory(addr, "\x90" * 8)
d.add_bp(TSTBP(addr, 0))
d.add_bp(TSTBP(addr + 1, 1))
d.add_bp(TSTBP(addr + 2, 2))
d.add_bp(TSTBP(addr + 3, 3))
d.add_bp(TSTBP(addr + 4, 4))
calc.create_thread(addr, 0)
with self.assertRaises(ValueError) as e:
d.loop()
self.assertIn("DRx", e.exception.message)
# Used to verif we actually NOT called the Breakpoints
TEST_CASE.assertEqual(data[0], 0)
def test_hwx_breakpoint_are_on_all_thread(self):
TEST_CASE = self
data = [0]
class MyDbg(windows.debug.Debugger):
def on_create_thread(self, exception):
# Check that later created thread have their HWX breakpoint :)
TEST_CASE.assertNotEqual(self.current_thread.context.Dr7, 0)
class TSTBP(windows.debug.HXBreakpoint):
def __init__(self, addr, expec_before):
self.addr = addr
self.expec_before = expec_before
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
calc.create_thread(addr, 0)
else:
d.current_process.exit()
calc = pop_calc_32(dwCreationFlags=DEBUG_PROCESS)
d = MyDbg(calc)
addr = calc.virtual_alloc(0x1000)
calc.write_memory(addr, "\x90" * 2)
d.add_bp(TSTBP(addr, 0))
calc.create_thread(addr, 0)
d.loop()
# Used to verif we actually called the Breakpoints
TEST_CASE.assertEqual(data[0], 1)
if __name__ == '__main__':
alltests = unittest.TestSuite()
alltests.addTest(unittest.makeSuite(WindowsTestCase))
alltests.addTest(unittest.makeSuite(WindowsAPITestCase))
alltests.addTest(unittest.makeSuite(DebuggerTestCase))
alltests.debug()
tester = unittest.TextTestRunner(verbosity=2)
tester.run(alltests)
+129 -39
View File
@@ -63,41 +63,92 @@ class EEXCEPTION_DEBUG_INFO32(ctypes.Structure):
class EEXCEPTION_DEBUG_INFO64(ctypes.Structure):
_fields_ = windows.utils.transform_ctypes_fields(EXCEPTION_DEBUG_INFO, {"ExceptionRecord": EnhancedEXCEPTION_RECORD64})
class Eflags(int):
_flags_ = [("CF", 1),
("RES_1", 1),
("PF", 1),
("RES_3", 1),
("AF", 1),
("RES_5", 1),
("ZF", 1),
("SF", 1),
("TF", 1),
("IF", 1),
("DF", 1),
("OF", 1),
("IOPL_1", 1),
("IOPL_2", 1),
("NT", 1),
("RES_15", 1),
("RF", 1),
("VM", 1),
("AC", 1),
("VIF", 1),
("VIP", 1),
("ID", 1),
#class Eflags(int):
# _flags_ = [("CF", 1),
# ("RES_1", 1),
# ("PF", 1),
# ("RES_3", 1),
# ("AF", 1),
# ("RES_5", 1),
# ("ZF", 1),
# ("SF", 1),
# ("TF", 1),
# ("IF", 1),
# ("DF", 1),
# ("OF", 1),
# ("IOPL_1", 1),
# ("IOPL_2", 1),
# ("NT", 1),
# ("RES_15", 1),
# ("RF", 1),
# ("VM", 1),
# ("AC", 1),
# ("VIF", 1),
# ("VIP", 1),
# ("ID", 1),
# ]
#
# _flag_mask_ = dict([(name, 1 << i) for i, (name, size) in enumerate(_flags_)])
#
# def __getattr__(self, name):
# if name in self._flag_mask_:
# return bool(self & self._flag_mask_[name])
# return super(Eflags, self).__getattr_(name)
#
# def dump(self):
# res = []
# for name in self._flag_mask_:
# if name.startswith("RES_"):
# continue
# if getattr(self, name):
# res.append(name)
# return "|".join(res)
#
# def __repr__(self):
# return "{0}({1})".format(type(self).__name__, self.dump())
#
# __str__ = __repr__
#
# def __hex__(self):
# return "{0}({1}:{2})".format(type(self).__name__, int.__hex__(self), self.dump())
class EEflags(ctypes.Structure):
_fields_ = [("CF", DWORD, 1),
("RES_1", DWORD, 1),
("PF", DWORD, 1),
("RES_3", DWORD, 1),
("AF", DWORD, 1),
("RES_5", DWORD, 1),
("ZF", DWORD, 1),
("SF", DWORD, 1),
("TF", DWORD, 1),
("IF", DWORD, 1),
("DF", DWORD, 1),
("OF", DWORD, 1),
("IOPL_1", DWORD, 1),
("IOPL_2", DWORD, 1),
("NT", DWORD, 1),
("RES_15", DWORD, 1),
("RF", DWORD, 1),
("VM", DWORD, 1),
("AC", DWORD, 1),
("VIF", DWORD, 1),
("VIP", DWORD, 1),
("ID", DWORD, 1),
]
_flag_mask_ = dict([(name, 1 << i) for i, (name, size) in enumerate(_flags_)])
def get_raw(self):
x = DWORD.from_address(ctypes.addressof(self))
return x.value
def __getattr__(self, name):
if name in self._flag_mask_:
return bool(self & self._flag_mask_[name])
return super(Eflags, self).__getattr_(name)
def set_raw(self, value):
x = DWORD.from_address(ctypes.addressof(self))
x.value = value
return None
def dump(self):
res = []
for name in self._flag_mask_:
for name in [x[0] for x in self._fields_]:
if name.startswith("RES_"):
continue
if getattr(self, name):
@@ -105,12 +156,38 @@ class Eflags(int):
return "|".join(res)
def __repr__(self):
return "{0}({1})".format(type(self).__name__, self.dump())
__str__ = __repr__
return hex(self)
def __hex__(self):
return "{0}({1}:{2})".format(type(self).__name__, int.__hex__(self), self.dump())
if self.raw == 0:
return "{0}({1})".format(type(self).__name__, hex(self.raw))
return "{0}({1}:{2})".format(type(self).__name__, hex(self.raw), self.dump())
raw = property(get_raw, set_raw)
class EDr7(ctypes.Structure):
_fields_ = [("L0", DWORD, 1),
("G0", DWORD, 1),
("L1", DWORD, 1),
("G1", DWORD, 1),
("L2", DWORD, 1),
("G2", DWORD, 1),
("L3", DWORD, 1),
("G3", DWORD, 1),
("LE", DWORD, 1),
("GE", DWORD, 1),
("RES_1", DWORD, 3),
("GD", DWORD, 1),
("RES_1", DWORD, 2),
("RW0", DWORD, 2),
("LEN0", DWORD, 2),
("RW1", DWORD, 2),
("LEN1", DWORD, 2),
("RW2", DWORD, 2),
("LEN2", DWORD, 2),
("RW3", DWORD, 2),
("LEN3", DWORD, 2),
]
class EnhancedCONTEXTBase():
default_dump = ()
@@ -142,23 +219,36 @@ class EnhancedCONTEXTBase():
pc = property(get_pc, set_pc, None, "Program Counter register (EIP or RIP)")
@property
def EEFlags(self):
off = type(self).EFlags.offset
x = EEflags.from_address(ctypes.addressof(self) + off)
x.self = self
return x
class EnhancedCONTEXT32(EnhancedCONTEXTBase, CONTEXT32):
@property
def EDr7(self):
off = type(self).Dr7.offset
x = EDr7.from_address(ctypes.addressof(self) + off)
x.self = self
return x
class EnhancedCONTEXT32(EnhancedCONTEXTBase, (CONTEXT32)):
default_dump = ('Eip', 'Esp', 'Eax', 'Ebx', 'Ecx', 'Edx', 'Ebp', 'Edi', 'Esi', 'EFlags')
pc_reg = 'Eip'
special_reg_type = {'EFlags': Eflags}
#special_reg_type = {'EFlags': Eflags}
class EnhancedCONTEXTWOW64(EnhancedCONTEXTBase, WOW64_CONTEXT):
class EnhancedCONTEXTWOW64(EnhancedCONTEXTBase, (WOW64_CONTEXT)):
default_dump = ('Eip', 'Esp', 'Eax', 'Ebx', 'Ecx', 'Edx', 'Ebp', 'Edi', 'Esi', 'EFlags')
pc_reg = 'Eip'
special_reg_type = {'EFlags': Eflags}
#special_reg_type = {'EFlags': Eflags}
class EnhancedCONTEXT64(EnhancedCONTEXTBase, CONTEXT64):
class EnhancedCONTEXT64(EnhancedCONTEXTBase, (CONTEXT64)):
default_dump = ('Rip', 'Rsp', 'Rax', 'Rbx', 'Rcx', 'Rdx', 'Rbp', 'Rdi', 'Rsi',
'R9', 'R10', 'R11', 'R12', 'R13', 'R14', 'R15', 'EFlags')
pc_reg = 'Rip'
special_reg_type = {'EFlags': Eflags}
#special_reg_type = {'EFlags': Eflags}
@classmethod
def new_aligned(cls):
+25 -6
View File
@@ -3,6 +3,7 @@ import os
import copy
import time
import struct
import itertools
import windows
import windows.network
@@ -52,7 +53,6 @@ class AutoHandle(object):
def __del__(self):
if hasattr(self, "_handle") and self._handle:
print("Del HANDLE {0} ({1})".format((self), self._handle))
self.CLOSE_FUNCTION(self._handle)
@@ -147,13 +147,13 @@ class WinThread(THREADENTRY32, AutoHandle):
if self.owner.bitness == 32 and windows.current_process.bitness == 64:
# Wow64
x = windows.vectored_exception.EnhancedCONTEXTWOW64()
x.ContextFlags = CONTEXT_FULL
x.ContextFlags = CONTEXT_ALL
winproxy.Wow64GetThreadContext(self.handle, x)
return x
if self.owner.bitness == 64 and windows.current_process.bitness == 32:
x = windows.vectored_exception.EnhancedCONTEXT64.new_aligned()
x.ContextFlags = CONTEXT_FULL
x.ContextFlags = CONTEXT_ALL
windows.syswow64.NtGetContextThread_32_to_64(self.handle, x)
return x
@@ -161,7 +161,7 @@ class WinThread(THREADENTRY32, AutoHandle):
x = windows.vectored_exception.EnhancedCONTEXT32()
else:
x = windows.vectored_exception.EnhancedCONTEXT64.new_aligned()
x.ContextFlags = CONTEXT_FULL
x.ContextFlags = CONTEXT_ALL
winproxy.GetThreadContext(self.handle, x)
return x
@@ -234,7 +234,6 @@ class WinThread(THREADENTRY32, AutoHandle):
# Really useful ?
thread = [t for t in System().threads if t.tid == tid][0]
# set AutoHandle _handle
print("New thread from handle {0}".format(handle))
thread._handle = handle
return thread
except IndexError:
@@ -519,7 +518,6 @@ class WinProcess(PROCESSENTRY32, Process):
pid = winproxy.GetProcessId(handle)
proc = [p for p in windows.system.processes if p.pid == pid][0]
proc._handle = handle
print("New Process from handle {0}".format(handle))
return proc
@@ -600,6 +598,27 @@ class WinProcess(PROCESSENTRY32, Process):
return self.read_dword(addr)
return self.read_qword(addr)
def read_string(self, addr):
res = []
for i in itertools.count():
x = self.read_memory(addr + (i * 0x100), 0x100)
if "\x00" in x:
res.append(x.split("\x00", 1)[0])
break
res.append(x)
return "".join(res)
def read_wstring(self, addr):
res = []
for i in itertools.count():
x = self.read_memory(addr + (i * 0x100), 0x100)
utf16_chars = ["".join(c) for c in zip(*[iter(x)] * 2)]
if "\x00\x00" in utf16_chars:
res.extend(utf16_chars[:utf16_chars.index("\x00\x00")])
break
res.extend(x)
return "".join(res).decode('utf16')
# Simple cache test
# real_read = read_memory
#