Beispiel #1
0
    def rename(self, name=None):
        """
        Renames (and comments) the string variable in IDA.

        :param str name: New name to given encoded string. (defaults to decoded_string)
        """
        name = name or self.display_name
        if not name:
            append_debug(
                'Unable to rename encoded string due to no decoded string: {!r}'.format(self),
                log_token='[!]')
            return

        # Add comment
        comment = '"{}"'.format(name[:self._MAX_COMMENT_LENGTH])
        if len(name) > self._MAX_COMMENT_LENGTH:
            comment += ' (truncated)'
        if self.string_location not in (INVALID, UNUSED):
            idc.MakeRptCmt(self.string_location, comment)
        if self.string_reference not in (INVALID, UNUSED):
            idc.MakeRptCmt(self.string_reference, comment)

        # Set variable name
        if self.string_location not in (INVALID, UNUSED):
            idaapi.do_name_anyway(self.string_location, name[:self._MAX_NAME_LENGTH])
Beispiel #2
0
 def annotate_code(self, enabled):
     for addr, infos in self.results.items():
         if not enabled:
             status = to_status_name(infos.status)
             idc.MakeRptCmt(addr, status)
         else:
             idc.MakeRptCmt(addr, "")
     self.actions[self.ANNOT_CODE] = (self.annotate_code, not enabled)
     self.result_widget.action_selector_changed(self.ANNOT_CODE)
Beispiel #3
0
def label_and_fix_branch_islands(dsc_file, adrfind, jmp_to_code):
    """ labels, comments and fixes code flow on branch islands """
    jmpaddrs = sorted(set(jmp_to_code.keys()))
    dsc_file.seek(0)
    header = dsc_header(dsc_file)
    dsc_file.seek(header.images_offset)
    i = 0
    jmpaddrslen = len(jmpaddrs)
    for addr in jmpaddrs:
        print "status: 0x%X %d/%d" % (addr, i, jmpaddrslen)
        res = adrfind.find(addr)
        if not res:
            print "[!] coudln't find addr for addr:", addr
        dylib_path, dsc_offset, macho_offset = res
        exportname = adrfind.get_export_name_for_addr(addr)
        if _IN_IDA:
            eas = jmp_to_code[addr]
            for ea in eas:
                idc.MakeRptCmt(ea, "%s'%s" % (dylib_path, exportname))
                if "branch_islands" in idc.SegName(ea):
                    make_name(ea, exportname)
                    # patch them to "RET" so they would return
                    memcpy(ea, "\xC0\x03\x5F\xD6")
                    make_islands_xrefs_force_bl_call(ea)
        else:
            print "[+] \\\\ %s" % exportname
        i += 1
Beispiel #4
0
    def annotate_code(self, enabled):
        for ret_data in self.results:
            addr = ret_data.addr
            if not enabled:  #Set the comment
                status_s = ret_data.get_status()
                labels_s = ''.join(["[%s]" % x for x in ret_data.get_labels()])
                comment = "Status:%s %s" % (status_s, labels_s)
                if ret_data.is_tampering():
                    comment += ' Ret:%s' % str(
                        ["%x" % x for x in ret_data.returnsites])
                idc.MakeRptCmt(addr, comment)
            else:  #Remove the comment
                idc.MakeRptCmt(addr, "")

        self.actions[self.ANNOT_CODE] = (self.annotate_code, not (enabled))
        self.result_widget.action_selector_changed(self.ANNOT_CODE)
Beispiel #5
0
def append_comment(ea, s, repeatable=False):
    """
    add the given string as a (possibly repeating) comment to the given address.
    does not add the comment if it already exists.
    adds the comment on its own line.

    Args:
      ea (int): the address at which to add the comment.
      s (str): the comment text.
      repeatable (bool): if True, set a repeatable comment.

    Raises:
      UnicodeEncodeError: if the given string is not ascii.
    """
    # see: http://blogs.norman.com/2011/security-research/improving-ida-analysis-of-x64-exception-handling

    s = s.encode("ascii")

    if repeatable:
        string = idc.RptCmt(ea)
    else:
        string = idc.Comment(ea)

    if not string:
        string = s  # no existing comment
    else:
        if s in string:  # ignore duplicates
            return
        string = string + "\\n" + s

    if repeatable:
        idc.MakeRptCmt(ea, string)
    else:
        idc.MakeComm(ea, string)
