def run_shellcode(self, sc_addr, offset=0): """ Begin emulating position independent code (i.e. shellcode) to prepare for emulation """ target = None for sc_path, _sc_addr, size in self.pic_buffers: if _sc_addr == sc_addr: target = _sc_addr break if not target: raise Win32EmuError("Invalid shellcode address") stack_commit = 0x4000 self.stack_base, stack_addr = self.alloc_stack(stack_commit) self.set_func_args(self.stack_base, self.return_hook, 0x7000) run = Run() run.type = "shellcode" run.start_addr = sc_addr + offset run.instr_cnt = 0 args = [ self.mem_map(1024, tag="emu.shellcode_arg_%d" % (i), base=0x41420000 + i) for i in range(4) ] run.args = args self.reg_write(_arch.X86_REG_ECX, 1024) self.add_run(run) # Create an empty process object for the shellcode if none is # supplied container = self.init_container_process() if container: self.processes.append(container) self.curr_process = container else: p = objman.Process(self) self.processes.append(p) self.curr_process = p mm = self.get_address_map(sc_addr) if mm: mm.set_process(self.curr_process) t = objman.Thread(self, stack_base=self.stack_base, stack_commit=stack_commit) self.om.objects.update({t.address: t}) self.curr_process.threads.append(t) self.curr_thread = t peb = self.alloc_peb(self.curr_process) # Set the TEB self.init_teb(t, peb) self.start()
def init_processes(self, processes): for proc in processes: p = objman.Process(self) self.add_object(p) p.name = proc.get('name', '') p.pid = proc.get('pid') if p.name.lower() == 'system': p.pid = 4 p.path = 'System' if not p.pid: p.pid = self.om.new_id() base = proc.get('base_addr') if isinstance(base, str): base = int(base, 16) p.base = base if not p.path: p.path = proc.get('path') p.image = ntpath.basename(p.path) # Create an initial thread for each process t = objman.Thread(self) self.add_object(t) t.process = p p.threads.append(t) self.processes.append(p) # The SYSTEM process should be the starting context sp = [p for p in self.processes if p.name.lower() == 'system'] if sp: sp = sp[0] self.set_current_process(sp)
def init_container_process(self): """ Create a process to be used to host shellcode or DLLs """ for p in self.config_processes: if p.get('is_main_exe'): name = p.get('name', '') emu_path = p.get('path', '') base = p.get('base_addr', 0) if isinstance(base, str): base = int(base, 0) cmd_line = p.get('command_line', '') proc = objman.Process(self, name=name, path=emu_path, base=base, cmdline=cmd_line) return proc return None
def init_container_process(self): """ Create a process to be used to host shellcode or DLLs """ for p in self.config_processes: if p.get("is_main_exe"): name = p.get("name", "") emu_path = p.get("path", "") base = p.get("base_addr", 0) if isinstance(base, str): base = int(base, 0) cmd_line = p.get("command_line", "") proc = objman.Process( self, name=name, path=emu_path, base=base, cmdline=cmd_line ) return proc return None
def init_processes(self, processes): """ Initialize configured processes set in the emulator config """ for proc in processes: p = objman.Process(self) self.add_object(p) p.name = proc.get('name', '') new_pid = proc.get('pid') if new_pid: p.pid = new_pid base = proc.get('base_addr') if isinstance(base, str): base = int(base, 16) p.base = base p.path = proc.get('path') p.session = proc.get('session', 0) p.image = ntpath.basename(p.path) self.processes.append(p)
def run_module(self, module, all_entrypoints=False): """ Begin emulating a previously loaded module Arguments: module: Module to emulate """ if not module: self.stop() raise Win32EmuError('Module not found') # Check if any TLS callbacks exist, these run before the module's entry point tls = module.get_tls_callbacks() for i, cb_addr in enumerate(tls): base = module.get_base() if base < cb_addr < base + module.get_image_size(): run = Run() run.start_addr = cb_addr run.type = 'tls_callback_%d' % (i) run.args = [base, DLL_PROCESS_ATTACH, 0] self.add_run(run) # Queue up the module's main entry point ep = module.base + module.ep run = Run() run.start_addr = ep main_exe = None if not module.is_exe(): run.args = [module.base, DLL_PROCESS_ATTACH, 0] run.type = 'dll_entry.DLL_PROCESS_ATTACH' container = self.init_container_process() if container: self.processes.append(container) self.curr_process = container else: run.type = 'module_entry' main_exe = module run.args = [ self.mem_map(8, tag='emu.module_arg_%d' % (i)) for i in range(4) ] if main_exe: self.user_modules = [main_exe] + self.user_modules self.add_run(run) if all_entrypoints: # Only emulate a subset of all the exported functions # There are some modules (such as the windows kernel) with # thousands of exports exports = [ k for k in module.get_exports()[:MAX_EXPORTS_TO_EMULATE] ] if exports: args = [ self.mem_map(8, tag='emu.export_arg_%d' % (i), base=0x41420000) for i in range(4) ] # noqa for exp in exports: if exp.name in ('DllMain', 'ServiceMain'): continue run = Run() if exp.name: fn = exp.name else: fn = 'no_name' run.type = 'export.%s' % (fn) run.start_addr = exp.address # Here we set dummy args to pass into the export function run.args = args # Store these runs and only queue them before the unload # routine this is because some exports may not be ready to # be called yet self.add_run(run) # Create an empty process object for the module if none is # supplied if len(self.processes) == 0: p = objman.Process(self, path=module.get_emu_path(), base=module.base, pe=module, cmdline=self.command_line) self.curr_process = p self.om.objects.update({p.address: p}) mm = self.get_address_map(module.base) if mm: mm.process = self.curr_process t = objman.Thread(self, stack_base=self.stack_base, stack_commit=module.stack_commit) self.om.objects.update({t.address: t}) self.curr_process.threads.append(t) self.curr_thread = t peb = self.alloc_peb(self.curr_process) # Set the TEB self.init_teb(t, peb) # Begin emulation self.start()
def run_module(self, module, all_entrypoints=False, emulate_children=False, entrypoints=None): """ Begin emulating a previously loaded module Arguments: module: Module to emulate """ if entrypoints is None: entrypoints = [] self.prepare_module_for_emulation(module, all_entrypoints, entrypoints) # Create an empty process object for the module if none is # supplied, only do this for the main module if len(self.processes) == 0: p = objman.Process( self, path=module.get_emu_path(), base=module.base, pe=module, cmdline=self.command_line, ) self.curr_process = p self.om.objects.update({p.address: p}) mm = self.get_address_map(module.base) if mm: mm.process = self.curr_process t = objman.Thread( self, stack_base=self.stack_base, stack_commit=module.stack_commit ) self.om.objects.update({t.address: t}) self.curr_process.threads.append(t) self.curr_thread = t peb = self.alloc_peb(self.curr_process) # Set the TEB self.init_teb(t, peb) # Begin emulation of main module self.start() if not emulate_children or len(self.child_processes) == 0: return # Emulate any child processes while len(self.child_processes) > 0: child = self.child_processes.pop(0) child.pe = self.load_module(data=child.pe_data, first_time_setup=False) self.prepare_module_for_emulation(child.pe, all_entrypoints, entrypoints) self.command_line = child.cmdline self.curr_process = child self.curr_process.base = child.pe.base self.curr_thread = child.threads[0] self.om.objects.update({self.curr_thread.address: self.curr_thread}) # PEB and TEB will be initialized when the next run happens self.start() return