Ejemplo n.º 1
0
	def datify(self):
		n = 0
		ea = self.get_start_ea(self.DATA)

		print "\nLooking for possible strings starting at: %s:0x%X" % (idc.SegName(ea), ea)

		for s in idautils.Strings():
			if s.ea > ea:
				if not idc.isASCII(idc.GetFlags(s.ea)) and idc.MakeStr(s.ea, idc.BADADDR):
					n += 1

		print "Created %d new ASCII strings" % n
	
		print "Converting remaining data to DWORDs...",
	
		while ea != idc.BADADDR:
			flags = idc.GetFlags(ea)
		            
			if idc.isUnknown(flags) or idc.isByte(flags):
				idc.MakeDword(ea)
				idc.OpOff(ea, 0, 0)

			ea = idc.NextAddr(ea)

		print "done.\n"
Ejemplo n.º 2
0
    def getOrigDisasm(self):
        # type: () -> str
        """
        Gets the original disassembly without any further applied transformations
        However, the formatting is different from the original and is more convenient
        for parsing
        :return: the disassembly
        """
        flags = idc.GetFlags(self.ea)
        if idc.isCode(flags):
            disasm = idc.GetDisasm(self.ea)
            disasm = self._filterComments(disasm)
            disasm = disasm.replace('  ', ' ')
        elif idc.isStruct(flags):
            disasm = self._getStructDisasm()
            # disasm = "INVALID"
        elif idc.isAlign(flags):
            disasm = idc.GetDisasm(self.ea)
            disasm = self._convertAlignDisasm(disasm)
        elif idc.isASCII(flags):
            content = self.getContent()
            numNewLines = content.count(0x0A)
            if numNewLines > 1:
                disasm = '.ascii "'
            else:
                disasm = '.asciz "'
            for i in range(len(content)):
                if content[i] == 0x00:
                    disasm += '"'
                elif chr(content[i]) == '"':
                    disasm += '\\\"'
                elif chr(content[i]) == '\\':
                    disasm += '\\\\'
                elif content[i] == 0x0A:
                    disasm += '\\n'
                    numNewLines -= 1
                    if numNewLines > 1:
                        disasm += '"\n\t.ascii "'
                    elif numNewLines == 1:
                        disasm += '"\n\t.asciz "'
                elif chr(content[i]) == ' ':
                    disasm += ' '
                elif not chr(content[i]).isspace():
                    disasm += chr(content[i])
                else:
                    # TODO [INVALID] arm-none-eabi doesn't recognize \xXX? \x seems to become a byte.
                    disasm += '\\x%02X' % content[i]
        elif idc.isData(flags):
            disasm = self._getDataDisasm()
        else:
            disasm = idc.GetDisasm(self.ea)
            disasm = self._filterComments(disasm)
            disasm = disasm.replace('  ', ' ')

        # parse force command
        if '<force>' in self.getComment():
            comment = self.getComment()
            disasm = comment[comment.index('<force> ') + len('<force> '):]
        return disasm
Ejemplo n.º 3
0
    def stringify(self):
        n = 0
        ea = self.get_start_ea(self.DATA)

        if ea == idc.BADADDR:
            ea = idc.FirstSeg()

        print ("Looking for possible strings starting at: %s:0x%X..." % (idc.SegName(ea), ea)),

        for s in idautils.Strings():
            if s.ea > ea:
                if not idc.isASCII(idc.GetFlags(s.ea)) and idc.MakeStr(s.ea, idc.BADADDR):
                    n += 1

        print "created %d new ASCII strings" % n
Ejemplo n.º 4
0
    def stringify(self):
        n = 0
        ea = self.get_start_ea(self.DATA)

        if ea == idc.BADADDR:
            ea = idc.FirstSeg()

        print("Looking for possible strings starting at: %s:0x%X..." %
              (idc.SegName(ea), ea)),

        for s in idautils.Strings():
            if s.ea > ea:
                if not idc.isASCII(idc.GetFlags(s.ea)) and idc.MakeStr(
                        s.ea, idc.BADADDR):
                    n += 1

        print "created %d new ASCII strings" % n
Ejemplo n.º 5
0
    def changeASCII(start_ea, ):
        """
        finds all ascii named data and changes it to bytes and removes its name
        """
        found = False
        for ea, name in idautils.Names():
            d = Data.Data(ea)
            if idc.isASCII(d._getFlags()):
                found = True
                print("%07X: Make ASCII -> Byte" % ea)
                idc.MakeByte(ea)
                idc.MakeName(ea, '')

        if found:
            print("changed all ASCII data to byte data!")
        else:
            print("no ASCII data was found!")
