def install_hook(self, mod_name, new_address, name=None, ordinal=None): if not (bool(name) ^ bool(ordinal)): raise ValueError('must select either name or ordinal, not both') image_import_descriptors = self.get_proc_attribute('image_import_descriptor') image_dos_header_addr = self.get_proc_attribute('image_dos_header_addr') is_ordinal = lambda x: bool(x & 0x80000000) for iid in image_import_descriptors: cur_mod_name = self._get_name_for_image_import_descriptor(iid) if cur_mod_name.lower() != mod_name.lower(): continue ilt = self._get_ilt_for_image_import_descriptor(iid) iat = self._get_iat_for_image_import_descriptor(iid) for idx in range(len(ilt)): if ilt[idx] is None: continue hook_it = False if not is_ordinal(ilt[idx]) and name: cur_func_name = self._get_name_for_ilt_entry(ilt[idx]) if cur_func_name == name: hook_it = True elif is_ordinal(ilt[idx]) and ordinal: cur_func_ordinal = self._get_ordinal_for_ilt_entry(ilt[idx]) if cur_func_ordinal == ordinal: hook_it = True if hook_it: old_address = iat[idx] iat_ent_addr = image_dos_header_addr iat_ent_addr += iid.FirstThunk iat_ent_addr += (ctypes.sizeof(ctypes.c_void_p) * idx) new_addr = ctypes.c_void_p() new_addr.value = new_address written = wintypes.DWORD() if m_k32.WriteProcessMemory(self.handle, iat_ent_addr, ctypes.byref(new_addr), ctypes.sizeof(new_addr), ctypes.byref(written)) == 0: errno = m_k32.GetLastError() if errno == 998: errno = 0 old_permissions = wintypes.DWORD() if (m_k32.VirtualProtectEx(self.handle, iat_ent_addr, 0x400, flags('PAGE_READWRITE'), ctypes.byref(old_permissions)) == 0): raise WindowsProcessError('Error: VirtualProtectEx', get_last_error=m_k32.GetLastError()) if m_k32.WriteProcessMemory(self.handle, iat_ent_addr, ctypes.byref(new_addr), ctypes.sizeof(new_addr), ctypes.byref(written)) == 0: errno = m_k32.GetLastError() self.protect(iat_ent_addr, permissions=old_permissions) if errno: raise WindowsProcessError('Error: WriteProcessMemory', get_last_error=errno) hook = Hook('iat', iat_ent_addr, old_address, new_address) self._installed_hooks.append(hook) return hook raise ProcessError('failed to find location to install hook')
def from_named_pipe(cls, name, buffer_size=4096, default_timeout=100, max_instances=5): handle = m_k32.CreateNamedPipeW( '\\\\.\\pipe\\' + name, # _In_ LPCTSTR lpName PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, # _In_ DWORD dwOpenMode PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, # _In_ DWORD dwPipeMode max_instances, # _In_ DWORD nMaxInstances buffer_size, # _In_ DWORD nInBufferSize buffer_size, # _In_ DWORD nOutBufferSize default_timeout, # _In_ DWORD nDefaultTimeout None # _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes ) if handle == INVALID_HANDLE_VALUE: raise ctypes.WinError() success = lambda: cls(handle, buffer_size=buffer_size) overlapped = wintypes.OVERLAPPED() overlapped.hEvent = m_k32.CreateEventW(None, True, False, None) if m_k32.ConnectNamedPipe(handle, ctypes.byref(overlapped)): m_k32.CloseHandle(overlapped.hEvent) return success() error = m_k32.GetLastError() if error == ERROR_IO_PENDING and _wait_overlapped_io(overlapped, default_timeout): m_k32.CloseHandle(overlapped.hEvent) return success() m_k32.CloseHandle(overlapped.hEvent) if error == ERROR_PIPE_CONNECTED: return success() m_k32.CloseHandle(handle) raise ctypes.WinError()
def start_thread(self, address, targ=None): handle = m_k32.CreateRemoteThread(self.handle, None, 0, address, targ, 0, None) if handle == 0: raise WindowsProcessError('Error: CreateRemoteThread', get_last_error=m_k32.GetLastError()) return handle
def protect(self, address, permissions=None, size=0x400): permissions = flags(permissions or 'PAGE_EXECUTE_READWRITE') old_permissions = wintypes.DWORD() if (m_k32.VirtualProtectEx(self.handle, address, size, permissions, ctypes.byref(old_permissions)) == 0): raise WindowsProcessError('Error: VirtualProtectEx', get_last_error=m_k32.GetLastError()) return
def read_memory(self, address, size=0x400): _data = (ctypes.c_byte * size) data = _data() if (m_k32.ReadProcessMemory(self.handle, address, ctypes.byref(data), ctypes.sizeof(data), 0) == 0): raise WindowsProcessError('Error: ReadProcessMemory', get_last_error=m_k32.GetLastError()) return ctarray_to_bytes(data)
def write_memory(self, address, data): if isinstance(data, str): data = data.encode('utf-8') _wr_data = (ctypes.c_char * len(data)) wr_data = _wr_data() wr_data.value = data written = wintypes.SIZE_T() if not m_k32.WriteProcessMemory(self.handle, address, ctypes.byref(wr_data), ctypes.sizeof(wr_data), ctypes.byref(written)): raise WindowsProcessError('Error: WriteProcessMemory', get_last_error=m_k32.GetLastError()) return
def read(self): ctarray = (ctypes.c_byte * self.buffer_size)() bytes_read = wintypes.DWORD(0) overlapped = wintypes.OVERLAPPED() overlapped.hEvent = m_k32.CreateEventW(None, True, False, None) if m_k32.ReadFile(self.handle, ctypes.byref(ctarray), self.buffer_size, ctypes.byref(bytes_read), ctypes.byref(overlapped)): return utilities.ctarray_to_bytes(ctarray)[:bytes_read.value] error = m_k32.GetLastError() if error == ERROR_IO_PENDING and _wait_overlapped_io(overlapped): return utilities.ctarray_to_bytes(ctarray)[:overlapped.InternalHigh] if error == ERROR_BROKEN_PIPE: return None raise ctypes.WinError()
def process_is_wow64(handle=None): """ Determine whether the process associated with the handle is running in WOW64 or not. :param int handle: A handle to the process to check. :return: Whether the process is running in WOW64 or not. :rtype: bool """ if not hasattr(m_k32, 'IsWow64Process'): return False handle = (handle or -1) is_wow64 = ctypes.c_bool() if not m_k32.IsWow64Process(handle, ctypes.byref(is_wow64)): raise WindowsProcessError('Error: IsWow64Process', get_last_error=m_k32.GetLastError()) return is_wow64.value
def free(self, address): free_type = flags('MEM_RELEASE') if (m_k32.VirtualFreeEx(self.handle, address, 0, free_type) == 0): raise WindowsProcessError('Error: VirtualFreeEx', get_last_error=m_k32.GetLastError()) return