Beispiel #6
0
 def yatest_comments(self):
     eas = []
     for offset in range(0, 3):
         for fn_cmt, fn_rpt, cmt, rpt, post, ant in tests:
             ea = get_func_item(offset)
             eas.append(ea)
             logger.debug("setting at 0x%08X : %r, %r, %r, %r, %r, %r" %
                          (ea, fn_cmt, fn_rpt, cmt, rpt, post, ant))
             if fn_cmt != None:
                 self.assertEqual(idc.SetFunctionCmt(ea, fn_cmt, False),
                                  True)
             if fn_rpt != None:
                 self.assertEqual(idc.SetFunctionCmt(ea, fn_rpt, True),
                                  True)
             if cmt != None:
                 self.assertEqual(idc.MakeComm(ea, cmt), True)
             if rpt != None:
                 self.assertEqual(idc.MakeRptCmt(ea, rpt), True)
             if post != None:
                 for i, txt in enumerate(post.split('\n')):
                     self.try_ext_lin(idc.ExtLinB, ea, i, txt)
             if ant != None:
                 for i, txt in enumerate(ant.split('\n')):
                     self.try_ext_lin(idc.ExtLinA, ea, i, txt)
     yaunit.save('comments', eas)
Beispiel #7
0
    def rename(self, name=None):
        """
        Renames (and comments) the string variable in IDA.

        :param str name: New name to given encoded string. (defaults to decoded_string)
        """
        name = name or self.display_name
        if not name:
            append_debug(
                'Unable to rename encoded string due to no decoded string: {!r}'.format(self),
                log_token='[!]')

        # Set name and comment in stack variable.
        comment = '"{}"'.format(name[:self._MAX_COMMENT_LENGTH])
        if len(name) > self._MAX_COMMENT_LENGTH:
            comment += ' (truncated)'
        if self.frame_id and self.stack_offset:
            idc.SetMemberComment(self.frame_id, self.stack_offset, comment, repeatable=1)
            var_name = re.sub('[^_$?@0-9A-Za-z]', '_', name[:self._MAX_NAME_LENGTH])  # Replace invalid characters
            if not var_name:
                raise ValueError('Unable to calculate var_name for : {!r}'.format(self))
            var_name = 'a' + var_name.capitalize()
            idc.SetMemberName(self.frame_id, self.stack_offset, var_name)

        # Add a comment where the string is being used.
        if self.string_reference:
            idc.MakeRptCmt(self.string_reference, comment)
Beispiel #8
0
def execute_comment(comment):
    """
        XXX : switch on the comment type
    """
    print comment["address"]
    idc.MakeRptCmt(comment["address"],
                   comment["data"].encode('ascii', 'replace'))
    print "[x] Added comment %s @0x%x " % (comment["data"], comment["address"])
Beispiel #9
0
 def on_pre_update(cls, patch_type, name, address, data):
     added_comment = str(cls.comment_format % (name, address))
     if idc.RptCmt(address) is not None and added_comment in idc.RptCmt(
             address):
         comment = idc.RptCmt(address).replace("\n" + added_comment,
                                               "").replace(
                                                   added_comment, "")
         idc.MakeRptCmt(address, comment)
Beispiel #10
0
 def on_perform_post_operations(cls, patch_type, name, address, data):
     original = idc.RptCmt(address)
     if original is not None:
         prefix = original + "\n"
     else:
         prefix = ""
     idc.MakeRptCmt(address,
                    str(prefix + cls.comment_format % (name, address)))
