def load_file(li, neflags, fmt): idaapi.set_processor_type('rl78', idaapi.SETPROC_ALL | idaapi.SETPROC_FATAL) f = FupdFile(li) if f.magic != MAGIC_PATCH: make_seg(0xf0000, 0x10000) for desc, block in f.iter_blocks(): make_seg(desc.flash_addr, desc.size) idaapi.put_many_bytes(desc.flash_addr, block) return 1
def load_mod(mod, data): nm = mod.Name.rstrip('\0') if mod.Tag == '$MME': base = mod.ModBase rapi1 = ((mod.Flags>>17)&7) rapi2 = ((mod.Flags>>20)&3) codestart = base + (rapi1+rapi2) * 0x1000 codeend = base + mod.CodeSize dataend = base + mod.MemorySize entry = mod.EntryPoint else: base = mod.LoadAddress rapi1 = rapi2 = 0 codestart = base codeend = base + mod.UncompressedSize dataend = base + mod.MappedSize entry = base + EntryRVA curoff = base if rapi1: rapi1end = curoff + rapi1 * 0x1000 print "%08X %08X %s RAPI" % (curoff, rapi1end, nm) myAddSeg(curoff, rapi1end, nm + ".RAPI", "CODE") curoff = rapi1end if rapi2: rapi2end = curoff + rapi2 * 0x1000 print "%08X %08X %s KAPI" % (curoff, rapi2end, nm) myAddSeg(curoff, rapi2end, nm + ".KAPI", "CODE") curoff = rapi2end if mod.PreUmaSize == 0: codestart = base if codestart: if curoff < codestart: print "%08X %08X %s GAP" % (curoff, codestart, nm) curoff = codestart print "%08X %08X %s CODE" % (curoff, codeend, nm) myAddSeg(codestart, codeend, nm + ".CODE", "CODE") print "data start: %s" % data[:4].encode('hex') idaapi.put_many_bytes(curoff, data[0:codeend-codestart]) curoff = codeend if curoff < dataend: print "%08X %08X %s DATA" % (curoff, dataend, nm) myAddSeg(curoff, dataend, nm + ".DATA", "DATA") idaapi.put_many_bytes(curoff, data[codeend-codestart:dataend-codestart]) curoff = dataend if curoff & 0xFFF: gapend = (curoff + 0xFFF) & ~0xFFF print "%08X %08X %s GAP" % (curoff, gapend, nm) curoff = gapend if entry != 0: makecode = len(data) > 0 AddEntryPoint(mod.EntryPoint, mod.EntryPoint, nm + "_entry", makecode)
def OnEditLine(self, n): # Empty list if n == -1: return # Multiselect START_SEL/END_SEL protocol if n == -2 or n ==-3: return ea = self.items_data[n][0] fpos = self.items_data[n][1] patch_buf = self.items_data[n][3] orig_buf = self.items_data[n][4] addr_str = "%#x" % ea fpos_str = "%#x" % fpos if fpos != -1 else "N/A" patch_str = self.items[n][3] org_str = self.items[n][4] # Create the form f = PatchEditForm(addr_str, fpos_str, patch_str, org_str) # Execute the form ok = f.Execute() if ok == 1: # Convert hex bytes to binary buf = f.strPatch.value buf = buf.replace(' ','') # remove spaces buf = buf.replace('\\x','') # remove '\x' prefixes buf = buf.replace('0x','') # remove '0x' prefixes try: buf = binascii.unhexlify(buf) # convert to bytes except Exception as e: idaapi.warning("Invalid input: %s" % e) f.Free() return # Restore original bytes first idaapi.put_many_bytes(ea, struct.pack("B"*len(orig_buf), *orig_buf)) # Now apply newly patched bytes idaapi.patch_many_bytes(ea, buf) # Refresh all IDA views self.refreshitems() # Dispose the form f.Free()
def OnEditLine(self, n): # Empty list if n == -1: return # Multiselect START_SEL/END_SEL protocol if n == -2 or n ==-3: return ea = self.items_data[n][0] fpos = self.items_data[n][1] patch_buf = self.items_data[n][3] orig_buf = self.items_data[n][4] addr_str = "%#x" % ea fpos_str = "%#x" % fpos if fpos != -1 else "N/A" patch_str = self.items[n][3] org_str = self.items[n][4] # Create the form f = PatchEditForm(addr_str, fpos_str, patch_str, org_str) # Execute the form ok = f.Execute() if ok == 1: # Convert hex bytes to binary buf = f.strPatch.value buf = buf.replace(' ','') # remove spaces buf = buf.replace('\\x','') # remove '\x' prefixes buf = buf.replace('0x','') # remove '0x' prefixes try: buf = binascii.unhexlify(buf) # convert to bytes except Exception, e: idaapi.warning("Invalid input: %s" % e) f.Free() return # Restore original bytes first idaapi.put_many_bytes(ea, struct.pack("B"*len(orig_buf), *orig_buf)) # Now apply newly patched bytes idaapi.patch_many_bytes(ea, buf) # Refresh all IDA views self.refreshitems() idaapi.refresh_idaview_anyway()
def load_file(li, neflags, format): """ Load the file into database @param li: a file-like object which can be used to access the input data @param neflags: options selected by the user, see loader.hpp @return: 0-failure, 1-ok """ if format == FormatName: idaapi.set_processor_type("arm", SETPROC_ALL|SETPROC_FATAL) chunk = "" while True: s = gets(li) if s == None: break # warning(s) if s.startswith("#") or s.startswith(" ") or s.startswith(".*: "): continue words = s.split() if len(words) > 2 and words[1].startswith('<') and words[1].endswith('>'): hex = words[2].decode('hex') chunk += hex[::-1] if ishex(words[3]) and len(words[3]) == len(words[2]): hex = words[3].decode('hex') chunk += hex[::-1] if len(chunk) == 0: return 0 size = len(chunk) AddSeg(0, size, 0, 1, idaapi.saRelByte, idaapi.scPub) idaapi.put_many_bytes(0, chunk) print "Load OK" return 1 Warning("Unknown format name: '%s'" % format) return 0
def write_memory(start, data, destructive=False): if destructive: idaapi.put_many_bytes(start, data) else: idaapi.patch_many_bytes(start, data)
def load_to_idb(self, seg_start): load_ea = seg_start + self.start_ea print "%08X: loading %04X bytes of %s memory" % (load_ea, self.end_ea - self.start_ea, self.mem_type) idaapi.put_many_bytes(load_ea, self.chunk)
def load_file(li, _, __): idaapi.set_processor_type("clemency", idaapi.SETPROC_ALL | idaapi.SETPROC_FATAL) # Get bytes as u16. li.seek(0) data_u16 = BitReader(li).read_as_u16() program_size = len(data_u16) / 2 # Load the firmware image. add_segment(0, program_size, "MAIN_PROGRAM", "CODE") idaapi.put_many_bytes(0, data_u16) MakeName(0, '_start') AutoMark(0, AU_CODE) MakeFunction(0) # Fake .BSS in case it's accessed. add_segment(program_size, program_size + 0x1000, "BSS", "BSS") def make_array(addr, name, size=3): MakeName(addr, name) MakeArray(addr, size) return size ''' 0x4000000 3 Timer 1 Delay 0x4000003 3 Number of milliseconds left for Timer 1 0x4000006 3 Timer 2 Delay 0x4000009 3 Number of milliseconds left for Timer 2 0x400000C 3 Timer 3 Delay 0x400000F 3 Number of milliseconds left for Timer 3 0x4000012 3 Timer 4 Delay 0x4000015 3 Number of milliseconds left for Timer 4 0x4000018 6 Number of seconds since Aug. 02, 2013 09:00 PST 0x400001E 3 Number of processing ticks since processor start ''' add_segment(0x4000000, 0x4000021, "CLOCK_IO", "DATA") addr = 0x4000000 for i in xrange(4): timer = 'timer%d' % (i + 1) addr += make_array(addr, 'g_%s_delay' % timer) addr += make_array(addr, 'g_%s_ms_left' % timer) addr += make_array(addr, 'g_secs_since_epoch', 6) addr += make_array(addr, 'g_ticks_since_start') add_segment(0x4010000, 0x4011000, "FLAG_IO", "DATA") make_array(0x4010000, 'g_flag', 0x1000) add_segment(0x5000000, 0x5002003, "DATA_RECEIVED", "DATA") make_array(0x5000000, 'g_data_received', 0x2000) make_array(0x5002000, 'g_data_received_size') add_segment(0x5010000, 0x5012003, "DATA_SENT", "DATA") make_array(0x5010000, 'g_data_sent', 0x2000) make_array(0x5012000, 'g_data_sent_size') add_segment(0x6000000, 0x6800000, "SHARED_MEMORY", "DATA") make_array(0x6000000, 'g_shm', 0x800000) add_segment(0x6800000, 0x7000000, "NVRAM_MEMORY", "DATA") make_array(0x6800000, 'g_nvram', 0x800000) ''' 0x7FFFF00 Timer 1 0x7FFFF03 Timer 2 0x7FFFF06 Timer 3 0x7FFFF09 Timer 4 0x7FFFF0C Invalid Instruction 0x7FFFF0F Divide by 0 0x7FFFF12 Memory Exception 0x7FFFF15 Data Received 0x7FFFF18 Data Sent ''' add_segment(0x7FFFF00, 0x7FFFF1B, "INTERRUPT_POINTERS", "DATA") addr = 0x7FFFF00 for i in xrange(4): timer = 'timer%d' % (i + 1) addr += make_array(addr, 'g_%s_interrupt_handler' % timer) addr += make_array(addr, 'g_invalid_instruction_handler') addr += make_array(addr, 'g_div_by_zero_handler') addr += make_array(addr, 'g_memory_exn_handler') addr += make_array(addr, 'g_data_received_handler') addr += make_array(addr, 'g_data_sent_handler') ''' 0x7FFFF80 20 Processor name 0x7FFFFA0 3 Processor version 0x7FFFFA3 3 Processor functionality flags 0x7FFFFA6 4A For future use 0x7FFFFF0 1 Interrupt stack direction flag 0x7FFFFF1 F For future use ''' add_segment(0x7FFFF80, 0x8000000, "PROC_ID_FEATURES", "DATA") addr = 0x7FFFF80 addr += make_array(addr, 'g_processor_name', 0x20) addr += make_array(addr, 'g_processor_version') addr += make_array(addr, 'g_processor_flags') addr += make_array(addr, 'g_processor_reserved_1', 0x4a) addr += make_array(addr, 'g_interrupt_stack_direction', 1) addr += make_array(addr, 'g_processor_reserved_2', 0xf) return 1
class PatchView(Choose2): """ Chooser class to display and manage patched bytes in the database. """ def __init__(self): Choose2.__init__(self, "Patches", [["Address", 10 | Choose2.CHCOL_HEX], ["Name", 18 | Choose2.CHCOL_PLAIN], ["Size", 4 | Choose2.CHCOL_DEC], ["Modified", 10 | Choose2.CHCOL_HEX], ["Original", 10 | Choose2.CHCOL_HEX], ["Comment", 30 | Choose2.CHCOL_PLAIN]], flags=Choose2.CH_MULTI_EDIT) self.popup_names = ["Insert", "Delete", "Edit", "Refresh"] self.icon = 47 # Items for display and corresponding data # NOTE: Could become desynchronized, so to avoid this # refresh the view after each change. self.items = [] self.items_data = [] # Initialize/Refresh the view self.refreshitems() # Data members self.patch_file = None self.restore = False # Command callbacks self.cmd_apply_patches = None self.cmd_restore_bytes = None def show(self): # Attempt to open the view if self.Show() < 0: return False # Add extra context menu commands # NOTE: Make sure you check for duplicates. if self.cmd_apply_patches == None: self.cmd_apply_patches = self.AddCommand( "Apply patches to input file...", flags=idaapi.CHOOSER_POPUP_MENU | idaapi.CHOOSER_NO_SELECTION, icon=27) if self.cmd_restore_bytes == None: self.cmd_restore_bytes = self.AddCommand( "Restore original byte(s)...", flags=idaapi.CHOOSER_POPUP_MENU | idaapi.CHOOSER_MULTI_SELECTION, icon=139) return True # Patch byte visitor callback to apply the patches # NOTE: Only bytes with fpos > -1 can be applied. def apply_patch_byte(self, ea, fpos, org_val, patch_val): if fpos != -1: self.patch_file.seek(fpos) if self.restore: self.patch_file.write(struct.pack('B', org_val)) else: self.patch_file.write(struct.pack('B', patch_val)) return 0 # Patch byte visitor callback to collect and aggregate bytes def get_patch_byte(self, ea, fpos, org_val, patch_val): # Aggregate contiguous bytes (base ea + length) # NOTE: Looking at the last item [-1] is sufficient # since we are dealing with sorted data. if len(self.items_data) and (ea - self.items_data[-1][0] == self.items_data[-1][2]): # Increment length self.items_data[-1][2] += 1 self.items[-1][2] = str(self.items_data[-1][2]) # Append patched bytes self.items_data[-1][3].append(patch_val) self.items[-1][3] = " ".join( ["%02X" % x for x in self.items_data[-1][3]]) # Append original bytes self.items_data[-1][4].append(org_val) self.items[-1][4] = " ".join( ["%02X" % x for x in self.items_data[-1][4]]) # Add new patch byte to the list else: name = SegName(ea) if GetFunctionName(ea) or Name(ea): name += ": %s" % GetFunctionName(ea) or Name(ea) comment = Comment(ea) or RptCmt(ea) or "" # DATA STORAGE FORMAT: address, function / fpos, len, patched byte(s), original byte(s), comments self.items.append([ "%08X" % ea, name, "1", "%02X" % patch_val, "%02X" % org_val, comment ]) self.items_data.append([ea, fpos, 1, [patch_val], [org_val], None]) return 0 def refreshitems(self): self.items_data = [] self.items = [] idaapi.visit_patched_bytes(0, idaapi.BADADDR, self.get_patch_byte) def OnCommand(self, n, cmd_id): # Apply patches to a file if cmd_id == self.cmd_apply_patches: # Set initial start/end EA values start_ea = 0x0 end_ea = idaapi.cvar.inf.maxEA # Set initial output file values org_file = GetInputFilePath() bkp_file = "%s.bak" % org_file # Create the form f = PatchApplyForm(start_ea, end_ea, org_file, bkp_file) # Execute the form ok = f.Execute() if ok == 1: # Get restore checkbox self.restore = f.rRestore.checked # Get updated ea max/min start_ea = f.intStartEA.value end_ea = f.intEndEA.value # Get updated file path new_org_file = f.orgFile.value # Backup the file before replacing if f.rBackup.checked: bkp_file = f.bkpFile.value shutil.copyfile(org_file, bkp_file) # Apply patches try: self.patch_file = open(new_org_file, 'rb+') except Exception, e: idaapi.warning("Cannot update file '%s'" % new_org_file) else: r = idaapi.visit_patched_bytes(start_ea, end_ea, self.apply_patch_byte) self.patch_file.close() self.restore = False # Update db input file, so we are working # with a patched version. #if not org_file == new_org_file: # idaapi.set_root_filename(new_org_file) # org_file = new_org_file # Dispose the form f.Free() # Restore selected byte(s) elif cmd_id == self.cmd_restore_bytes: # List start/end if n == -2 or n == -3: return 1 elif not len(self.items) > 0: idaapi.warning("There are no patches to restore.") return 1 # Nothing selected elif n == -1: idaapi.warning("Please select bytes to restore.") return 1 ea = self.items_data[n][0] fpos = self.items_data[n][1] buf = self.items_data[n][4] addr_str = "%#x" % ea fpos_str = "%#x" % fpos if fpos != -1 else "N/A" patch_str = self.items[n][3] org_str = self.items[n][4] # Create the form f = PatchRestoreForm(addr_str, fpos_str, patch_str, org_str) # Execute the form ok = f.Execute() if ok == 1: # Restore original bytes idaapi.put_many_bytes(ea, struct.pack("B" * len(buf), *buf)) # Refresh all IDA views self.refreshitems() # Dispose the form f.Free()
import idc import idaapi import sys idc.Wait() if len(idc.ARGV) == 2: tmp_dir = idc.ARGV[1] for tmp_file in sorted(os.listdir(tmp_dir)): if tmp_file.endswith('.dmp'): with open("{}/{}".format(tmp_dir, tmp_file)) as f: data = f.read() start_addr = int(tmp_file.split('.')[0], 16) stop_addr = (start_addr + len(data)) | 0xfff idc.SegCreate(start_addr, stop_addr, 0, 1, 0, idaapi.scPub) idc.SetSegmentType(start_addr, idc.SEG_CODE) idaapi.put_many_bytes(start_addr, data) # reanalyze after adding all the new sections idc.AnalyzeArea(0, idc.BADADDR) # compresses the DB idc.SaveBase('{}.idb'.format(idc.GetInputFile()), flags=idaapi.DBFL_COMP) idc.Exit(0)
def write(ea, data, original=False): return idaapi.patch_many_bytes( ea, data) if original else idaapi.put_many_bytes(ea, data)
def OnCommand(self, n, cmd_id): # Apply patches to a file if cmd_id == self.cmd_apply_patches: # Set initial start/end EA values start_ea = 0x0 end_ea = idaapi.cvar.inf.maxEA # Set initial output file values org_file = GetInputFilePath() bkp_file = "%s.bak" % org_file # Create the form f = PatchApplyForm(start_ea, end_ea, org_file, bkp_file) # Execute the form ok = f.Execute() if ok == 1: # Get restore checkbox self.restore = f.rRestore.checked # Get updated ea max/min start_ea = f.intStartEA.value end_ea = f.intEndEA.value # Get updated file path new_org_file = f.orgFile.value # Backup the file before replacing if f.rBackup.checked: bkp_file = f.bkpFile.value shutil.copyfile(org_file, bkp_file) # Apply patches try: self.patch_file = open(new_org_file,'rb+') except Exception as e: idaapi.warning("Cannot update file '%s'" % new_org_file) else: r = idaapi.visit_patched_bytes(start_ea, end_ea, self.apply_patch_byte) self.patch_file.close() self.restore = False # Update db input file, so we are working # with a patched version. #if not org_file == new_org_file: # idaapi.set_root_filename(new_org_file) # org_file = new_org_file # Dispose the form f.Free() # Restore selected byte(s) elif cmd_id == self.cmd_restore_bytes: # List start/end if n == -2 or n ==-3: return 1 elif not len(self.items) > 0: idaapi.warning("There are no patches to restore.") return 1 # Nothing selected elif n == -1: idaapi.warning("Please select bytes to restore.") return 1 ea = self.items_data[n][0] fpos = self.items_data[n][1] buf = self.items_data[n][4] addr_str = "%#x" % ea fpos_str = "%#x" % fpos if fpos != -1 else "N/A" patch_str = self.items[n][3] org_str = self.items[n][4] # Create the form f = PatchRestoreForm(addr_str, fpos_str, patch_str, org_str) # Execute the form ok = f.Execute() if ok == 1: # Restore original bytes idaapi.put_many_bytes(ea, struct.pack("B"*len(buf), *buf)) # Refresh all IDA views self.refreshitems() # Dispose the form f.Free() return 1
def write(ea, data, original=False): return idaapi.patch_many_bytes(ea, data) if original else idaapi.put_many_bytes(ea, data)