def LocalAlloc(self, proc, argv, ctx={}): ''' DECLSPEC_ALLOCATOR HLOCAL LocalAlloc( UINT uFlags, SIZE_T uBytes ); ''' flag, size = argv pMem = self.win_emu.mem_manager.alloc_heap(proc.proc_default_heap, size) hnd = ObjectManager.create_new_object('EmLMEM', pMem, size, flag) if flag and 0x0: # LMEM_FIXED lMem_obj = ObjectManager.get_obj_by_handle(hnd) lMem_obj.handle = hnd return hnd
def LocalLock(self, proc, argv, ctx={}): ''' LPVOID LocalLock( HLOCAL hMem ); ''' lmem_handle, = argv lMem_obj = ObjectManager.get_obj_by_handle(lmem_handle) return lMem_obj.base
def create_heap(self, pid, size, max_size, option=None) -> Heap: block = self.find_block_from_pid(pid) if not block: return -1 if max_size: size = max_size if size % PAGE_SIZE != 0: #Upperbound size += (PAGE_SIZE - size % PAGE_SIZE) page_protect = PageProtect.PAGE_READWRITE if option == HeapOption.HEAP_CREATE_ENABLE_EXECUTE: page_protect = PageProtect.PAGE_EXECUTE_READWRITE _p_region = self.alloc_page( pid, size=size, allocation_type=PageAllocationType.MEM_COMMIT, protect=page_protect) hHeap = ObjectManager.create_new_object('Heap', pid, option, _p_region, True) else: if size % PAGE_SIZE != 0: #Upperbound size += (PAGE_SIZE - size % PAGE_SIZE) page_protect = PageProtect.PAGE_READWRITE if option == HeapOption.HEAP_CREATE_ENABLE_EXECUTE: page_protect = PageProtect.PAGE_EXECUTE_READWRITE _p_region = self.alloc_page( pid, size=size, allocation_type=PageAllocationType.MEM_COMMIT, protect=page_protect) hHeap = ObjectManager.create_new_object('Heap', pid, option, _p_region, False) heap = ObjectManager.get_obj_by_handle(hHeap) heap.set_handle(hHeap) self.add_heap_list(block, heap) return heap
def destroy_heap(self, handle): heap = ObjectManager.get_obj_by_handle(handle) block = self.find_block_from_pid(heap.pid) if not block: return -1 for heaps in heap.heap_space: self.unmap_process_vas(block["proc_obj"], heaps) self.delete_heap_from_list(block, heap) pass
def LocalSize(self, proc, argv, ctx={}): ''' SIZE_T LocalSize( HLOCAL hMem ); ''' lmem_handle, = argv lMem_obj = ObjectManager.get_obj_by_handle(lmem_handle) return lMem_obj.size
def LocalFlags(self, proc, argv, ctx={}): ''' UINT LocalFlags( HLOCAL hMem ); ''' lmem_handle, = argv lMem_obj = ObjectManager.get_obj_by_handle(lmem_handle) return lMem_obj.flags
def LocalFree(self, proc, argv, ctx={}): ''' HLOCAL LocalFree( _Frees_ptr_opt_ HLOCAL hMem ); ''' lmem_handle, = argv lMem_obj = ObjectManager.get_obj_by_handle(lmem_handle) self.win_emu.mem_manager.free_heap(proc.proc_default_heap, lMem_obj.base) return 0
def CreateProcess(self, proc, argv, ctx={}): '''BOOL CreateProcess( LPTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation );''' app, cmd, pa, ta, inherit, flags, env, cd, si, ppi = argv cw = self.get_char_width(ctx) cmdstr = '' appstr = '' if app: appstr = proc.read_string(app, cw) argv[0] = appstr if cmd: cmdstr = proc.read_string(cmd, cw) argv[1] = cmdstr if not appstr and cmdstr: appstr = cmdstr elif appstr and cmdstr: appstr += " " + cmdstr # cmdstr be param elif appstr and not cmdstr: pass else: return 0 # child proc can't be inherited new_proc_obj, hProc, hThread = self.win_emu.create_process(appstr) main_thread = ObjectManager.get_obj_by_handle(hThread) EmuProcManager.push_wait_queue(new_proc_obj.pid, new_proc_obj) _pi = self.k32types.PROCESS_INFORMATION(proc.ptr_size) data = common.mem_cast(proc.uc_eng, _pi, ppi) _pi.hProcess = hProc _pi.hThread = hThread _pi.dwProcessId = new_proc_obj.pid _pi.dwThreadId = main_thread.tid proc.write_mem_self(ppi, common.get_bytes(data)) rv = 1 return rv
def __init__(self, parent=None): if not parent: # create new virtual FileSystem self.emu_vfs = WinVFS() self.obj_manager = ObjectManager() self.mem_manager = mem_manager.MemoryManager() else: self.net_manager = parent.net_manager self.obj_manager = parent.obj_manager self.arch = UC_ARCH_X86 self.mode = UC_MODE_32 self.cur_thread = None self.threads = [] self.ctx: CONTEXT = None self.ptr_size = 0 self.api_handler = ApiHandler(self) self.set_ptr_size() self.emu_waiting_queue = [] self.winapi_info_dict = {} self.running_process = None self.__set_emulation_config()
def VirtualFreeEx(self, proc, argv, ctx={}): ''' BOOL VirtualFreeEx( HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType ); ''' proc_handle, base_addr, size, ftype = argv targ_proc_obj = ObjectManager.get_obj_by_handle(proc_handle) self.win_emu.mem_manager.free_page(targ_proc_obj.pid, base_addr, size) return True
def ReadProcessMemory(self, proc, argv, ctx={}): ''' BOOL ReadProcessMemory( HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead ); ''' proc_handle, base_addr, pBuf, size, pRead_sz = argv targ_proc_obj = ObjectManager.get_obj_by_handle(proc_handle) mem_raw = targ_proc_obj.read_mem_self(base_addr, size) proc.write_mem_self(pBuf, mem_raw) proc.write_mem_self(pRead_sz, len(mem_raw).to_bytes(4, "little")) return True
def WriteProcessMemory(self, proc, argv, ctx={}): ''' BOOL WriteProcessMemory( HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten ); ''' proc_handle, base_addr, pData, dwSize, pWritten_sz = argv targ_proc_obj = ObjectManager.get_obj_by_handle(proc_handle) raw_data = proc.read_mem_self(pData, dwSize) targ_proc_obj.write_mem_self(base_addr, bytes(raw_data)) proc.write_mem_self(pWritten_sz, len(raw_data).to_bytes(4, 'little')) return 0x1
def VirtualAllocEx(self, proc, argv, ctx={}): ''' LPVOID VirtualAllocEx( HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect ); ''' proc_handle, base_addr, size, alloc_type, protection = argv targ_proc_obj = ObjectManager.get_obj_by_handle(proc_handle) page_region = self.win_emu.mem_manager.alloc_page( pid=targ_proc_obj.pid, size=size, allocation_type=alloc_type, page_type=PageType.MEM_PRIVATE, alloc_base=base_addr) return page_region.get_base_addr()
def MapViewOfFile(self, proc, argv, ctx={}): ''' LPVOID MapViewOfFile( HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap ); ''' hFileMap, access, offset_high, offset_low, bytes_to_map = argv fmap_obj = ObjectManager.get_obj_by_handle(hFileMap) if bytes_to_map > fmap_obj.maximum_size: return win_const.INVALID_HANDLE_VALUE # map_region = self.win_emu.mem_manager.alloc_page( pid=proc.pid, size=fmap_obj.maximum_size, allocation_type=PageAllocationType.MEM_COMMIT, page_type=fmap_obj.protect) mf = fmap_obj.map_memory_with_file(map_region.get_base_addr(), offset_high, offset_low, bytes_to_map) if not mf["success"]: return win_const.INVALID_HANDLE_VALUE map_region.set_mmf_handle(hFileMap) proc.write_mem_self(map_region.get_base_addr(), mf["data"]) Dispatcher.mmf_counter_tab[hFileMap] = 0 h = proc.uc_eng.hook_add(UC_HOOK_MEM_WRITE, Dispatcher.file_map_dispatcher, (proc, fmap_obj)) fmap_obj.set_dispatcher(h) return map_region.get_base_addr()
def VirtualQueryEx(self, proc, argv, ctx={}): ''' SIZE_T VirtualQueryEx( HANDLE hProcess LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength ); ''' proc_handle, base_addr, pMbi, size = argv targ_proc_obj = ObjectManager.get_obj_by_handle(proc_handle) mbi = k32types.MEMORY_BASIC_INFORMATION(proc.ptr_size) targ_pg_rg = self.win_emu.mem_manager.get_page_region_from_baseaddr( targ_proc_obj, base_addr) mbi.AllocationBase = targ_pg_rg.base_address mbi.AllocationProtect = PageProtect.PAGE_EXECUTE_READWRITE mbi.State = PageAllocationType.MEM_COMMIT mbi.RegionSize = targ_pg_rg.size mbi.Type = targ_pg_rg.page_type targ_proc_obj.mem_write(pMbi, mbi.get_bytes()) return mbi.sizeof()
class WinX86Emu: def __init__(self, parent=None): if not parent: # create new virtual FileSystem self.emu_vfs = WinVFS() self.obj_manager = ObjectManager() self.mem_manager = mem_manager.MemoryManager() else: self.net_manager = parent.net_manager self.obj_manager = parent.obj_manager self.arch = UC_ARCH_X86 self.mode = UC_MODE_32 self.cur_thread = None self.threads = [] self.ctx: CONTEXT = None self.ptr_size = 0 self.api_handler = ApiHandler(self) self.set_ptr_size() self.emu_waiting_queue = [] self.winapi_info_dict = {} self.running_process = None self.__set_emulation_config() def create_new_emu_engine(self): return Uc(UC_ARCH_X86, UC_MODE_32) def init_emulation_environment(self, phy_file_full_path): def split_path(path): sep = "" if "\\" in path: sep = "\\" else: sep = "/" return path.split(sep) def get_basename(file_path): return split_path(file_path)[-1] # creation emulation env self.emu_vfs.create_home_dir(self.emu_home_dir) virtual_file_full_path = emu_path_join( self.emu_home_dir, get_basename(phy_file_full_path).lower()) self.emu_vfs.copy(phy_file_full_path, virtual_file_full_path) self.insert_emulation_processing_queue(virtual_file_full_path) pass def insert_emulation_processing_queue(self, argv): proc_obj = None if isinstance(argv, str): proc_obj, _, _ = self.create_process(argv) # file_path elif isinstance(argv, bytes) or isinstance(bytearray): # TODO: # CreateProcess with SectionHandle or FileHandle pass EmuProcManager.push_wait_queue(proc_obj.pid, proc_obj) pass def launch(self): while not EmuProcManager.is_wait_empty(): po = EmuProcManager.deq_wait_queue() self.running_process = po["obj"] self.resume_thread(self.running_process) pass def resume_thread(self, proc_obj: EmuProcess, tid: int = -1): thread_obj = None pid = proc_obj.pid wait_q = EmuThreadManager.get_wait_queue(pid) while wait_q: tid = -1 if tid == -1: to = EmuThreadManager.deq_wait_queue(pid) thread_obj = to["obj"] tid = thread_obj.tid else: q = wait_q if not q: raise Exception('Fail to resume thread tid : %d' % (tid)) idx = 0 for o in q: if o["tid"] == tid: to = EmuThreadManager.deq_wait_queue(pid, idx) thread_obj = to["obj"] idx += 1 if not thread_obj: raise Exception('Fail to resume thread tid : %d' % (tid)) EmuThreadManager.set_running_thread(pid, tid, thread_obj) thread_obj.setup_context() thread_obj.setup_ldt() try: thread_obj.uc_eng.emu_start(thread_obj.ctx.Eip, 0) except Exception as e: if e.args[0] == UC_ERR_EXCEPTION: thread_obj.uc_eng.emu_stop() elif e.args[0] == UC_ERR_OK: thread_obj.uc_eng.emu_stop() else: print(e) pass # def resume(self): # while len(self.threads) != 0: # em_thread_handle = self.pop_waiting_queue() # em_thread = ObjectManager.get_obj_by_handle(em_thread_handle) # em_thread.setup_context() # em_thread.setup_ldt() # self.running_thread = em_thread # try: # self.emu_suspend_flag = False # em_thread.uc_eng.emu_start(em_thread.ctx.Eip, 0) # except Exception as e: # if e.args[0] == UC_ERR_EXCEPTION: # em_thread.uc_eng.emu_stop() # elif e.args[1] == UC_ERR_OK: # em_thread.uc_eng.emu_stop() def init_vas(self, proc_obj: EmuProcess): # This is actually done by ntoskrnl self.mem_manager.alloc_page( pid=proc_obj.pid, alloc_base=0, size=0x10000, allocation_type=PageAllocationType.MEM_RESERVE) peb_heap = self.mem_manager.create_heap(pid=proc_obj.pid, size=0x2000, max_size=0) peb_base = self.mem_manager.alloc_heap( peb_heap, ntos.PEB(self.ptr_size).sizeof()) proc_default_heap = self.mem_manager.create_heap(pid=proc_obj.pid, size=1024 * 1024, max_size=1024 * 1024) proc_obj.set_peb_heap(peb_heap) proc_obj.set_peb_base(peb_base) proc_obj.set_proc_default_heap(proc_default_heap) pass def load_target_proc(self, proc_obj: EmuProcess): _pe_ = proc_obj.parsed_pe if _pe_.DOS_HEADER.e_magic != struct.unpack("<H", b'MZ')[0]: # pylint: disable=no-member raise Exception("Target file is not PE") image_base = _pe_.OPTIONAL_HEADER.ImageBase size_of_image = _pe_.OPTIONAL_HEADER.SizeOfImage ep = image_base + _pe_.OPTIONAL_HEADER.AddressOfEntryPoint image_pages = self.mem_manager.alloc_page( pid=proc_obj.pid, size=size_of_image, allocation_type=PageAllocationType.MEM_COMMIT | PageAllocationType.MEM_RESERVE, alloc_base=image_base, protect=PageProtect.PAGE_EXECUTE_READWRITE, page_type=PageType.MEM_IMAGE) image_base = image_pages.get_base_addr() proc_obj.set_image_base(image_base) proc_obj.set_ep(ep) pe_image = _pe_.get_memory_mapped_image(ImageBase=image_base) self.mem_manager.write_process_memory(proc_obj.pid, image_base, pe_image) del pe_image def load_import_mods(self, proc_obj: EmuProcess): # will be changed # cur : load all modules that was emulated # todo : load specific modules which recorded in IAT for dll_name in pydll.EMULATED_DLL_LIST: self.load_library(dll_name, proc_obj) def load_library(self, dll_name, proc_obj: EmuProcess): if dll_name not in pydll.SYSTEM_DLL_BASE: dll_name = self.api_handler.api_set_schema(dll_name) if dll_name not in pydll.SYSTEM_DLL_BASE: return 0xFFFFFFFF # Invalid Handle if dll_name not in proc_obj.imports: _sys_dll_init_base = pydll.SYSTEM_DLL_BASE[dll_name] dll_page = self.mem_manager.alloc_page( pid=proc_obj.pid, size=ALLOCATION_GRANULARITY, allocation_type=PageAllocationType.MEM_COMMIT | PageAllocationType.MEM_RESERVE, alloc_base=_sys_dll_init_base, page_type=PageType.MEM_IMAGE) pydll.SYSTEM_DLL_BASE[dll_name] = dll_page.get_base_addr() self.setup_emulated_dllobj(dll_name, proc_obj) # Fake load # overwrite RET at entire dll memory region self.mem_manager.write_process_memory( proc_obj.pid, dll_page.get_base_addr(), b'\xC3' * ALLOCATION_GRANULARITY) self.add_module_to_peb(proc_obj, dll_name) return pydll.SYSTEM_DLL_BASE[dll_name] else: return pydll.SYSTEM_DLL_BASE[dll_name] def setup_emulated_dllobj(self, mod_name, proc_obj: EmuProcess): def igetattr(obj, attr): for a in dir(obj): if a.lower() == attr.lower(): return getattr(obj, a) raise AttributeError if mod_name not in sys.modules: mod_obj = importlib.import_module("pydll." + mod_name) if mod_name not in proc_obj.e_dllobj: proc_obj.add_e_dll_obj(mod_name, igetattr(mod_obj, mod_name)(self)) pass def setup_import_tab(self, proc_obj: EmuProcess): def rewrite_iat_table(uc, first_thunk_etry, addr): addr = struct.pack("I", addr) uc.mem_write(first_thunk_etry, addr) for dll in proc_obj.parsed_pe.DIRECTORY_ENTRY_IMPORT: # pylint: disable=no-member dll_name = dll.dll.decode("ascii").lower().split(".")[0] proc_obj.set_imports(dll_name, []) if dll_name not in pydll.SYSTEM_DLL_BASE: dll_name = self.api_handler.api_set_schema(dll_name) try: dll_base = pydll.SYSTEM_DLL_BASE[dll_name] except: raise Exception("Unsupported DLL") for imp_api in dll.imports: api_name = imp_api.name.decode("ascii") if "msvcp" in dll_name: # MS cpp runtime lib if not proc_obj.pid in self.api_handler.cpp_procedure: self.api_handler.cpp_procedure[proc_obj.pid] = {} self.api_handler.cpp_procedure[proc_obj.pid][ imp_api.address] = api_name else: if dll_name not in proc_obj.imports: proc_obj.set_imports( dll_name, [(api_name, dll_base + imp_api.hint)]) proc_obj.add_imports(dll_name, (api_name, dll_base + imp_api.hint)) proc_obj.set_api_va_dict(dll_base + imp_api.hint, (dll_name, api_name)) rewrite_iat_table(proc_obj.uc_eng, imp_api.address, dll_base + imp_api.hint) pass def init_peb(self, proc_obj: EmuProcess): # create new PEB & PEB_LDR & Process Image LDR_ENTRY peb = ntos.PEB(self.ptr_size) new_ldte = ntos.LDR_DATA_TABLE_ENTRY(self.ptr_size) peb_ldr_data = ntos.PEB_LDR_DATA(self.ptr_size) peb.BeingDebugged = 0 peb.ImageBaseAddress = proc_obj.image_base peb.ProcessHeap = proc_obj.proc_default_heap.get_base_addr() # allocate memory space for PEB and PEB_LDR & Process Image LDR_ENTRY peb.Ldr = self.mem_manager.alloc_heap(proc_obj.peb_heap, peb_ldr_data.sizeof()) pNew_ldte = self.mem_manager.alloc_heap(proc_obj.peb_heap, new_ldte.sizeof()) # setup Process Image LDR_ENTRY new_ldte.SizeOfImage = proc_obj.parsed_pe.OPTIONAL_HEADER.SizeOfImage new_ldte.DllBase = proc_obj.parsed_pe.OPTIONAL_HEADER.ImageBase new_ldte.LoadCount = 1 self.new_unicode_string(proc_obj, new_ldte.BaseDllName, proc_obj.name) self.new_unicode_string(proc_obj, new_ldte.FullDllName, proc_obj.path) # link PEB_LDR and Process Image LDR_ENTRY size_of_list_etry = ntos.LIST_ENTRY(self.ptr_size).sizeof() peb_ldr_data.InLoadOrderModuleList.Flink = pNew_ldte peb_ldr_data.InMemoryOrderModuleList.Flink = pNew_ldte + size_of_list_etry new_ldte.InLoadOrderLinks.Flink = peb.Ldr + 0xC new_ldte.InMemoryOrderLinks.Flink = peb.Ldr + 0xC + size_of_list_etry proc_obj.write_mem_self(pNew_ldte, new_ldte.get_bytes()) proc_obj.write_mem_self(peb.Ldr, peb_ldr_data.get_bytes()) proc_obj.write_mem_self(proc_obj.peb_base, peb.get_bytes()) proc_obj.add_ldr_entry((pNew_ldte, new_ldte)) proc_obj.set_peb_ldr(peb_ldr_data) proc_obj.set_peb(peb) pass def add_module_to_peb(self, proc_obj: EmuProcess, mod_name: str): new_ldte = ntos.LDR_DATA_TABLE_ENTRY(self.ptr_size) new_ldte.DllBase = pydll.SYSTEM_DLL_BASE[mod_name] new_ldte.Length = ntos.LDR_DATA_TABLE_ENTRY(self.ptr_size).sizeof() self.new_unicode_string(proc_obj, new_ldte.BaseDllName, mod_name) self.new_unicode_string(proc_obj, new_ldte.FullDllName, "C:\\Windows\\System32\\" + mod_name + ".dll") pNew_ldte = self.mem_manager.alloc_heap(proc_obj.peb_heap, new_ldte.sizeof()) list_type = ntos.LIST_ENTRY(self.ptr_size) # Link created list_entry to LDR_MODULE if not proc_obj.ldr_entries: pEntry, prev = proc_obj.peb.Ldr, proc_obj.peb_ldr_data prev.InLoadOrderModuleList.Flink = pNew_ldte prev.InMemoryOrderModuleList.Flink = pNew_ldte + list_type.sizeof() prev.InInitializationOrderModuleList.Flink = 0 else: pEntry, prev = proc_obj.ldr_entries[-1] prev.InLoadOrderLinks.Flink = pNew_ldte prev.InMemoryOrderLinks.Flink = pNew_ldte + list_type.sizeof() prev.InInitializationOrderLinks.Flink = 0 # Not implement Blink new_ldte.InLoadOrderLinks.Flink = proc_obj.peb.Ldr + 0xC new_ldte.InMemoryOrderLinks.Flink = proc_obj.peb.Ldr + 0xC + list_type.sizeof( ) proc_obj.add_ldr_entry((pNew_ldte, new_ldte)) proc_obj.write_mem_self(pNew_ldte, new_ldte.get_bytes()) proc_obj.write_mem_self(pEntry, prev.get_bytes()) proc_obj.write_mem_self(proc_obj.peb_base, proc_obj.peb.get_bytes()) proc_obj.write_mem_self(proc_obj.peb.Ldr, proc_obj.peb_ldr_data.get_bytes()) pass def setup_uc_hooks(self, proc_obj: EmuProcess): h0 = proc_obj.uc_eng.hook_add(UC_HOOK_MEM_READ, self.api_handler.cpp_runtime_api_cb, (proc_obj, self.api_handler)) h3 = proc_obj.uc_eng.hook_add(UC_HOOK_CODE, logger) h1 = proc_obj.uc_eng.hook_add( UC_HOOK_CODE, self.api_handler.pre_api_call_cb_wrapper, (self, proc_obj, self.get_arch(), self.get_ptr_size())) h2 = proc_obj.uc_eng.hook_add( UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED, invalid_mem_access_cb) #h2 = proc_obj.uc_eng.hook_add(UC_HOOK_CODE, self.code_cb_handler.logger, (proc_obj, self.get_arch(), self.get_ptr_size())) #h3 = self.uc_eng.hook_add(UC_HOOK_MEM_UNMAPPED, self.code_cb_handler.unmap_handler, (self, self.get_arch(), self.get_ptr_size())) pass def switch_thread_context(self, proc_obj: EmuProcess, thread_obj: EmuThread, ret=0): def context_switch_cb(proc_obj: EmuProcess, thread_handle): proc_obj.running_thread.save_context() proc_obj.push_waiting_queue(proc_obj.running_thread.handle) proc_obj.push_waiting_queue(thread_handle) proc_obj.uc_eng.hook_del(proc_obj.ctx_switch_hook) proc_obj.running_thread.suspend_thread() proc_obj.ctx_switch_hook = proc_obj.uc_eng.hook_add( UC_HOOK_CODE, self.api_handler.post_api_call_cb_wrapper, (proc_obj, (proc_obj, thread_obj.handle), 1, context_switch_cb)) pass def create_thread( self, proc_obj: EmuProcess, thread_entry, param=None, stack_size=1024 * 1024, # 1MB default stack size creation=windef.CREATE_NEW): if stack_size == 0: stack_size = 1024 * 1024 thread_stack_region = self.mem_manager.alloc_page( proc_obj.pid, stack_size, PageAllocationType.MEM_COMMIT) stack_limit, stack_base = thread_stack_region.get_page_region_range() hThread = self.obj_manager.create_new_object( 'Thread', proc_obj, thread_entry, stack_base - stack_size + 0x1000, stack_limit, param) thread_obj: EmuThread = self.obj_manager.get_obj_by_handle(hThread) thread_obj.set_thread_stack(thread_stack_region) thread_obj.teb_heap = self.mem_manager.create_heap(proc_obj.pid, size=0x10000, max_size=0x10000) if creation & windef.CREATE_SUSPENDED: thread_obj.suspend_count += 1 teb_base = self.mem_manager.alloc_heap( thread_obj.teb_heap, ntos.TEB(self.ptr_size).sizeof()) gdt_page = self.mem_manager.alloc_page(proc_obj.pid, 0x1000, PageAllocationType.MEM_COMMIT) selectors = proc_obj.gdt.setup_selector( gdt_addr=gdt_page.get_base_addr(), fs_base=teb_base, fs_limit=ALLOCATION_GRANULARITY) thread_obj.set_selectors(selectors) thread_obj.init_teb(proc_obj.peb_base) thread_obj.init_context() self.mem_manager.write_process_memory(proc_obj.pid, teb_base, thread_obj.get_bytes()) EmuThreadManager.push_wait_queue(proc_obj.pid, thread_obj.tid, thread_obj) return hThread def create_process(self, file_path): def parse_pe_binary(pe_bin): return pefile.PE(data=pe_bin) """ 1. """ if os.path.basename(file_path) == file_path: # input file_path is using alias # search procedure # 1. %home_dir% # 2. c:/windows/system32 virtual_file_path = convert_winpath_to_emupath( emu_path_join(self.emu_home_dir, file_path)) virtual_file_path = emu_path_join(virtual_file_path["vl"], virtual_file_path["ps"]) if self.emu_vfs.check_file_exist(virtual_file_path): pass else: virtual_file_path = convert_winpath_to_emupath( emu_path_join("c:/windows/system32", file_path)) virtual_file_path = emu_path_join(virtual_file_path["vl"], virtual_file_path["ps"]) if self.emu_vfs.check_file_exist(virtual_file_path): pass else: """ *** Copy Mock Application to Start """ mock_app_path = emu_path_join(self.emu_home_dir, file_path) self.emu_vfs.vcopy(self.emu_vfs.dummpy_app, mock_app_path) virtual_file_path = mock_app_path else: virtual_file_path = convert_winpath_to_emupath(file_path) virtual_file_path = emu_path_join(virtual_file_path["vl"], virtual_file_path["ps"]) uc_eng = self.create_new_emu_engine() hFile = self.obj_manager.get_object_handle( 'File', virtual_file_path, DesiredAccess.GENERIC_ALL, CreationDisposition.OPEN_EXISTING, 0, FileAttribute.FILE_ATTRIBUTE_NORMAL) if hFile == windef.INVALID_HANDLE_VALUE: raise Exception("There is no target file to execute") pHandle = self.obj_manager.create_new_object('Process', uc_eng, self, virtual_file_path, hFile) proc_obj = self.obj_manager.get_obj_by_handle(pHandle) file_obj = self.obj_manager.get_obj_by_handle(hFile) rf = file_obj.im_read_file() if not rf["success"]: return None pe_bin = rf["data"] _pe_ = parse_pe_binary(pe_bin) proc_obj.set_parsed_pe(_pe_) self.mem_manager.register_new_process(proc_obj) self.init_vas(proc_obj) self.init_peb(proc_obj) self.load_target_proc(proc_obj) self.setup_uc_hooks(proc_obj) self.load_import_mods(proc_obj) self.setup_import_tab(proc_obj) hThread = self.create_thread(proc_obj, proc_obj.entry_point) return proc_obj, pHandle, hThread def create_process_ex(self, section_handle): pass def __update_api_va_dict__(self, va, dll: str, api: str): self.api_va_dict[va] = (dll, api) pass def __set_emulation_config(self, config=None): """ Parse the config to be used for emulation """ import json if not config: config_path = os.path.join(os.getcwd(), "env.config") with open(config_path, 'r') as f: self.config = json.load(f) config = self.config else: self.config = config if isinstance(config, str): config = json.loads(config) self.osversion = config.get('os_ver', {}) self.env = config.get('env', {}) self.user_config = config.get('user', {}) self.domain = config.get('domain') self.hostname = config.get('hostname') self.symlinks = config.get('symlinks', []) self.drive_config = config.get('drives', []) self.registry_config = config.get('registry', {}) self.network_config = config.get('network', {}) self.process_config = config.get('processes', []) self.command_line = config.get('command_line', '') self.img_name = config.get('image_name' '') self.img_path = config.get('image_path', '') self.emu_home_dir = config.get('home_dir', '').lower().replace("\\", "/") self.parse_api_conf() def parse_api_conf(self, conf_path="./winapi.config"): with open(conf_path, "rt") as f: confs = f.readlines() for line in confs: line = line[:-1] if not line: continue if line[0] == "#": continue s = line.split("|") rettype = s[0] api_name = s[1] if len(s) > 2: args_types = s[2:] else: args_types = [] self.winapi_info_dict[api_name] = { "rettype": rettype, "argc": len(args_types), "args_types": args_types } def new_unicode_string(self, proc_obj: EmuProcess, ustr, pystr: str): uBytes = (pystr + "\x00").encode("utf-16le") pMem = self.mem_manager.alloc_heap(proc_obj.proc_default_heap, len(uBytes) + 1) ustr.Length = len(uBytes) ustr.MaximumLength = len(uBytes) + 1 ustr.Buffer = pMem self.mem_manager.write_process_memory(proc_obj.pid, pMem, uBytes) pass def get_ptr_size(self): return self.ptr_size def get_arch(self): return self.arch def set_ptr_size(self): if self.arch == UC_ARCH_X86 and self.mode == UC_MODE_32: self.ptr_size = 4 # elif self.arch == UC_ARCH_X86 and self.mode == UC_MODE_64: # reserved # self.ptr_size = 8 else: raise Exception("Unsupported architecture") def get_param(self): return self.command_line.split(" ")[1:]
def free_heap(self, handle, address): heap = ObjectManager.get_obj_by_handle(handle) heap.free_heap_segment(address=address) pass