Beispiel #11
0
def execute_comment(comment):
    """
        XXX : switch on the comment type
    """
    idc.MakeRptCmt(comment["address"],
                   comment["data"].encode('ascii', 'replace'))
    g_logger.debug("[x] Added comment %s @0x%x " %
                   (comment["data"], comment["address"]))
Beispiel #12
0
def main():
    print('[+] start')
    currer = idc.ScreenEA()
    print('[+] address: %#x' % currer)
    crypted_data, crypted_size = get_data(currer)
    if crypted_size > 0:
        decode_data = decode(crypted_data, crypted_size)
        idc.MakeRptCmt(currer, str(decode_data))
    else:
        print('[-] failed')
Beispiel #13
0
def done(addr):
    print('[+] address: %#x' % addr)
    crypted_data, crypted_size = get_data(addr)
    if crypted_size > 0:
        decode_data = decode(crypted_data, crypted_size)
        idc.MakeRptCmt(addr, str(decode_data))
        return decode_data
        #print('[+] size: %#x' % crypted_size)
    else:
        print('[-] failed')
        return None
Beispiel #14
0
 def annotate_code(self, enabled):
     if not enabled:  #Annotate
         s = ":[" + self.results.get_status() + "]"
         if self.results.has_values():
             s += " vals:[" + ''.join(
                 ["%x," % x for x in self.results.values])[:-1] + "]"
         cmt = idc.RptCmt(self.results.target)
         if cmt != "":
             self.backup_comment[self.results.target] = cmt
             if cmt.startswith("//@assert"):
                 s = cmt + s
             else:
                 s = cmt + "\n" + self.results.query + s
         else:
             s = self.results.query + s
             self.backup_comment[self.results.target] = ""
         idc.MakeRptCmt(self.results.target, s.encode("utf-8", "ignore"))
     else:
         for addr, cmt in self.backup_comment.items():
             idc.MakeRptCmt(addr, cmt)
         self.backup_comment.clear()
     self.actions[self.ANNOT_CODE] = (self.annotate_code, not (enabled))
     self.result_widget.action_selector_changed(self.ANNOT_CODE)
Beispiel #15
0
def add_fct_descr(ea, function, rep):
    """ Insert a (repeatable) comment describing the function at ea.

    Arguments:
    ea -- effective address where the comment is added
    function -- function object holding data
    rep -- add repeatable comment (True/False)
    """
    descr = format_comment(function.description) + '\n' + \
        format_comment('RETURN VALUE: ' + function.returns)
    # Both functions do not return
    if rep:
        idc.MakeRptCmt(ea, descr)
    else:
        idc.MakeComm(ea, descr)
def AppendComment(ea, s, repeatable=False):
    # see williutils and http://blogs.norman.com/2011/security-research/improving-ida-analysis-of-x64-exception-handling
    if repeatable:
        string = idc.RptCmt(ea)
    else:
        string = idc.Comment(ea)
    if not string:
        string = s  # no existing comment
    else:
        if s in string:  # ignore duplicates
            return
        string = string + "\n" + s
    if repeatable:
        idc.MakeRptCmt(ea, string)
    else:
        idc.MakeComm(ea, string)
Beispiel #17
0
def import_comments(comments, sections):
    """Import BN comments
    """
    for addr, current_function in comments.iteritems():
        addr = base_addr_off_section(sections, int(addr))
        if addr is None:
            continue 

        if current_function["comment"]:
            idc.MakeRptCmt(int(addr), current_function["comment"].encode("utf-8"))

        for instr_addr, comment in current_function["comments"].iteritems():
            instr_addr = base_addr_off_section(sections, int(instr_addr))
            if instr_addr is None:
                continue

            idc.MakeComm(instr_addr, comment.encode("utf-8"))
