def dump_and_rebuild(pid, oep, newimpdir="newimpdir", newiat="newiat"): '''Dump process and rebuild with new original entry point. @param pid: process ID @param oep: original entry point @param newimpdir: name for new section that will contain imports @param newiat: name for new section that will contain new IAT ''' System.request_debug_privileges() process = Process( pid ) try: process.suspend() except WindowsError as e: pass file_path = process.get_filename() file_name = p_os.path.basename(file_path) ####################################################################### # # REBUILD THE DUMPED PE # # I'm sure there is a better way to do this because all we are really # doing is dumping the PE mapped sections. Suggestions welcome! # # The crazy way we do this is to get a memory map of the whole process # then find the pages that are owned by the file that spawned the process. # ####################################################################### mem_map = get_mem_map(process) temp_data_arr = {} for page in mem_map: if file_name.upper() in page["Owner"].upper(): dump_data = process.peek(page["BaseAddress"],page["RegionSize"]) temp_data_arr[page["BaseAddress"]] = dump_data # we need to work with the dump as one contiguous data block in "mapped" format. ordered_mem = temp_data_arr.keys() ordered_mem.sort() block_data = temp_data_arr[ordered_mem[0]] for addr_ptr in range(1,len(ordered_mem)): padding_len = ordered_mem[addr_ptr] - (ordered_mem[0] + len(block_data)) #print "Padding: %d" % padding_len # These should be contiguous pages so there should be no need for padding! block_data += temp_data_arr[ordered_mem[addr_ptr]] + '\x00'*padding_len # The lowest mapped section is the base address base_address = ordered_mem[0] # Elfesteem has a small issue with the way it loads mapped PE files # instead of using the virtual size for segments it uses the raw size # this messes up unpacker dumps so we will fix it manually. pf = pe_init.PE(loadfrommem=True, pestr=block_data) new_sections = [] for tmp_section in pf.SHList: new_sections.append({"name": tmp_section.name ,"offset": tmp_section.addr ,"size": tmp_section.size ,"addr": tmp_section.addr ,"flags": tmp_section.flags ,"rawsize": tmp_section.size}) # Remove existing sections pf.SHList.shlist=[] for tmp_section in new_sections: pf.SHList.add_section(name=tmp_section["name"], data=block_data[tmp_section["offset"]:tmp_section["offset"] + tmp_section["rawsize"]], size=tmp_section["size"], addr=tmp_section["addr"], offset=tmp_section["offset"], rawsize=tmp_section["rawsize"]) pf.NThdr.ImageBase = base_address pf.Opthdr.AddressOfEntryPoint = oep # Disable rebase, since addresses are absolute any rebase will make this explode pf.NThdr.dllcharacteristics = 0x0 ####################################################################### # # At this point pf contains a fully reconstructed PE but with a # broken IAT. Fix the IAT! # ####################################################################### return rebuild_iat(pid, str(pf), base_address, oep, newimpdir=newimpdir, newiat=newiat, loadfrommem=False)