Ejemplo n.º 6
0
def get_first_string(ea):
    """ walk up and grab a string like this
    push    offset aGamegetpotionc ; "GameGetPotionColorUint"
    lea     ecx, [ebp+var_244] ; int
    call    makestr
    push    offset sub_435ADA
    lea     eax, [ebp+var_244]
    mov     ecx, esi
    push    eax
    call    register_global ; <---- ea
    """
    maybe_start = idc.get_func_attr(ea, idc.FUNCATTR_START)
    limit = 0
    if maybe_start == idc.BADADDR:
        limit = 10

    cur_ea = ea
    limit_count = 0
    while cur_ea != idc.BADADDR:
        # are we over limit or up to the func start?
        limit_count += 1
        limit_exceeded = (limit > 0 and limit_count > limit)
        too_far = (maybe_start != idc.BADADDR and cur_ea < maybe_start)
        if limit_exceeded or too_far:
            LOG.error(
                "Failed to find string walking backwards from {:08X}".format(
                    ea))
            return None

        prev_ins = idautils.DecodePreviousInstruction(cur_ea)
        prev_ea = prev_ins.ea

        # did we find it?
        if idc.GetMnem(prev_ea) == 'push':
            if idc.get_operand_type(prev_ea, 0) in [idc.o_mem, idc.o_imm]:
                # push offset found!
                pushed_addr = idc.GetOperandValue(prev_ea, 0)
                if idc.isASCII(idc.GetFlags(pushed_addr)):
                    s = idc.GetString(pushed_addr, -1, idc.ASCSTR_C)
                    #LOG.debug("Read string {} from {:08X} from instruction at {:08X}".format(repr(s), pushed_addr, prev_ea))
                    return s

        cur_ea = prev_ea
Ejemplo n.º 7
0
def removeText(start_ea, end_ea):
    """
    removes all ASCII text within range
    :param start_ea: start of the range to remove
    :param end_ea: end of the range to remove
    """
    found = False
    ea = start_ea
    while ea < end_ea:
        d = Data.Data(ea)
        if idc.isASCII(d.getFlags()):
            found = True
            print("%07X: Make text -> Byte" % ea)
            idc.MakeByte(ea)
        ea += d.getSize()
    if found:
        print("changed all ASCII data to byte data!")
    else:
        print("no ASCII data was found!")
Ejemplo n.º 8
0
def changeASCII(start_ea, end_ea):
    """
    finds all ascii data which is not user named and changes it to bytes and removes its name
    """
    found = False
    ea = start_ea
    while ea < end_ea:
        d = Data.Data(ea)
        if idc.isASCII(d.getFlags()):
            found = True
            print("%07X: Make ASCII -> Byte" % ea)
            idc.MakeByte(ea)
            idc.MakeName(ea, 'ASCII_%07X' % ea)
        ea += d.getSize()

    if found:
        print("changed all ASCII data to byte data!")
    else:
        print("no ASCII data was found!")
Ejemplo n.º 9
0
 def nextascii(self, ea, ui=True):
     # type: (int) -> str
     """
     returns the next data item containing ascii characters (seems valid for utf too)
     :param ea: the address to start searching from
     :param ui: if True, jump to address automatically
     :return: hex formatted str of the address of the next ascii item
     """
     # don't count this item
     ea = Data.Data(ea).ea + Data.Data(ea).getSize()
     output = idaapi.BADADDR
     while ea < self.end_ea:
         d = Data.Data(ea)
         # ARM, unless it's a branch
         if idc.isASCII(d._getFlags()):
             output = ea
             break
         ea += d.getSize()
     if ui: idaapi.jumpto(output)
     return '%07X' % output
Ejemplo n.º 10
0
def _read_struct_member_once(ea, flags, size, member_sid, member_size, asobject):
    """Read part of a struct member for _read_struct_member."""
    if idc.isByte(flags):
        return read_word(ea, 1), 1
    elif idc.isWord(flags):
        return read_word(ea, 2), 2
    elif idc.isDwrd(flags):
        return read_word(ea, 4), 4
    elif idc.isQwrd(flags):
        return read_word(ea, 8), 8
    elif idc.isOwrd(flags):
        return read_word(ea, 16), 16
    elif idc.isASCII(flags):
        return idc.GetManyBytes(ea, size), size
    elif idc.isFloat(flags):
        return idc.Float(ea), 4
    elif idc.isDouble(flags):
        return idc.Double(ea), 8
    elif idc.isStruct(flags):
        value = read_struct(ea, sid=member_sid, asobject=asobject)
        return value, member_size
    return None, size
Ejemplo n.º 11
0
 def isString(self, reference):
     return idc.isASCII(self.getFlags(reference))