def RetAddrStackWalk(nn, long_size):
    # get stack pointer
    if long_size == 8:
        sp = cpu.Rsp
    else:
        sp = cpu.Esp
    seg = idaapi.getseg(sp)
    if not seg:
        return (False, "Could not locate stack segment!")

    stack_seg_end = seg.endEA

    for sp in range(cpu.Esp, stack_seg_end + long_size, long_size):
        if long_size == 8:
            ptr = idc.Qword(sp)
        else:
            ptr = idc.Dword(sp)
        seg = idaapi.getseg(ptr)
        # only accept executable segments
        if (not seg) or ((seg.perm & idaapi.SEGPERM_EXEC) == 0):
            continue
        # try to find caller
        caller = IsPrevInsnCall(ptr)
        # we have no recognized caller, skip!
        if not caller:
            continue

        # do we have a debug name that is near?
        if nn:
            near = nn.find(caller)
            if near:
                # function exists?
                f = idaapi.get_func(near[0])
                if not f:
                    # create function
                    idc.MakeFunction(near[0], idaapi.BADADDR)

        # get the flags
        f = idc.GetFlags(caller)
        # no code there?
        if not isCode(f):
            MakeCode(caller)

        idc.SetColor(sp, idc.CIC_ITEM, 0xc7c7ff)
        idc.MakeRptCmt(sp, CreateCommentString(caller, sp))
Beispiel #19
0
        def db_write(cls, address, key, value, repeatable=0):
            result = cls.db_read(address, repeatable=repeatable)
            result[key] = value

            if '__color__' in result:
                value = result['__color__']
                cls.color(address, value)
                del(result['__color__'])

            if '__address__' in result:
                del(result['__address__'])

            # del all hidden things
            result = dict((k,v) for k,v in result.iteritems() if not k.startswith('__'))

            res = comment.toString(result).encode('ascii')
            if repeatable:
                return idc.MakeRptCmt(address, res)
            return idc.MakeComm(address, res)
Beispiel #20
0
def delete_comment_at_ea(ea, comment_type):
    logger.debug("Deleting comment at 0x%08X / %d" % (ea, comment_type))
    if comment_type == ya.COMMENT_REPEATABLE:
        idc.MakeRptCmt(ea, "")
        # TODO: remove the test with "comment" (temporary fix because of cache incoherency)
    elif comment_type == ya.COMMENT_NON_REPEATABLE or comment_type == "comment":
        idc.MakeComm(ea, "")
    elif comment_type == ya.COMMENT_ANTERIOR:
        for i in xrange(0, idaapi.get_first_free_extra_cmtidx(ea, idaapi.E_PREV)):
            idaapi.del_extra_cmt(ea, idaapi.E_PREV + i)
    elif comment_type == ya.COMMENT_POSTERIOR:
        for i in xrange(0, idaapi.get_first_free_extra_cmtidx(ea, idaapi.E_NEXT)):
            idaapi.del_extra_cmt(ea, idaapi.E_NEXT + i)
    elif comment_type == ya.COMMENT_BOOKMARK:
        # parse marked position
        for i in xrange(1, 1024):
            if idc.GetMarkedPos(i) == idc.BADADDR:
                break
            elif idc.GetMarkedPos(i) == ea:
                idc.MarkPosition(ea, 0, 0, 0, i, "")
Beispiel #21
0
 def yatest_data_comments(self):
     eas = []
     for offset in range(0, 3):
         for cmt, rpt, post, ant in tests_data:
             ea = get_data_item()
             eas.append(ea)
             logger.debug(
                 "setting data comment at 0x%08X : %r, %r, %r, %r" %
                 (ea, cmt, rpt, post, ant))
             if cmt != None:
                 idc.MakeComm(ea, cmt)
             if rpt != None:
                 idc.MakeRptCmt(ea, rpt)
             if post != None:
                 for i, txt in enumerate(post.split('\n')):
                     try_ext_lin(idc.ExtLinB, ea, i, txt)
             if ant != None:
                 for i, txt in enumerate(ant.split('\n')):
                     try_ext_lin(idc.ExtLinA, ea, i, txt)
     yaunit.save('data_comments', eas)
