diff --git a/ctypes_generation/winfunc.txt b/ctypes_generation/winfunc.txt index 2bb118f..513450c 100644 --- a/ctypes_generation/winfunc.txt +++ b/ctypes_generation/winfunc.txt @@ -725,4 +725,8 @@ BOOL WINAPI DebugSetProcessKillOnExit( BOOL WINAPI DebugBreakProcess ( __in HANDLE Process - ); \ No newline at end of file + ); + +DWORD WINAPI GetProcessId( + _In_ HANDLE Process +); diff --git a/windows/debug.py b/windows/debug.py index b8dc170..78996fd 100644 --- a/windows/debug.py +++ b/windows/debug.py @@ -1,6 +1,8 @@ import windows import windows.winproxy as winproxy +from windows.winobject import WinProcess, WinThread + import windows.native_exec.simple_x86 as x86 import windows.native_exec.simple_x64 as x64 @@ -8,8 +10,6 @@ from windows.generated_def.winstructs import * from .generated_def import windef - - class DEBUG_EVENT(DEBUG_EVENT): KNOWN_EVENT_CODE = dict((x,x) for x in [EXCEPTION_DEBUG_EVENT, CREATE_THREAD_DEBUG_EVENT, CREATE_PROCESS_DEBUG_EVENT, @@ -22,26 +22,23 @@ class DEBUG_EVENT(DEBUG_EVENT): class Debugger(object): -#define EXCEPTION_DEBUG_EVENT 1 -#define CREATE_THREAD_DEBUG_EVENT 2 -#define CREATE_PROCESS_DEBUG_EVENT 3 -#define EXIT_THREAD_DEBUG_EVENT 4 -#define EXIT_PROCESS_DEBUG_EVENT 5 -#define LOAD_DLL_DEBUG_EVENT 6 -#define UNLOAD_DLL_DEBUG_EVENT 7 -#define OUTPUT_DEBUG_STRING_EVENT 8 -#define RIP_EVENT 9 - + dwDebugEventCode_handlers = {} + def handle_dwDebugEventCode(code_number, d=dwDebugEventCode_handlers): + def wrapper(f): + d[code_number] = (f) + return f + return wrapper def __init__(self, target): # Todo: accept PID / String / WinProcess self.target = target winproxy.DebugActiveProcess(target.pid) - self._handle_initial_debug_event() - def _handle_initial_debug_event(self): - pass + self.processes = {} + self.threads = {} + self.current_process = None + self.current_thread = None def _debug_event_generator(self): while True: @@ -55,9 +52,84 @@ class Debugger(object): winproxy.ContinueDebugEvent(event.dwProcessId, event.dwThreadId, action) def loop(self): - for x, i in enumerate(self._debug_event_generator()): - print(i, i.code) - self._finish_debug_event(i, windef.DBG_CONTINUE) + for x, debug_event in enumerate(self._debug_event_generator()): + #print(debug_event, debug_event.code) + self._dispatch_debug_event(debug_event) + self._finish_debug_event(debug_event, windef.DBG_CONTINUE) # TODO: exit on process exit - if x == 100: - break + + def _update_debugger_state(self, debug_event): + self.current_process = self.processes[debug_event.dwProcessId] + self.current_thread = self.threads[debug_event.dwThreadId] + + def _dispatch_debug_event(self, debug_event): + handler = self.dwDebugEventCode_handlers.get(debug_event.dwDebugEventCode, self._handle_unknown_debug_event) + return handler(self, debug_event) + + @staticmethod + def _handle_unknown_debug_event(self, debug_event): + raise NotImplementedError("dwDebugEventCode = {0}".format(debug_event.dwDebugEventCode)) + + @handle_dwDebugEventCode(EXCEPTION_DEBUG_EVENT) + def _handle_exception(self, debug_event): + print("_handle_exception") + self._update_debugger_state(debug_event) + + @handle_dwDebugEventCode(CREATE_THREAD_DEBUG_EVENT) + def _handle_create_thread(self, debug_event): + print("_handle_create_thread") + create_thread = debug_event.u.CreateThread + self.current_thread = WinThread._from_handle(create_thread.hThread) + self.threads[self.current_thread.tid] = self.current_thread + + @handle_dwDebugEventCode(CREATE_PROCESS_DEBUG_EVENT) + def _handle_create_process(self, debug_event): + print("_handle_create_process") + create_process = debug_event.u.CreateProcessInfo + + self.current_process = WinProcess._from_handle(create_process.hProcess) + self.current_thread = WinThread._from_handle(create_process.hThread) + # TODO: verif debug_event.dwProcessId for REAL process creation :) + # Voir ce qu'on fout en current ? le parent ? (!le fils ?) + self.threads[self.current_thread.tid] = self.current_thread + self.processes[self.current_process.pid] = self.current_process + self._update_debugger_state(debug_event) + + + @handle_dwDebugEventCode(EXIT_PROCESS_DEBUG_EVENT) + def _handle_exit_process(self, debug_event): + self._update_debugger_state(debug_event) + del self.processes[self.current_process.pid] + print("Remove PID {0}".format(self.current_process.pid)) + print("Bye") + exit() + + @handle_dwDebugEventCode(EXIT_THREAD_DEBUG_EVENT) + def _handle_exit_thread(self, debug_event): + self._update_debugger_state(debug_event) + del self.threads[self.current_thread.tid] + print("Remove TID {0}".format(self.current_thread.tid)) + + @handle_dwDebugEventCode(LOAD_DLL_DEBUG_EVENT) + def _handle_load_dll(self, debug_event): + self._update_debugger_state(debug_event) + load_dll = debug_event.u.LoadDll + print("_handle_load_dll") + + @handle_dwDebugEventCode(UNLOAD_DLL_DEBUG_EVENT) + def _handle_unload_dll(self, debug_event): + self._update_debugger_state(debug_event) + pass + print("_handle_unload_dll") + + @handle_dwDebugEventCode(OUTPUT_DEBUG_STRING_EVENT) + def _handle_output_debug_string(self, debug_event): + self._update_debugger_state(debug_event) + pass + print("_handle_output_debug_string") + + @handle_dwDebugEventCode(RIP_EVENT) + def _handle_rip(self, debug_event): + self._update_debugger_state(debug_event) + pass + print("_handle_rip") diff --git a/windows/generated_def/winfuncs.py b/windows/generated_def/winfuncs.py index cdbda73..b5a5267 100644 --- a/windows/generated_def/winfuncs.py +++ b/windows/generated_def/winfuncs.py @@ -3,7 +3,7 @@ from ctypes import * from ctypes.wintypes import * from .winstructs import * -functions = ['ExitProcess', 'TerminateProcess', 'GetLastError', 'GetCurrentProcess', 'CreateFileA', 'CreateFileW', 'NtQuerySystemInformation', 'NtQueryInformationProcess', 'NtQueryVirtualMemory', 'NtCreateThreadEx', 'NtQueryInformationThread', 'GetExitCodeThread', 'GetExitCodeProcess', 'VirtualAlloc', 'VirtualAllocEx', 'VirtualFree', 'VirtualFreeEx', 'VirtualProtect', 'VirtualQuery', 'VirtualQueryEx', 'GetModuleFileNameA', 'GetModuleFileNameW', 'CreateThread', 'CreateRemoteThread', 'VirtualProtect', 'CreateProcessA', 'CreateProcessW', 'GetThreadContext', 'NtGetContextThread', 'SetThreadContext', 'OpenThread', 'OpenProcess', 'CloseHandle', 'ReadProcessMemory', 'NtWow64ReadVirtualMemory64', 'WriteProcessMemory', 'CreateToolhelp32Snapshot', 'Thread32First', 'Thread32Next', 'Process32First', 'Process32Next', 'Process32FirstW', 'Process32NextW', 'GetProcAddress', 'LoadLibraryA', 'LoadLibraryW', 'OpenProcessToken', 'LookupPrivilegeValueA', 'LookupPrivilegeValueW', 'AdjustTokenPrivileges', 'FindResourceA', 'FindResourceW', 'SizeofResource', 'LoadResource', 'LockResource', 'GetVersionExA', 'GetVersionExW', 'GetVersion', 'GetCurrentThread', 'GetCurrentThreadId', 'GetCurrentProcessorNumber', 'AllocConsole', 'FreeConsole', 'GetStdHandle', 'SetStdHandle', 'SetThreadAffinityMask', 'WriteFile', 'GetExtendedTcpTable', 'GetExtendedUdpTable', 'SetTcpEntry', 'AddVectoredContinueHandler', 'AddVectoredExceptionHandler', 'TerminateThread', 'ExitThread', 'RemoveVectoredExceptionHandler', 'ResumeThread', 'SuspendThread', 'WaitForSingleObject', 'GetThreadId', 'LoadLibraryExA', 'LoadLibraryExW', 'SymInitialize', 'SymFromName', 'SymLoadModuleEx', 'SymSetOptions', 'SymGetTypeInfo', 'DeviceIoControl', 'GetTokenInformation', 'RegOpenKeyExA', 'RegOpenKeyExW', 'RegGetValueA', 'RegGetValueW', 'RegCloseKey', 'Wow64DisableWow64FsRedirection', 'Wow64RevertWow64FsRedirection', 'Wow64EnableWow64FsRedirection', 'Wow64GetThreadContext', 'SetConsoleCtrlHandler', 'WinVerifyTrust', 'GlobalAlloc', 'GlobalFree', 'GlobalUnlock', 'GlobalLock', 'OpenClipboard', 'EmptyClipboard', 'CloseClipboard', 'SetClipboardData', 'GetClipboardData', 'EnumClipboardFormats', 'GetClipboardFormatNameA', 'GetClipboardFormatNameW', 'WinVerifyTrust', 'OpenProcessToken', 'OpenThreadToken', 'GetTokenInformation', 'SetTokenInformation', 'GetSidIdentifierAuthority', 'GetSidSubAuthority', 'GetSidSubAuthorityCount', 'DebugBreak', 'WaitForDebugEvent', 'ContinueDebugEvent', 'DebugActiveProcess', 'DebugActiveProcessStop', 'DebugSetProcessKillOnExit', 'DebugBreakProcess'] +functions = ['ExitProcess', 'TerminateProcess', 'GetLastError', 'GetCurrentProcess', 'CreateFileA', 'CreateFileW', 'NtQuerySystemInformation', 'NtQueryInformationProcess', 'NtQueryVirtualMemory', 'NtCreateThreadEx', 'NtQueryInformationThread', 'GetExitCodeThread', 'GetExitCodeProcess', 'VirtualAlloc', 'VirtualAllocEx', 'VirtualFree', 'VirtualFreeEx', 'VirtualProtect', 'VirtualQuery', 'VirtualQueryEx', 'GetModuleFileNameA', 'GetModuleFileNameW', 'CreateThread', 'CreateRemoteThread', 'VirtualProtect', 'CreateProcessA', 'CreateProcessW', 'GetThreadContext', 'NtGetContextThread', 'SetThreadContext', 'OpenThread', 'OpenProcess', 'CloseHandle', 'ReadProcessMemory', 'NtWow64ReadVirtualMemory64', 'WriteProcessMemory', 'CreateToolhelp32Snapshot', 'Thread32First', 'Thread32Next', 'Process32First', 'Process32Next', 'Process32FirstW', 'Process32NextW', 'GetProcAddress', 'LoadLibraryA', 'LoadLibraryW', 'OpenProcessToken', 'LookupPrivilegeValueA', 'LookupPrivilegeValueW', 'AdjustTokenPrivileges', 'FindResourceA', 'FindResourceW', 'SizeofResource', 'LoadResource', 'LockResource', 'GetVersionExA', 'GetVersionExW', 'GetVersion', 'GetCurrentThread', 'GetCurrentThreadId', 'GetCurrentProcessorNumber', 'AllocConsole', 'FreeConsole', 'GetStdHandle', 'SetStdHandle', 'SetThreadAffinityMask', 'WriteFile', 'GetExtendedTcpTable', 'GetExtendedUdpTable', 'SetTcpEntry', 'AddVectoredContinueHandler', 'AddVectoredExceptionHandler', 'TerminateThread', 'ExitThread', 'RemoveVectoredExceptionHandler', 'ResumeThread', 'SuspendThread', 'WaitForSingleObject', 'GetThreadId', 'LoadLibraryExA', 'LoadLibraryExW', 'SymInitialize', 'SymFromName', 'SymLoadModuleEx', 'SymSetOptions', 'SymGetTypeInfo', 'DeviceIoControl', 'GetTokenInformation', 'RegOpenKeyExA', 'RegOpenKeyExW', 'RegGetValueA', 'RegGetValueW', 'RegCloseKey', 'Wow64DisableWow64FsRedirection', 'Wow64RevertWow64FsRedirection', 'Wow64EnableWow64FsRedirection', 'Wow64GetThreadContext', 'SetConsoleCtrlHandler', 'WinVerifyTrust', 'GlobalAlloc', 'GlobalFree', 'GlobalUnlock', 'GlobalLock', 'OpenClipboard', 'EmptyClipboard', 'CloseClipboard', 'SetClipboardData', 'GetClipboardData', 'EnumClipboardFormats', 'GetClipboardFormatNameA', 'GetClipboardFormatNameW', 'WinVerifyTrust', 'OpenProcessToken', 'OpenThreadToken', 'GetTokenInformation', 'SetTokenInformation', 'GetSidIdentifierAuthority', 'GetSidSubAuthority', 'GetSidSubAuthorityCount', 'DebugBreak', 'WaitForDebugEvent', 'ContinueDebugEvent', 'DebugActiveProcess', 'DebugActiveProcessStop', 'DebugSetProcessKillOnExit', 'DebugBreakProcess', 'GetProcessId'] # ExitProcess(uExitCode): ExitProcessPrototype = WINFUNCTYPE(VOID, UINT) @@ -509,3 +509,7 @@ DebugSetProcessKillOnExitParams = ((1, 'KillOnExit'),) DebugBreakProcessPrototype = WINFUNCTYPE(BOOL, HANDLE) DebugBreakProcessParams = ((1, 'Process'),) +# GetProcessId(Process): +GetProcessIdPrototype = WINFUNCTYPE(DWORD, HANDLE) +GetProcessIdParams = ((1, 'Process'),) + diff --git a/windows/winobject.py b/windows/winobject.py index d17447f..4abef20 100644 --- a/windows/winobject.py +++ b/windows/winobject.py @@ -512,6 +512,14 @@ class WinProcess(PROCESSENTRY32, Process): is_pythondll_injected = 0 is_remote_slave_running = False + @staticmethod + def _from_handle(handle): + pid = winproxy.GetProcessId(handle) + proc = [p for p in windows.system.processes if p.pid == pid][0] + proc._handle = handle + return proc + + @utils.fixedpropety def name(self): """Name of the process @@ -572,6 +580,23 @@ class WinProcess(PROCESSENTRY32, Process): self.low_read_memory(addr, ctypes.byref(buffer), size) return buffer[:] + def read_char(self, addr): + sizeof_char = sizeof(CHAR) + return struct.unpack("