def fix_imports_by_dllname(self, uc, hdr, total_size, dllname_to_functionlist): pe_write(uc, hdr.opt_header.ImageBase, total_size, ".unipacker_brokenimport.exe") with open(".unipacker_brokenimport.exe", 'rb') as f: b = f.read() dllname_to_ptrs = [] for k in dllname_to_functionlist.keys(): k = k.split('#')[0] dllname_to_ptrs.append( (k, self.locate_ptr_to_occurences(b, self.find_occurences(b, k)))) if len(dllname_to_ptrs) == 1 and len(dllname_to_ptrs[0][1]) == 1: addr = dllname_to_ptrs[0][1] elif len(dllname_to_ptrs) == 1: # TODO Try Fix Imports by Imported Function Names print("FAILED here") return None # FAILED else: for i in range(len(dllname_to_ptrs) - 1): addrlist = dllname_to_ptrs[i][1] addrlist2 = dllname_to_ptrs[i + 1][1] a1, a2 = self.search_offset_two(addrlist, addrlist2, 0x14) if a1 is not None and a2 is not None: break if a1 is None and a2 is None: print(f"FAILED a1: {a1}, a2: {a2}") return None # FAILED dllname_to_ptrs[0] = (dllname_to_ptrs[0][0], [a1]) dllname_to_ptrs[1] = (dllname_to_ptrs[1][0], [a2]) offset = 0x14 for i in range(len(dllname_to_ptrs)): if i + 1 < len(dllname_to_ptrs): cmp = dllname_to_ptrs[i][1][0] val = None for e in dllname_to_ptrs[i + 1][1]: if cmp + 0x14 == e: val = e dllname_to_ptrs[i + 1] = (dllname_to_ptrs[i + 1][0], [val]) # select pointer addr = dllname_to_ptrs[0][1][0] for i in range(len(dllname_to_ptrs)): if addr > dllname_to_ptrs[i][1][0]: addr = dllname_to_ptrs[i][1][0] hdr.data_directories[1].VirtualAddress = addr - 0xC hdr.data_directories[1].Size = len(dllname_to_functionlist) * 5 * 4 # Per Dll 1 IMAGE_IMPORT_DESCRIPTOR (THUNK_DATA), Per IMAGE_IMPORT_DESCRIPTOR 5 DWORDS, Size in bytes so time 4 os.remove(".unipacker_brokenimport.exe") return hdr
def find_iat(self, uc, base_addr, total_size, iat_array, dll_name, offset=0x4): # hex = ' '.join('0x%02x' % hx for hx in iat_array) # print(f"IAT_ARRAY:{hex}") pe_write(uc, base_addr, total_size, ".unipacker_brokenimport.exe") with open(".unipacker_brokenimport.exe", 'rb') as f: b = f.read() # Part 1: Find all possible ptrs possible_ptrs = [] for iat_entry in iat_array: found_ptr = -1 possible_addr = [] while True: found_ptr = b.find(struct.pack("I", iat_entry), (found_ptr + 1), len(b)) if found_ptr == -1: break else: possible_addr.append(found_ptr) possible_ptrs.append(possible_addr) # Part 2: Validate with offset if len(possible_ptrs) == 1: if len(possible_ptrs[0]) == 0: return None return possible_ptrs[0][ 0] # TODO Default first check with allocated section ptrs = [] for i in range(len(possible_ptrs) - 1): l1 = possible_ptrs[i] l2 = possible_ptrs[i + 1] a1, a2 = self.search_offset_two(l1, l2, offset) if a1 is None: print("Not Found!") ptrs.append(a1) lx = possible_ptrs[-1] for elem in lx: if elem - offset == ptrs[-1]: ptrs.append(elem) # print_addr_list(f"Printing possible ptrs for {dll_name}: ", ptrs) return ptrs[0]
def do_onlydmp(self, args): args = args or "dump" pe_write(self.engine.uc, self.sample.BASE_ADDR, self.sample.virtualmemorysize, args)
def dump_image(self, uc, base_addr, virtualmemorysize, apicall_handler, sample, path="unpacked.exe"): ntp = apicall_handler.ntp dllname_to_functionlist = sample.dllname_to_functionlist if len(sample.allocated_chunks) == 0: total_size = virtualmemorysize else: total_size = sorted(sample.allocated_chunks)[-1][1] - base_addr virtualmemorysize = total_size print(f"Totalsize:{hex(total_size)}, " f"VirtualMemorySize:{hex(virtualmemorysize)}") print_chunks(sample.allocated_chunks) try: hdr = PE(uc, base_addr) except InvalidPEFile as i: print("Invalid PE File... Cannot dump") return old_number_of_sections = hdr.pe_header.NumberOfSections print("Setting unpacked Entry Point") print(f"OEP:{hex(uc.reg_read(UC_X86_REG_EIP) - base_addr)}") hdr.opt_header.AddressOfEntryPoint = uc.reg_read( UC_X86_REG_EIP) - base_addr print("Fixing Imports...") hdr = self.fix_imports(uc, hdr, virtualmemorysize, total_size, dllname_to_functionlist, sample.original_imports) print("Fixing sections") self.fix_sections(hdr, old_number_of_sections, virtualmemorysize) print("Set IAT-Directory to 0 (VA and Size)") hdr.data_directories[12].VirtualAddress = 0 hdr.data_directories[12].Size = 0 print( f"RVA to import table: {hex(hdr.data_directories[1].VirtualAddress)}" ) if (virtualmemorysize - 0xE000) <= hdr.data_directories[ 1].VirtualAddress <= virtualmemorysize or len( sample.allocated_chunks) != 0 or True: print(f"Totalsize:{hex(total_size)}, " f"VirtualMemorySize:{hex(virtualmemorysize)}, " f"Allocated chunks: {sample.allocated_chunks}") # print("Relocating Headers to End of Image") # hdr.dos_header.e_lfanew = virtualmemorysize - 0x10000 # hdr = self.add_section(hdr, '.newhdr', 0x10000, virtualmemorysize-0x10000) # print("Adding new import section") # hdr = self.add_section(hdr, '.nimdata', 0xe000, (virtualmemorysize - 0x10000) + 0x2000) # print("Appending allocated chunks at the end of the image") # hdr = self.chunk_to_image_section_hdr(hdr, base_addr, sample.allocated_chunks) # TODO Fix chunk unmapped space with 0 else: virtualmemorysize -= 0x10000 total_size = virtualmemorysize hdr.sync(uc) print("Fixing SizeOfImage...") hdr.opt_header.SizeOfImage = alignments( total_size, hdr.opt_header.SectionAlignment) print("Fixing Memory Protection of Sections") hdr = self.fix_section_mem_protections(hdr, ntp) hdr.sync(uc) print("Fixing Checksum") hdr = self.fix_checksum(uc, hdr, base_addr, total_size) hdr.sync(uc) dllcharacteristics = hdr.opt_header.DllCharacteristics & 0xFFBF hdr.opt_header.DllCharacteristics = dllcharacteristics # Remove Dynamic Base hdr.sync(uc) print(f"Dumping state to {path}") pe_write(uc, base_addr, total_size, path)