def _handle_create_process(self, debug_event): """Handle CREATE_PROCESS_DEBUG_EVENT""" create_process = debug_event.u.CreateProcessInfo # Duplicate handle, so garbage collection of the process/thread does not # break the debug API invariant (those x_event handle are close by the debug API itself) proc_handle = HANDLE() thread_handle = HANDLE() cp_handle = windows.current_process.handle winproxy.DuplicateHandle(cp_handle, create_process.hProcess, cp_handle, ctypes.byref(proc_handle), dwOptions=DUPLICATE_SAME_ACCESS) winproxy.DuplicateHandle(cp_handle, create_process.hThread, cp_handle, ctypes.byref(thread_handle), dwOptions=DUPLICATE_SAME_ACCESS) dbgprint( " Got PROC handle {0:#x}".format(create_process.hProcess, self), "HANDLE") dbgprint(" PROC handle duplicated: {0:#x}".format(proc_handle.value), "HANDLE") dbgprint( " Got THREAD handle {0:#x}".format(create_process.hThread, self), "HANDLE") dbgprint( " THREAD handle duplicated: {0:#x}".format(thread_handle.value), "HANDLE") self.current_process = WinProcess._from_handle(proc_handle.value) self.current_thread = WinThread._from_handle(thread_handle.value) dbgprint("New process: {0}".format(self.current_process), "DBG") self.threads[self.current_thread.tid] = self.current_thread self._explicit_single_step[self.current_thread.tid] = False self._hardware_breakpoint[self.current_thread.tid] = {} self._breakpoint_to_reput[self.current_thread.tid] = [] self.processes[self.current_process.pid] = self.current_process self._watched_pages[self.current_process.pid] = {} #defaultdict(list) self.breakpoints[self.current_process.pid] = {} self._memory_save[self.current_process.pid] = {} self._module_by_process[self.current_process.pid] = {} self._update_debugger_state(debug_event) self._add_exe_to_module_list(create_process) self._setup_pending_breakpoints_new_process(self.current_process) self._setup_pending_breakpoints_new_thread(self.current_thread) with self.DisabledMemoryBreakpoint(): try: return self.on_create_process(create_process) finally: if create_process.hFile: winproxy.CloseHandle(create_process.hFile)
def enumerate_processes(): dbgprint("Enumerating processes with CreateToolhelp32Snapshot", "SLOW") process_entry = gdef.PROCESSENTRY32() process_entry.dwSize = ctypes.sizeof(process_entry) snap = winproxy.CreateToolhelp32Snapshot(gdef.TH32CS_SNAPPROCESS, 0) winproxy.Process32First(snap, process_entry) res = [] res.append(process.WinProcess._from_PROCESSENTRY32(process_entry)) while winproxy.Process32Next(snap, process_entry): res.append(process.WinProcess._from_PROCESSENTRY32(process_entry)) winproxy.CloseHandle(snap) return res
def enumerate_threads_generator(): # Ptet dangereux, parce que on yield la meme THREADENTRY32 a chaque fois dbgprint("Enumerating threads with CreateToolhelp32Snapshot <generator>", "SLOW") thread_entry = gdef.THREADENTRY32() thread_entry.dwSize = ctypes.sizeof(thread_entry) snap = winproxy.CreateToolhelp32Snapshot(gdef.TH32CS_SNAPTHREAD, 0) dbgprint("New handle CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD) <generator> | {0:#x}".format(snap), "HANDLE") try: winproxy.Thread32First(snap, thread_entry) yield thread_entry while winproxy.Thread32Next(snap, thread_entry): yield thread_entry finally: winproxy.CloseHandle(snap) dbgprint("CLOSE CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD) <generator> | {0:#x}".format(snap), "HANDLE")
def enumerate_threads_setup_owners(self): # Enumerating threads is a special operation concerning the owner process. # We may not be able to retrieve the name of the owning process by normal way # (as we need to get a handle on the process) # So, this implementation of enumerate_thread also setup the owner with the result of enumerate_processes dbgprint( "Enumerating threads with CreateToolhelp32Snapshot and setup owner", "SLOW") # One snap for both enum to be prevent race snap = winproxy.CreateToolhelp32Snapshot( windef.TH32CS_SNAPTHREAD | windef.TH32CS_SNAPPROCESS, 0) process_entry = PROCESSENTRY32() process_entry.dwSize = ctypes.sizeof(process_entry) winproxy.Process32First(snap, process_entry) processes = [] processes.append( process.WinProcess._from_PROCESSENTRY32(process_entry)) while winproxy.Process32Next(snap, process_entry): processes.append( process.WinProcess._from_PROCESSENTRY32(process_entry)) # Forge a dict pid -> process proc_dict = {proc.pid: proc for proc in processes} thread_entry = THREADENTRY32() thread_entry.dwSize = ctypes.sizeof(thread_entry) threads = [] winproxy.Thread32First(snap, thread_entry) parent = proc_dict[thread_entry.th32OwnerProcessID] threads.append( process.WinThread._from_THREADENTRY32(thread_entry, owner=parent)) while winproxy.Thread32Next(snap, thread_entry): parent = proc_dict[thread_entry.th32OwnerProcessID] threads.append( process.WinThread._from_THREADENTRY32(thread_entry, owner=parent)) winproxy.CloseHandle(snap) return threads
def _handle_load_dll(self, debug_event): """Handle LOAD_DLL_DEBUG_EVENT""" self._update_debugger_state(debug_event) load_dll = debug_event.u.LoadDll dll = self._get_loaded_dll(load_dll) dll_name = os.path.basename(dll).lower() if dll_name.endswith(".dll"): dll_name = dll_name[:-4] # Mais c'est debile.. # Si j'ai ntdll et ntdll64: les deux vont avoir le meme nom.. if dll_name.endswith(".dll64"): 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._setup_pending_breakpoints_load_dll(dll_name) with self.DisabledMemoryBreakpoint(): try: return self.on_load_dll(load_dll) finally: if load_dll.hFile: winproxy.CloseHandle(load_dll.hFile)
def __del__(self): if self.dwProcessId == current_process_pid: return if hasattr(self, "_local_handle"): return winproxy.CloseHandle(self._local_handle)
def __del__(self): winproxy.CloseHandle(self.file_handle) self.secondary_signatures.clear()
def __del__(self): if hasattr(self, "_handle") and self._handle: winproxy.CloseHandle(self._handle)