Beispiel #22
0
 def yatest_code_comments(self):
     eas = []
     for offset in range(0, 3):
         for cmt, rpt, post, ant in tests_code:
             ea = get_code_item()
             eas.append(ea)
             logger.debug(
                 "setting code comment at 0x%08X : %r, %r, %r, %r" %
                 (ea, cmt, rpt, post, ant))
             if cmt:
                 self.assertEqual(idc.MakeComm(ea, cmt), True)
             if rpt:
                 self.assertEqual(idc.MakeRptCmt(ea, rpt), True)
             if post:
                 for i, txt in enumerate(post.split('\n')):
                     self.try_ext_lin(idc.ExtLinB, ea, i, txt)
             if ant:
                 for i, txt in enumerate(ant.split('\n')):
                     self.try_ext_lin(idc.ExtLinA, ea, i, txt)
     yaunit.save('code_comments', eas)
Beispiel #23
0
def add_struc_descr(sid, structure, rep):
    """ Insert a (repeatable) comment descripting the structure whose id is sid.
    And name address in added segment annotated with structure description.
    
    Arguments:
    sid -- structure id which the added comment is describing
    structure -- structure object holding data
    rep -- add repeatable comment (True\False)
    
    Return:
    True -- if success; False otherwise
    """

    # TODO correct or not
    descr = format_comment(structure.description) + '\n'

    if idc.SetStrucComment(sid, descr, rep):

        frm = [x.frm for x in idautils.XrefsTo(sid)]

        for ea in frm:
            # Added comment for global %structure.name% variable or pointer
            if ea > idc.MaxEA():
                # getting 'member_t' using ea as 'mid'
                mptr = idaapi.get_member_by_id(ea)

                # IDA 6.8: setting member comment using 'mptr' as index
                idaapi.set_member_cmt(mptr, descr, rep)

                # IDA 6.9: mptr is type of list
                #idaapi.set_member_cmt(mptr[0], descr, rep)
            else:
                if not rep:
                    idc.MakeComm(ea, descr)
                else:
                    idc.MakeRptCmt(ea, descr)

        return True

    else:
        return False
Beispiel #24
0
def fix_callgraph(msgsend, segname, class_param, sel_param):
    '''
  fix_callgraph: msgsend, segname, class_param, sel_param

  Given the msgsend flavour address as a parameter, looks
  for the parameters (class and selector, identified by
  class_param and sel_param) and creates a new segment where
  it places a set of dummy calls named as classname_methodname
  (we use method instead of selector most of the time).
  '''

    t1 = time.time()
    if not msgsend:
        print 'ERROR: msgSend not found'
        return

    total = 0
    resolved = 0
    call_table = dict()

    for xref in idautils.XrefsTo(msgsend, idaapi.XREF_ALL):
        total += 1
        ea_call = xref.frm
        func_start = idc.GetFunctionAttr(ea_call, idc.FUNCATTR_START)
        if not func_start or func_start == idc.BADADDR:
            continue
        ea = ea_call

        method_name_ea = track_param(ea, func_start, idc.o_displ, sel_param)
        if method_name_ea:
            method_name = idc.GetString(method_name_ea, -1, idc.ASCSTR_C)
            if not method_name:
                method_name = ''
        else:
            method_name = ''

        class_name_ea = track_param(ea, func_start, idc.o_phrase, class_param)
        if class_name_ea:
            class_name = idc.GetString(class_name_ea, -1, idc.ASCSTR_C)
            if not class_name:
                class_name = ''
        else:
            class_name = ''

        if not method_name and not class_name:
            continue

        # Using this name convention, if the class and method
        # are identified by IDA, the patched call will point to
        # the REAL call and not one of our dummy functions
        #
        class_name = class_name.replace('_objc_class_name_', '')

        new_name = '_[' + class_name + '_' + method_name + ']'
        call_table[ea_call] = new_name
        resolved += 1

    print '\nFinal stats:\n\t%d total calls, %d resolved' % (total, resolved)
    print '\tAnalysis took %.2f seconds' % (time.time() - t1)

    if resolved == 0:
        print 'Nothing to patch.'
        return

    print 'Adding new segment to store new nullsubs'

    # segment size = opcode ret (4 bytes) * num_calls
    seg_size = resolved * 4
    seg_start = idc.MaxEA() + 4
    idaapi.add_segm(0, seg_start, seg_start + seg_size, segname, 'CODE')

    print 'Patching database...'
    seg_ptr = seg_start
    for ea, new_name in call_table.items():
        if idc.LocByName(new_name) != idc.BADADDR:
            offset = (idc.LocByName(new_name) - ea) & idc.BADADDR
        else:
            # create code and name it
            idc.PatchDword(seg_ptr, 0x90)  # nop
            idc.MakeName(seg_ptr, new_name)
            idc.MakeCode(seg_ptr)
            idc.MakeFunction(seg_ptr, seg_ptr + 4)
            idc.MakeRptCmt(seg_ptr, new_name)
            offset = seg_ptr - ea
            seg_ptr += 4

        dw = offset - 5
        idc.PatchByte(ea, 0xE8)
        idc.PatchDword(ea + 1, dw)