Ejemplo n.º 12
0
    def make_struc_member(self,
                          object_version,
                          address,
                          member_type=ya.OBJECT_TYPE_STRUCT_MEMBER):
        struc_object_id = object_version.get_parent_object_id()

        struc_id = 0
        try:
            struc_id = self.struc_ids[struc_object_id]
        except:
            return
        is_union = struc_id in self.union_ids

        offset = address

        if is_union:
            last_offset = idc.GetLastMember(struc_id)
            if last_offset == idc.BADADDR:
                last_offset = -1
            if last_offset < offset:
                for i in xrange(last_offset + 1, offset + 1):
                    idc.AddStrucMember(struc_id, "yaco_filler_%d" % i, 0,
                                       idc.FF_BYTE | idc.FF_DATA, -1, 1)
                    # ensure that 'offset' fields are present

        member_size = object_version.get_size()
        member_name = object_version.get_name()

        flags = object_version.get_object_flags()
        if idc.isStruct(flags):
            # if the sub field is a struct, it must have a single Xref field with the struct object id
            try:
                sub_struc_object_id = object_version.getXRefIdsAt(0, 0)[0]
                sub_struc_id = self.struc_ids[sub_struc_object_id]

                #                 logger.debug("%20s: adding sub member at offset 0x%08X,
                #                               size=0x%08X (sub=0x%.016X, size=0x%08X) with name %s" %
                #                             (
                #                                 idc.GetStrucName(struc_id), offset, member_size, sub_struc_id,
                #                                               idc.GetStrucSize(sub_struc_id), object_version.get_name()
                #                             ))

                sub_struc_size = idc.GetStrucSize(sub_struc_id)
                if sub_struc_size == 0:
                    logger.error(
                        "%20s: adding sub member at offset 0x%08X, size=0x%08X "
                        "(sub=0x%.016X, size=0x%08X) with name %s : sub struc size is ZERO"
                        % (idc.GetStrucName(struc_id), offset, member_size,
                           sub_struc_id, idc.GetStrucSize(sub_struc_id),
                           object_version.get_name()))

                else:
                    nitems = member_size / sub_struc_size

                    YaToolIDATools.SetStrucmember(struc_id, member_name,
                                                  offset, flags, sub_struc_id,
                                                  nitems)

            except KeyError:
                logger.error(
                    "Error while looking for sub struc in struc %s, offset 0x%08X (field name='%s')"
                    % (self.hash_provider.hash_to_string(struc_object_id),
                       offset, object_version.get_name()))
                traceback.print_exc()
        elif idc.isEnum0(flags):
            # an enum is applied here
            try:
                sub_enum_object_id = object_version.getXRefIdsAt(0, 0)[0]
                sub_enum_id = self.enum_ids[sub_enum_object_id]

                name_ok = idc.SetMemberName(struc_id, offset, member_name)
                if name_ok is not True:
                    logger.debug(
                        "Error while setting member name (enum) : "
                        "(struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d, tid=0x%016X"
                        % (name_ok, idc.GetStrucName(struc_id), member_name,
                           offset, flags, member_size, sub_struc_id))
                else:
                    sub_enum_size = idc.GetEnumWidth(sub_enum_id)
                    if sub_enum_size == 0:
                        sub_enum_size = member_size

                    nitems = member_size / sub_enum_size
                    ret = idc.SetMemberType(struc_id, offset, flags,
                                            sub_enum_id, nitems)
                    if ret == 0:
                        logger.debug(
                            "Error while setting member type (enum) : "
                            "(struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d, tid=0x%016X"
                            % (ret, idc.GetStrucName(struc_id), member_name,
                               offset, flags, member_size, sub_struc_id))

            except KeyError:
                logger.error(
                    "Error while looking for sub enum in struc %s, offset 0x%08X (field name='%s')"
                    % (struc_object_id, offset, member_name))
                traceback.print_exc()

        else:
            #             logger.debug("%20s: adding member at offset 0x%08X, size=0x%08X with name %s" %
            #                         (
            #                         idc.GetStrucName(struc_id), offset, member_size, object_version.get_name()
            #                         ))
            tid = -1
            if idc.isASCII(flags):
                logger.debug(
                    "object: %s : %s" % (self.hash_provider.hash_to_string(
                        object_version.get_id()), object_version.get_name()))
                try:
                    tid = object_version.get_string_type()
                except KeyError:
                    tid = idc.ASCSTR_C

            name_ok = idc.SetMemberName(struc_id, offset, member_name)
            if name_ok is not True:
                logger.debug(
                    "Error while setting member name :" +
                    " (struc_id=0x%08X, struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d)"
                    % (struc_id, idc.GetStrucName(struc_id), member_name,
                       offset, flags, member_size))
            else:
                item_size = YaToolIDATools.get_field_size(flags, tid)
                nitems = member_size / item_size
                # IDA BUG : 4-byte chars are stored as 2 double words, thus me must
                # multiply nitem by 2!
                ret = idc.SetMemberType(struc_id, offset, flags, tid, nitems)
                if ret == 0:
                    logger.debug(
                        "Error while setting member type :" +
                        " (struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d)"
                        % (idc.GetStrucName(struc_id), member_name, offset,
                           flags, member_size))

        try:
            repeatable_headercomment = self.sanitize_comment_to_ascii(
                object_version.get_header_comment(True))
            idc.SetMemberComment(struc_id, offset, repeatable_headercomment, 1)
        except KeyError:
            pass

        try:
            nonrepeatable_headercomment = self.sanitize_comment_to_ascii(
                object_version.get_header_comment(False))
            idc.SetMemberComment(struc_id, offset, nonrepeatable_headercomment,
                                 0)
        except KeyError:
            pass

        member_id = idc.GetMemberId(struc_id, offset)

        self.set_struct_member_type(object_version, member_id)
        if object_version.get_type() == ya.OBJECT_TYPE_STRUCT_MEMBER:
            self.strucmember_ids[object_version.get_id()] = member_id
