Exemple #1
0
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
Exemple #2
0
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)
Exemple #3
0
    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()
Exemple #5
0
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
Exemple #6
0
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
Exemple #7
0
def write_memory(start, data, destructive=False):
    if destructive:
        idaapi.put_many_bytes(start, data)

    else:
        idaapi.patch_many_bytes(start, data)
Exemple #8
0
 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)
Exemple #9
0
 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
Exemple #11
0
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)
Exemple #13
0
def write(ea, data, original=False):
    return idaapi.patch_many_bytes(
        ea, data) if original else idaapi.put_many_bytes(ea, data)
Exemple #14
0
    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
Exemple #15
0
def write(ea, data, original=False):
    return idaapi.patch_many_bytes(ea, data) if original else idaapi.put_many_bytes(ea, data)