Beispiel #25
0
 def repeat(self, comment):
     idc.MakeRptCmt(self._ea, comment)
Beispiel #26
0
 def make_rpt():
     idc.MakeRptCmt(comment["address"],
                    comment["data"].encode('ascii', 'replace'))
Beispiel #27
0
 def makeRptComment(self, ea, comment):
     return idc.MakeRptCmt(ea, comment)
Beispiel #28
0
def dispatch(args):

    ## dispatch args....
    class A():
        pass

    a = A()
    for name in args:
        setattr(a, name, args[name])
    del args

    ### dispatch idp events
    if a.action == 'rename':
        debug('[*] renaming %s to %s @ %x', a.old_name, a.new_name, a.ea)
        idc.MakeNameEx(a.ea, str(a.new_name), idaapi.SN_NOWARN)
        return

    ## dispatch idb events
    if a.action == 'cmt_changed':
        if not a.cmt: a.cmt = ''
        _pcmt = a.cmt if len(a.cmt) < 10 else a.cmt[:10] + '...'
        debug('[*] cmt changed @ %X (rep:%s) - %s', a.ea, a.rep, _pcmt)
        if a.rep: idc.MakeRptCmt(a.ea, str(a.cmt))
        else: idc.MakeComm(a.ea, str(a.cmt))

    if a.action == 'struct_created':
        debug('[*] Struct %s created with id %x', a.sname, a.struct)
        print idc.AddStrucEx(-1, str(a.sname), a.union)

    if a.action == 'struct_deleted':
        sid = idc.GetStrucId(a.struct)
        sname = idc.GetStrucName(sid)
        debug('[*] Struct(%x) %s deleted', a.struct, sname)
        idc.DelStruc(sid)

    if a.action == 'struct_renamed':
        sid = idc.GetStrucId(a.struct)
        sname = idc.GetStrucName(sid)
        debug('[*] Struct(%d - %x) renamed from %s to %s', a.struct, sid,
              sname, a.sname)
        idc.SetStrucName(sid, str(a.sname))

    if a.action == 'struct_cmt_changed':
        sid = idc.GetStrucId(a.struct)
        debug('[*] Struct(%d - %x) %s - cmt changed', a.struct, sid, a.sname)
        idc.SetStrucComment(sid, a.cmt, 0)

    if a.action == 'struct_expanded':
        pass

    if a.action == 'struct_member_created':
        pass

    if a.action == 'struct_member_deleted':
        pass
    if a.action == 'struct_member_renamed':
        pass
    if a.action == 'struct_member_changed':
        pass
    if a.action == 'struct_member_':
        pass
    if a.action == 'struct_member_created':
        pass
    if a.action == 'struct_member_created':
        pass

    # if a.action == 'struct_expanded':
    #     debug('

    return 0
