From e4c0f8645e98f3393ea88a5111ee6c9e9fa60ede Mon Sep 17 00:00:00 2001 From: hakril Date: Mon, 18 May 2020 23:07:33 +0200 Subject: [PATCH] Adapted symbol code & samples for py3 compat --- samples/debug/follow_file_read_write.py | 118 ++++++++++++++++++++++++ samples/debug/symbol_debugger.py | 2 +- samples/service/service_demo.py | 30 ++++++ windows/debug/symbols.py | 5 +- windows/winproxy/apis/dbghelp.py | 3 +- 5 files changed, 154 insertions(+), 4 deletions(-) create mode 100644 samples/debug/follow_file_read_write.py create mode 100644 samples/service/service_demo.py diff --git a/samples/debug/follow_file_read_write.py b/samples/debug/follow_file_read_write.py new file mode 100644 index 0000000..157bcb2 --- /dev/null +++ b/samples/debug/follow_file_read_write.py @@ -0,0 +1,118 @@ +import sys +import os.path +import pprint +import argparse +sys.path.append(os.path.abspath(__file__ + "\..\..")) + +import windows +import windows.debug +import windows.generated_def as gdef + +class FollowNtCreateFile(windows.debug.FunctionBP): + TARGET = windows.winproxy.NtCreateFile + + def trigger(self, dbg, exc): + params = self.extract_arguments(dbg.current_process, dbg.current_thread) + filename = params["ObjectAttributes"].contents.ObjectName.contents.str + handle_addr = params["FileHandle"].value + self.data = (filename, handle_addr) + self.break_on_ret(dbg, exc) + + def ret_trigger(self, dbg, exc): + filename, handle_addr = self.data + ret_value = dbg.current_thread.context.func_result # EAX / RAX depending of bitness + if ret_value: + return # Creation failed + handle_value = dbg.current_process.read_ptr(handle_addr) + return dbg.on_file_create(filename, handle_value) + +class FollowReadFile(windows.debug.FunctionBP): + TARGET = windows.winproxy.ReadFile + + def trigger(self, dbg, exc): + params = self.extract_arguments(dbg.current_process, dbg.current_thread) + self.data = params + if params["hFile"] in dbg.followed_handles: + self.break_on_ret(dbg, exc) + + def ret_trigger(self, dbg, exc): + params = self.data + ret_value = dbg.current_thread.context.func_result + if not ret_value: # Read failed + return + buffer_size = dbg.current_process.read_dword(params["lpNumberOfBytesRead"]) + read_data = dbg.current_process.read_memory(params["lpBuffer"], buffer_size) + return dbg.on_file_read(params["hFile"], read_data) + +class FollowWriteFile(windows.debug.FunctionBP): + TARGET = windows.winproxy.WriteFile + + def trigger(self, dbg, exc): + params = self.extract_arguments(dbg.current_process, dbg.current_thread) + write_data = dbg.current_process.read_memory(params["lpBuffer"], params["nNumberOfBytesToWrite"]) + return dbg.on_file_write(params["hFile"], write_data) + +class FollowCloseFile(windows.debug.FunctionBP): + TARGET = windows.winproxy.CloseHandle + + def trigger(self, dbg, exc): + params = self.extract_arguments(dbg.current_process, dbg.current_thread) + return dbg.on_file_close(params["hObject"]) + + +class FileFollowDebugger(windows.debug.Debugger): + def __init__(self, target, filenames): + super(FileFollowDebugger, self).__init__(target) + self.filenames = filenames + self.followed_handles = {} + self.add_bp(FollowNtCreateFile()) + self.add_bp(FollowReadFile()) + self.add_bp(FollowWriteFile()) + self.add_bp(FollowCloseFile()) + + def on_exception(self, exc): + if exc.ExceptionRecord.ExceptionCode == gdef.EXCEPTION_BREAKPOINT: + return gdef.DBG_CONTINUE + return gdef.DBG_EXCEPTION_NOT_HANDLED + + def on_file_create(self, filename, handle): + if any(filename.lower().endswith(fname) for fname in self.filenames): + self.followed_handles[handle] = filename + print("Opened <{0}> as handle <{1:#x}>".format(filename, handle)) + + + def on_file_read(self, handle, data): + filename = self.followed_handles[handle] + print("Read from <{0}> ({1:#x})".format(filename, handle)) + print(repr(data)) + + def on_file_write(self, handle, data): + filename = self.followed_handles[handle] + print("Write to <{0}> ({1:#x})".format(filename, handle)) + print(repr(data)) + + def on_file_close(self, handle): + try: + filename = self.followed_handles[handle] + except KeyError as e: + return + print("Closing handle <{0:#x}> to <{1}>".format(handle, filename)) + del self.followed_handles[handle] + + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(prog=__file__) + parser.add_argument('exe') + parser.add_argument('--cmdline', default="") + parser.add_argument('files', nargs="+") + args = parser.parse_args() + print(args) + + target = windows.utils.create_process(args.exe, args.cmdline.split(), dwCreationFlags=gdef.DEBUG_PROCESS, show_windows=True) + + dbg = FileFollowDebugger(target, args.files) + dbg.loop() + print("BYE") + + diff --git a/samples/debug/symbol_debugger.py b/samples/debug/symbol_debugger.py index d7275da..2b9718d 100644 --- a/samples/debug/symbol_debugger.py +++ b/samples/debug/symbol_debugger.py @@ -30,7 +30,7 @@ class MyInfoBP(windows.debug.Breakpoint): dbg.current_process.exit() print("") -dbg = windows.debug.SymbolDebugger.debug(r"c:\windows\system32\notepad.exe") +dbg = windows.debug.SymbolDebugger.debug(b"c:\\windows\\system32\\notepad.exe") dbg.add_bp(MyInfoBP("kernelbase!CreateFileInternal+2")) dbg.add_bp(MyInfoBP("ntdll!LdrpInitializeProcess")) dbg.loop() \ No newline at end of file diff --git a/samples/service/service_demo.py b/samples/service/service_demo.py new file mode 100644 index 0000000..4a1b582 --- /dev/null +++ b/samples/service/service_demo.py @@ -0,0 +1,30 @@ +import windows +import windows.generated_def as gdef + +print("Listing the first 3 services:") +for service in windows.system.services[:3]: + print(" * {0}".format(service)) +print("") + +TARGET_SERVICE = "TapiSrv" +print("Retriving service <{0}>".format(TARGET_SERVICE)) +service = windows.system.services[TARGET_SERVICE] +print("{0}".format(service)) +print(" - name: {0!r}".format(service.name)) +print(" - description: {0!r}".format(service.description)) +print(" - state: {0!r}".format(service.status.state)) +print(" - type: {0!r}".format(service.status.type)) +print(" - process: {0!r}".format(service.process)) +print(" - security-description: {0}".format(service.security_descriptor)) + +if service.status.state == gdef.SERVICE_RUNNING: + print("Service already running, not trying to start it") +else: + print("Trying to start the service") + service.start() + while service.status.state != gdef.SERVICE_RUNNING: + pass + print("Service started !") + print("{0}".format(service)) + print(" - state: {0!r}".format(service.status.state)) + print(" - process: {0!r}".format(service.process)) \ No newline at end of file diff --git a/windows/debug/symbols.py b/windows/debug/symbols.py index d70e968..b9c6b0d 100644 --- a/windows/debug/symbols.py +++ b/windows/debug/symbols.py @@ -296,7 +296,7 @@ class SymbolModule(gdef.IMAGEHLP_MODULE64): return LoadedPdbName def __repr__(self): - pdb_basename = self.LoadedPdbName.split("\\")[-1] + pdb_basename = self.LoadedPdbName.split(b"\\")[-1] return '<{0} name="{1}" type={2} pdb="{3}" addr={4:#x}>'.format(type(self).__name__, self.name, self.type.value.name, pdb_basename, self.addr) @@ -483,7 +483,8 @@ class SymbolHandler(object): callback = ctypes.WINFUNCTYPE(gdef.BOOL, ctypes.POINTER(SymbolInfo), gdef.ULONG , ctypes.py_object)(callback) addr = getattr(mod, "addr", mod) # Retrieve mod.addr, else us the value directly - + # Expect A-string + mask = windows.pycompat.raw_encode(mask) windows.winproxy.SymSearch(self.handle, gdef.DWORD64(addr), 0, tag, mask, 0, callback, res, options) for sym in res: sym.resolver = self diff --git a/windows/winproxy/apis/dbghelp.py b/windows/winproxy/apis/dbghelp.py index 4cb1f16..808dceb 100644 --- a/windows/winproxy/apis/dbghelp.py +++ b/windows/winproxy/apis/dbghelp.py @@ -1,5 +1,6 @@ import ctypes import windows.generated_def as gdef +from windows.pycompat import int_types from ..apiproxy import ApiProxy, NeededParameter from ..error import fail_on_zero @@ -14,7 +15,7 @@ class DbgHelpProxy(ApiProxy): # !! this code loose a ref to obj. # Should still work as our calling-caller method keep a ref def transform_pyobject_to_pvoid(obj): - if obj is None or isinstance(obj, (int, long)): + if obj is None or isinstance(obj, int_types): return obj return ctypes.POINTER(gdef.PVOID)(ctypes.py_object(obj))[0]