def load_module(self, path=None, data=None) -> PeFile: """ Load a module into the speakeasy emulator args: path: Path to file to load into the emulation space data: Raw data to load as a module into the emulation space return: A PeFile object representing the newly loaded module """ if not path and not data: raise SpeakeasyError('No emulation target supplied') if path and not os.path.exists(path): raise SpeakeasyError('Target file not found: %s' % (path)) if data: test = data else: with open(path, 'rb') as f: test = f.read(4) self.loaded_bins.append(path) if not self.is_pe(test): raise SpeakeasyError('Target file is not a PE') self._init_emulator(path=path, data=data) return self.emu.load_module(path=path, data=data)
def _init_emulator(self, path=None, data=None, is_raw_code=False) -> None: """ Based on the PE metadata, use the appropriate emulator. That is, a user mode emulator vs a kernel mode emulator """ if not is_raw_code: pe = PeFile(path=path, data=data) # Get the machine type we only support x86/x64 atm mach = MACHINE_TYPE[pe.FILE_HEADER.Machine].split( '_')[-1:][0].lower() if mach not in ('amd64', 'i386'): raise SpeakeasyError('Unsupported architecture: %s' % mach) if pe.is_dotnet(): raise NotSupportedError( '.NET assemblies are not currently supported') if pe.is_driver(): self.emu = WinKernelEmulator(config=self.config, logger=self.logger, debug=self.debug, exit_event=self.exit_event) else: self.emu = Win32Emulator(config=self.config, logger=self.logger, argv=self.argv, debug=self.debug, exit_event=self.exit_event) else: self.emu = Win32Emulator(config=self.config, logger=self.logger, argv=self.argv, debug=self.debug, exit_event=self.exit_event)
def mem_write(self, addr: int, data: bytes) -> None: """ Write bytes to a memory address args: addr: address to write bytes to data: data to write return: None """ try: return self.emu.mem_write(addr, data) except Exception: raise SpeakeasyError("Failed to write %d bytes at address: 0x%x" % (len(data), addr))
def mem_read(self, addr: int, size: int) -> bytes: """ Read bytes from a memory address args: addr: address to read bytes from size: number of bytes to read return: Python bytes object contained the data read """ try: return self.emu.mem_read(addr, size) except Exception: raise SpeakeasyError("Failed to read %d bytes at address: 0x%x" % (size, addr))
def disasm(self, addr: int, size: int, fast=True): """ Get the disassembly from an address args: addr: address to being disassebmly size: number of bytes to include return: A tuple of: (mnemonic, operands, and the full instruction) """ try: return self.emu.get_disasm(addr, size, fast) except Exception: raise SpeakeasyError("Failed to disassemble at address: 0x%x" % (addr))
def wrap(self, *args, **kwargs): if not self.emu: raise SpeakeasyError('Emulator not initialized') return func(self, *args, **kwargs)