def fix_callgraph(msgsend, segname, class_param, sel_param):
    '''
    fix_callgraph: msgsend, segname, class_param, sel_param

    Given the msgsend flavour address as a parameter, looks
    for the parameters (class and selector, identified by
    class_param and sel_param) and creates a new segment where
    it places a set of dummy calls named as classname_methodname
    (we use method instead of selector most of the time).
    '''

    t1 = time.time()
    if not msgsend:
        print 'ERROR: msgSend not found'
        return

    total = 0
    resolved = 0
    call_table = dict()

    for xref in idautils.XrefsTo(msgsend, idaapi.XREF_ALL):
        total += 1
        ea_call = xref.frm
        func_start = idc.GetFunctionAttr(ea_call, idc.FUNCATTR_START)
        if not func_start or func_start == idc.BADADDR:
            continue
        ea = ea_call
        method_name_ea = trace_param(ea, func_start, idc.o_reg, sel_param)
        if method_name_ea and idc.isASCII(idc.GetFlags(method_name_ea)):
            method_name = idc.GetString(method_name_ea, -1, idc.ASCSTR_C)
            if not method_name:
                method_name = '_unk_method'
        else:
            method_name = '_unk_method'

        class_name_ea = trace_param(ea, func_start, idc.o_reg, class_param)
        if class_name_ea:
            class_name = idc.Name(class_name_ea)
            if not class_name:
                class_name = '_unk_class'
        else:
            class_name = '_unk_class'

        if method_name == '_unk_method' and class_name == '_unk_class':
            continue

        # Using this name convention, if the class and method
        # are identified by IDA, the patched call will point to
        # the REAL call and not one of our dummy functions
        #
        class_name = class_name.replace('_OBJC_CLASS_$_', '')
        class_name = class_name.replace('_OBJC_METACLASS_$_', '')
        new_name = '_[' + class_name + '_' + method_name + ']'
        print '%08x: %s' % (ea_call, new_name)
        call_table[ea_call] = new_name
        resolved += 1

    print '\nFinal stats:\n\t%d total calls, %d resolved' % (total, resolved)
    print '\tAnalysis took %.2f seconds' % (time.time() - t1)

    if resolved == 0:
        print 'Nothing to patch.'
        return

    print 'Adding new segment to store new nullsubs'

    # segment size = opcode ret (4 bytes) * num_calls
    seg_size = resolved * 4
    seg_start = idc.MaxEA() + 4
    idaapi.add_segm(0, seg_start, seg_start + seg_size, segname, 'CODE')

    print 'Patching database...'
    seg_ptr = seg_start
    for ea, new_name in call_table.items():
        if idc.LocByName(new_name) != idc.BADADDR:
            offset = idc.LocByName(new_name) - ea
        else:
            # create code and name it
            idc.PatchDword(seg_ptr, 0xE12FFF1E) # BX LR
            idc.MakeName(seg_ptr, new_name)
            idc.MakeCode(seg_ptr)
            idc.MakeFunction(seg_ptr, seg_ptr + 4)
            idc.MakeRptCmt(seg_ptr, new_name)
            offset = seg_ptr - ea
            seg_ptr += 4

        # patch the msgsend call
        if idc.GetReg(ea, "T") == 1:
            if offset > 0 and offset & 0xFF800000:
                print 'Offset too far for Thumb (%08x) Stopping [%08x]' % (offset, ea)
                return

            off1 = (offset & 0x7FF000) >> 12
            off2 = (offset & 0xFFF) / 2
            w1 = (0xF000 | off1)
            w2 = (0xE800 | off2) - 1
            idc.PatchWord(ea, w1)
            idc.PatchWord(ea + 2, w2)
        else:
            if offset > 0 and offset & 0xFF000000:
                print 'Offset too far (%08x) Stopping [%08x]' % (offset, ea)
            dw = (0xFA000000 | (offset - 8 >> 2))
            if dw < 0:
                dw = dw & 0xFAFFFFFF
            idc.PatchDword(ea, dw)
Beispiel #30
0
 def db_empty(cls, address, repeatable=0):
     if repeatable:
         cls.color(address, None)
         return idc.MakeRptCmt(int(address), '')
     cls.color(address, None)
     return idc.MakeComm(int(address), '')