Ejemplo n.º 13
0
    def make_data(self, object_version, address):
        size = 0
        try:
            size = object_version.get_size()
        except KeyError:
            pass
        flags = None
        try:
            flags = object_version.get_object_flags()
        except KeyError:
            pass

        if size == 0:
            idc.MakeUnkn(address, idc.DOUNK_EXPAND)
        else:
            if flags is not None:
                if idc.isASCII(flags):
                    try:
                        str_type = object_version.get_string_type()
                        YaToolIDATools.check_and_set_str_type(str_type)
                    except KeyError:
                        pass
                    idc.MakeStr(address, address + size)
                    idc.SetFlags(address, flags)

                if idc.isStruct(flags):
                    found = False
                    for xref_offset_operand, xref_id_attr in object_version.get_xrefed_id_map(
                    ).iteritems():
                        (xref_offset, xref_operand) = xref_offset_operand
                        for xref_hash, xref_attrs in xref_id_attr:

                            if xref_hash in self.struc_ids:
                                struc_id = self.struc_ids[xref_hash]
                                if DEBUG_EXPORTER:
                                    logger.debug(
                                        "making unknown from 0x%08X to 0x%08X"
                                        % (address, address + size))
                                idaapi.do_unknown_range(
                                    address, size, idc.DOUNK_DELNAMES)

                                #   idc.MakeUnkn(address, DOUNK_SIMPLE | idc.DOUNK_DELNAMES)
                                #   for i in xrange(1, size):
                                #       MakeName(address + i, "")
                                #       idc.MakeUnkn(address + i, DOUNK_SIMPLE | idc.DOUNK_DELNAMES)
                                # idc.MakeStructEx uses idaapi.doStruct (but asks for name while
                                # we already have the struc id)
                                if DEBUG_EXPORTER:
                                    logger.debug(
                                        "Making struc at %s : %s (sizeof(%s)=0x%08X, size=0x%08X, flags=0x%08X"
                                        % (self.yatools.address_to_hex_string(
                                            address),
                                           self.yatools.address_to_hex_string(
                                               struc_id),
                                           idaapi.get_struc_name(struc_id),
                                           idc.GetStrucSize(struc_id), size,
                                           flags))
                                idc.SetCharPrm(idc.INF_AUTO, True)
                                idc.Wait()
                                if idaapi.doStruct(address, size,
                                                   struc_id) == 0:
                                    if DEBUG_EXPORTER:
                                        logger.warning("Making struc failed")
                                idc.SetCharPrm(idc.INF_AUTO, False)
                                #                                     idc.SetFlags(address, flags)
                                found = True
                    else:
                        logger.error(
                            "bad struc flags : idc.isStruct is true but no xref available for object %s"
                            % self.hash_provider.hash_to_string(
                                object_version.get_id()))
                    if not found:
                        logger.error(
                            "bad struc flags : idc.isStruct is true "
                            "but no struc available for object %s (%s)" %
                            (self.hash_provider.hash_to_string(
                                object_version.get_id()),
                             object_version.get_name()))
                else:
                    idc.MakeData(address, flags & (idc.DT_TYPE | idc.MS_0TYPE),
                                 size, 0)

            else:
                idc.MakeData(address, idc.FF_BYTE, size, 0)

        self.make_name(object_version, address, False)

        self.set_type(object_version, address)
Ejemplo n.º 14
0
 def isString(self, reference):
     return idc.isASCII(self.getFlags(reference))
Ejemplo n.º 15
0
Archivo: data.py Proyecto: hakril/midap
 def is_ascii(self):
     return idc.isASCII(self.flags)
Ejemplo n.º 16
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)