Exemplo n.º 1
0
def main():
    idaapi.auto_wait()
    base = idaapi.get_imagebase()
    tif = idaapi.tinfo_t()

    f = open(os.environ.get("DESTPATH", "functype_"), 'w')

    for ea in Segments():
        # only code segment
        if idaapi.segtype(ea) != idaapi.SEG_CODE:
            continue

        for fva in Functions(get_segm_start(ea), get_segm_end(ea)):
            func_name = get_func_name(fva)
            has_type = idaapi.get_tinfo(tif, fva) or idaapi.guess_tinfo(
                tif, fva)

            if not has_type:
                continue

            info = serialize(tif)
            if info is None:
                continue

            print(
                hex(fva - base)[:-1], "|", func_name, "|", tif, "|",
                len(info['args']))
            f.write("0x%x|%s|%s\n" % (fva - base, func_name, json.dumps(info)))

    f.close()
    idaapi.qexit(0)
Exemplo n.º 2
0
def output_segments(out):
    """Dump binary segmentation."""
    info = idaapi.get_inf_structure()
    size = "r32" if info.is_32bit else "r64"
    out.writelines(('(', info.get_proc_name()[1], ' ', size, ' ('))
    for seg in idautils.Segments():
        out.write("\n({} {} {:d} ({:#x} {:d}))".format(
            get_segm_name(seg),
            "code" if idaapi.segtype(seg) == idaapi.SEG_CODE else "data",
            idaapi.get_fileregion_offset(seg),
            seg, idaapi.getseg(seg).size()))
    out.write("))\n")
Exemplo n.º 3
0
def output_segments(out):
    """Dump binary segmentation."""
    info = idaapi.get_inf_structure()
    size = "r32" if info.is_32bit else "r64"
    out.writelines(('(', info.get_proc_name()[1], ' ', size, ' ('))
    for seg in idautils.Segments():
        out.write("\n({} {} {:d} ({:#x} {:d}))".format(
            idaapi.get_segm_name(seg),
            "code" if idaapi.segtype(seg) == idaapi.SEG_CODE else "data",
            idaapi.get_fileregion_offset(seg),
            seg, idaapi.getseg(seg).size()))
    out.write("))\n")
Exemplo n.º 4
0
def dump_loader_info(output_filename):
    """Dump information for BAP's loader into output_filename."""
    from idautils import Segments
    import idc

    idaapi.autoWait()

    with open(output_filename, 'w+') as out:
        info = idaapi.get_inf_structure()
        size = "r32" if info.is_32bit else "r64"
        out.write("(%s %s (" % (info.get_proc_name()[1], size))
        for seg in Segments():
            out.write("\n(%s %s %d (0x%X %d))" % (
                idaapi.get_segm_name(seg),
                "code" if idaapi.segtype(seg) == idaapi.SEG_CODE else "data",
                idaapi.get_fileregion_offset(seg),
                seg, idaapi.getseg(seg).size()))
        out.write("))\n")
Exemplo n.º 5
0
def dump_loader_info(output_filename):
    """Dump information for BAP's loader into output_filename."""
    from idautils import Segments
    import idc

    idaapi.autoWait()

    with open(output_filename, 'w+') as out:
        info = idaapi.get_inf_structure()
        size = "r32" if info.is_32bit else "r64"
        out.write("(%s %s (" % (info.get_proc_name()[1], size))
        for seg in Segments():
            out.write("\n(%s %s %d (0x%X %d))" % (
                idaapi.get_segm_name(seg),
                "code" if idaapi.segtype(seg) == idaapi.SEG_CODE else "data",
                idaapi.get_fileregion_offset(seg),
                seg, idaapi.getseg(seg).size()))
        out.write("))\n")
Exemplo n.º 6
0
 def type(self):
     return idaapi.segtype(self.ea)
Exemplo n.º 7
0
def scan_for_stacks():
    def preceeding_call(ea):
        p = idautils.DecodePreviousInstruction(ea)
        if p and "BL" in idc.GetMnem(p.ea):
            return str(idc.GetOpnd(p.ea, 0))
        else:
            return ""

    def jumps_to(f, t):
        f_ea = idc.LocByName(f)
        t_ea = idc.LocByName(t)

        for start, end in idautils.Chunks(f_ea):
            ea = start
            while (ea < end):
                i = idautils.DecodeInstruction(ea)

                #Functions have data chunks in them, these are offsets and dwords. skipping 4 ahead seems like a safe choice.
                if type(i) == type(None):
                    ea += 4
                    continue

                #detect if instruction is a jump to t_ea
                m = idc.GetMnem(ea)
                if idc.GetMnem(ea) == "LDR" and idc.GetOpnd(
                        ea, 0) == "PC" and t in idc.GetOpnd(ea, 1):
                    return True
                elif idc.GetMnem(ea) == "BX" and idc.GetOpnd(ea, 0) == t:
                    return True

                try:
                    ea += i.size
                except:
                    print "0x%08x" % ea
                    print "DecodeInstruction failed!"
                    print i.size

        return False

    #return True if the function at ea has an indirect jump, like BX Reg
    #    (This is not so simple, e.g. we don't want to include jumptables etc... for now it is just this simple implementation.)
    def jumps_to_reg(ea):
        return False

    stack_addrs = []
    for s in idautils.Segments():
        if idaapi.segtype(s) != idaapi.SEG_CODE:
            print "starting scanning segment at 0x%08x" % s
            addrs = find_ret_addrs(s)
            print "found %d return addresses in segment" % len(addrs)
            stack_addrs += addrs

    log_stack_addrs(stack_addrs)

    print "okay, stored all occurences. let's find viable call chains."

    chain = []
    chains = []

    for i in range(len(stack_addrs)):

        #if this is the last one, just add to chain if had to and finish.
        if (i == (len(stack_addrs) - 1)):
            if len(chain) > 0:
                chain.append(addr)
                chains.append(chain)
            continue

        addr = stack_addrs[i]
        ret_addr = Dword(addr) & 0xFFFFFFFE  #adjust Thumb addresses
        to_f = str(idc.GetFunctionName(ret_addr))

        next_ret_addr = Dword(
            stack_addrs[i + 1]) & 0xFFFFFFFE  #adjust Thumb addresses

        pre_f = preceeding_call(next_ret_addr)
        if pre_f == to_f:
            chain.append(addr)

        elif jumps_to(pre_f, to_f):
            chain.append("direct jump")
            chain.append(addr)

        elif jumps_to_reg(pre_f):
            chain.append("indirect_jump?")
            chain.append(addr)

        #no bonus, need to start a new chain at next_ret_addr

        else:
            # if there is an existing chain, that means this addr was connected to the previous, so can be added into the chain.
            if len(chain) > 0:
                chain.append(addr)
                chains.append(chain)

            chain = []

    print "found all chains, logging..."

    log_stack_chains(chains)

    print "... and done!"
Exemplo n.º 8
0
                f = idaapi.get_func(s_addr)
                if (type(f) == type(None)):
                    print "Failed to create function! Undefined instructions?"
                    s_addr += 2
                else:
                    num_added_functions += 1
                    ea = -1
                    for c in idautils.Chunks(s_addr):
                        if c[1] > ea:
                            ea = c[1]
                    if ea != -1:
                        s_addr = ea
                    #failed?
                    else:
                        s_addr += 2
            else:
                s_addr += 2

    print "finished segment"
    return num_added_functions


num_total_added_functions = 0
for s in idautils.Segments():
    s_start = s
    if idaapi.segtype(s_start) == idaapi.SEG_CODE:
        print "starting segment at 0x%08x" % s_start
        num_total_added_functions += def_functions(s)

print "Added %d functions in total" % num_total_added_functions
Exemplo n.º 9
0
                f = idaapi.get_func(s_addr)
                if (type(f) == type(None)):
                    print "Failed to create function! Undefined instructions?"
                    s_addr += 2
                else:
                    num_added_functions += 1
                    ea = -1
                    for c in idautils.Chunks(s_addr):
                        if c[1] > ea:
                            ea = c[1]
                    if ea != -1:
                        s_addr = ea
                    #failed?
                    else:
                        s_addr += 2
            else:
                s_addr += 2

    print "finished segment"
    return num_added_functions
 

num_total_added_functions = 0
for s in idautils.Segments():
    s_start = s   
    if idaapi.segtype(s_start) == idaapi.SEG_CODE:
        print "starting segment at 0x%08x" % s_start
        num_total_added_functions += def_functions(s)

print "Added %d functions in total" % num_total_added_functions
Exemplo n.º 10
0
def scan_for_stacks():

	def preceeding_call(ea):
		p = idautils.DecodePreviousInstruction(ea)
		if p and "BL" in idc.GetMnem(p.ea):
			return str(idc.GetOpnd(p.ea, 0))
		else:
			return ""

	def jumps_to(f, t):
		f_ea = idc.LocByName(f)
		t_ea = idc.LocByName(t)

		for start,end in idautils.Chunks(f_ea):
			ea = start
			while (ea < end):
				i = idautils.DecodeInstruction(ea)

				#Functions have data chunks in them, these are offsets and dwords. skipping 4 ahead seems like a safe choice.
				if type(i) == type(None):
					ea += 4
					continue

				#detect if instruction is a jump to t_ea
				m = idc.GetMnem(ea)
				if idc.GetMnem(ea) == "LDR" and idc.GetOpnd(ea, 0) == "PC" and t in idc.GetOpnd(ea, 1):
					return True
				elif idc.GetMnem(ea) == "BX" and idc.GetOpnd(ea, 0) == t:
					return True

				try:
					ea += i.size
				except:
					print "0x%08x" % ea
					print "DecodeInstruction failed!"
					print i.size

		return False

	#return True if the function at ea has an indirect jump, like BX Reg
	#    (This is not so simple, e.g. we don't want to include jumptables etc... for now it is just this simple implementation.)
	def jumps_to_reg(ea):
		return False

	stack_addrs = []
	for s in idautils.Segments():
		if idaapi.segtype(s) != idaapi.SEG_CODE:
			print "starting scanning segment at 0x%08x" % s
			addrs = find_ret_addrs(s)
			print "found %d return addresses in segment" % len(addrs)
			stack_addrs += addrs

	log_stack_addrs(stack_addrs)

	print "okay, stored all occurences. let's find viable call chains."

	chain = []
	chains = []

	for i in range(len(stack_addrs)):

		#if this is the last one, just add to chain if had to and finish.
		if (i == (len(stack_addrs) - 1) ):
			if len(chain) > 0:
				chain.append(addr)
				chains.append(chain)
			continue

		addr = stack_addrs[i]
		ret_addr = Dword(addr) & 0xFFFFFFFE #adjust Thumb addresses
		to_f = str(idc.GetFunctionName(ret_addr))

		next_ret_addr = Dword(stack_addrs[i+1]) & 0xFFFFFFFE #adjust Thumb addresses

		pre_f = preceeding_call(next_ret_addr)
		if pre_f == to_f:
			chain.append(addr)

		elif jumps_to(pre_f, to_f):
			chain.append("direct jump")
			chain.append(addr)

		elif jumps_to_reg(pre_f):
			chain.append("indirect_jump?")
			chain.append(addr)
 
		#no bonus, need to start a new chain at next_ret_addr

		else:
			# if there is an existing chain, that means this addr was connected to the previous, so can be added into the chain.
			if len(chain) > 0:
				chain.append(addr)
				chains.append(chain)
			
			chain = []

	print "found all chains, logging..."

	log_stack_chains(chains)

	print "... and done!"
Exemplo n.º 11
0
def load_cro(li, is_crs):
    if is_crs:
        base = 0
    else:
        base = 0x00100000  # arbitrary

    li.seek(0x80)
    (Magic, NameOffset, NextCRO, PreviousCRO, FileSize, BssSize, FixedSize,
     UnknownZero, UnkSegmentTag, OnLoadSegmentTag, OnExitSegmentTag,
     OnUnresolvedSegmentTag, CodeOffset, CodeSize, DataOffset, DataSize,
     ModuleNameOffset, ModuleNameSize, SegmentTableOffset, SegmentNum,
     ExportNamedSymbolTableOffset, ExportNamedSymbolNum,
     ExportIndexedSymbolTableOffset, ExportIndexedSymbolNum,
     ExportStringsOffset, ExportStringsSize, ExportTreeTableOffset,
     ExportTreeNum, ImportModuleTableOffset, ImportModuleNum,
     ExternalPatchTableOffset, ExternalPatchNum, ImportNamedSymbolTableOffset,
     ImportNamedSymbolNum, ImportIndexedSymbolTableOffset,
     ImportIndexedSymbolNum, ImportAnonymousSymbolTableOffset,
     ImportAnonymousSymbolNum, ImportStringsOffset, ImportStringsSize,
     StaticAnonymousSymbolTableOffset, StaticAnonymousSymbolNum,
     InternalPatchTableOffset, InternalPatchNum, StaticPatchTableOffset,
     StaticPatchNum) = struct.unpack(
         "<IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII",
         li.read(0x138 - 0x80))

    if not is_crs:
        li.file2base(0, base, base + FileSize, 0)
        idaapi.add_segm(0, base, base + 0x80, "header", "RODATA")
        idaapi.add_segm(0, base + SegmentTableOffset, base + DataOffset,
                        "tables", "RODATA")

    # set segments
    li.seek(SegmentTableOffset)
    segmentDic = [("CODE", ".text"), ("DATA", ".rodata"), ("DATA", ".data"),
                  ("BSS", ".bss")]
    segmentAddress = []
    for i in range(SegmentNum):
        SegmentOffset, SegmentSize, SegmentType = struct.unpack(
            "<III", li.read(12))
        if SegmentType == 3:
            SegmentOffset = 0x08000000
            idaapi.enable_flags(base + SegmentOffset,
                                base + SegmentOffset + SegmentSize,
                                idaapi.STT_VA)

        segmentAddress.append(base + SegmentOffset)
        if SegmentSize:
            idaapi.add_segm(0, segmentAddress[i],
                            segmentAddress[i] + SegmentSize,
                            segmentDic[SegmentType][1],
                            segmentDic[SegmentType][0])

    # do internal relocations
    li.seek(InternalPatchTableOffset)
    for i in range(InternalPatchNum):
        target, patch_type, source, _, _, shift = struct.unpack(
            "<IBBBBI", li.read(12))
        target_offset = DecodeTag(segmentAddress, target)
        source_offset = segmentAddress[source] + shift
        if patch_type == 2:
            value = source_offset
        elif patch_type == 3:
            rel = source_offset - target_offset
            if rel < 0:
                rel += 0x100000000
            value = rel
        idaapi.patch_long(target_offset, value)
        f = idaapi.fixup_data_t()
        f.type = idaapi.FIXUP_OFF32
        f.off = value
        idaapi.set_fixup(target_offset, f)

    # import
    li.seek(ImportNamedSymbolTableOffset)
    importNamedSymbolTable = []
    for i in range(ImportNamedSymbolNum):
        importNamedSymbolTable.append(struct.unpack('<II', li.read(8)))

    for importNamedSymbol in importNamedSymbolTable:
        nameOffset, batchOffset = importNamedSymbol
        li.seek(nameOffset)
        name = ""
        while True:
            c = li.read(1)
            if c == '\0':
                break
            name += c
        do_import_batch(li, segmentAddress, batchOffset, name)

    li.seek(ImportModuleTableOffset)
    module = []
    for i in range(ImportModuleNum):
        module.append(struct.unpack('<IIIII', li.read(20)))

    for m in module:
        moduleNameOffset, indexed, indexedNum, anonymous, anonymousNum = m
        li.seek(moduleNameOffset)
        mname = ""
        while True:
            c = li.read(1)
            if c == '\0':
                break
            mname += c

        indexeds = []
        li.seek(indexed)
        for i in range(indexedNum):
            indexeds.append(struct.unpack('<II', li.read(8)))

        anonymouses = []
        li.seek(anonymous)
        for i in range(anonymousNum):
            anonymouses.append(struct.unpack('<II', li.read(8)))

        for i in indexeds:
            index, batchOffset = i
            do_import_batch(li, segmentAddress, batchOffset,
                            "%s_%d" % (mname, index))

        for i in anonymouses:
            tag, batchOffset = i
            do_import_batch(li, segmentAddress, batchOffset,
                            "%s_%08X" % (mname, tag))

    # export
    li.seek(ExportNamedSymbolTableOffset)
    exportNamedSymbolTable = []
    for i in range(ExportNamedSymbolNum):
        exportNamedSymbolTable.append(struct.unpack('<II', li.read(8)))

    for exportNamedSymbol in exportNamedSymbolTable:
        nameOffset, target = exportNamedSymbol
        target_offset = DecodeTag(segmentAddress, target)
        li.seek(nameOffset)
        name = ""
        while True:
            c = li.read(1)
            if c == '\0':
                break
            name += c
        if idaapi.segtype(target_offset) == idaapi.SEG_CODE:
            target_offset &= ~1
        idaapi.add_entry(target_offset, target_offset, name,
                         idaapi.segtype(target_offset) == idaapi.SEG_CODE)
        idaapi.make_name_public(target_offset)

    li.seek(ExportIndexedSymbolTableOffset)
    for i in range(ExportIndexedSymbolNum):
        target, = struct.unpack('<I', li.read(4))
        target_offset = DecodeTag(segmentAddress, target)
        if idaapi.segtype(target_offset) == idaapi.SEG_CODE:
            target_offset &= ~1
        idaapi.add_entry(i, target_offset, "indexedExport_%d" % i,
                         idaapi.segtype(target_offset) == idaapi.SEG_CODE)
        idaapi.make_name_public(target_offset)
Exemplo n.º 12
0
def load_cro(li, is_crs):
    if is_crs:
        base = 0
    else:
        base = 0x00100000 # arbitrary

    li.seek(0x80)
    (Magic,
    NameOffset,
    NextCRO,
    PreviousCRO,
    FileSize,
    BssSize,
    FixedSize,
    UnknownZero,
    UnkSegmentTag,
    OnLoadSegmentTag,
    OnExitSegmentTag,
    OnUnresolvedSegmentTag,

    CodeOffset,
    CodeSize,
    DataOffset,
    DataSize,
    ModuleNameOffset,
    ModuleNameSize,
    SegmentTableOffset,
    SegmentNum,

    ExportNamedSymbolTableOffset,
    ExportNamedSymbolNum,
    ExportIndexedSymbolTableOffset,
    ExportIndexedSymbolNum,
    ExportStringsOffset,
    ExportStringsSize,
    ExportTreeTableOffset,
    ExportTreeNum,

    ImportModuleTableOffset,
    ImportModuleNum,
    ExternalPatchTableOffset,
    ExternalPatchNum,
    ImportNamedSymbolTableOffset,
    ImportNamedSymbolNum,
    ImportIndexedSymbolTableOffset,
    ImportIndexedSymbolNum,
    ImportAnonymousSymbolTableOffset,
    ImportAnonymousSymbolNum,
    ImportStringsOffset,
    ImportStringsSize,

    StaticAnonymousSymbolTableOffset,
    StaticAnonymousSymbolNum,
    InternalPatchTableOffset,
    InternalPatchNum,
    StaticPatchTableOffset,
    StaticPatchNum) = struct.unpack("<IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII", li.read(0x138 - 0x80))

    if not is_crs:
        li.file2base(0, base, base + FileSize, 0)

    # set segments
    li.seek(SegmentTableOffset)
    segmentDic = [
        ("CODE", ".text"),
        ("DATA", ".rodata"),
        ("DATA", ".data"),
        ("BSS", ".bss")
    ]
    segmentAddress = []
    for i in range(SegmentNum):
        SegmentOffset, SegmentSize, SegmentType = struct.unpack("<III", li.read(12))
        if SegmentType == 3:
            SegmentOffset = 0x08000000
            idaapi.enable_flags(base + SegmentOffset, base + SegmentOffset + SegmentSize, idaapi.STT_VA)

        segmentAddress.append(base + SegmentOffset)
        if SegmentSize :
            idaapi.add_segm(0, segmentAddress[i], segmentAddress[i] + SegmentSize, segmentDic[SegmentType][1], segmentDic[SegmentType][0])

    # do internal relocations
    li.seek(InternalPatchTableOffset)
    for i in range(InternalPatchNum):
        target, patch_type, source, _, _, shift = struct.unpack("<IBBBBI", li.read(12))
        target_offset = DecodeTag(segmentAddress, target)
        source_offset = segmentAddress[source] + shift
        if patch_type == 2:
            value = source_offset
        elif patch_type == 3:
            rel = source_offset - target_offset
            if rel < 0:
                rel += 0x100000000
            value = rel
        idaapi.patch_long(target_offset, value)
        f = idaapi.fixup_data_t()
        f.type = idaapi.FIXUP_OFF32
        f.off = value
        idaapi.set_fixup(target_offset, f)

    # import
    li.seek(ImportNamedSymbolTableOffset)
    importNamedSymbolTable = []
    for i in range(ImportNamedSymbolNum):
        importNamedSymbolTable.append(struct.unpack('<II', li.read(8)))

    for importNamedSymbol in importNamedSymbolTable:
        nameOffset, batchOffset = importNamedSymbol
        li.seek(nameOffset)
        name = ""
        while True:
            c = li.read(1)
            if c == '\0':
                break
            name += c
        do_import_batch(li, segmentAddress, batchOffset, name)

    li.seek(ImportModuleTableOffset)
    module = []
    for i in range(ImportModuleNum):
        module.append(struct.unpack('<IIIII', li.read(20)))

    for m in module:
        moduleNameOffset, indexed, indexedNum, anonymous, anonymousNum = m
        li.seek(moduleNameOffset)
        mname = ""
        while True:
            c = li.read(1)
            if c == '\0':
                break
            mname += c

        indexeds = []
        li.seek(indexed)
        for i in range(indexedNum):
            indexeds.append(struct.unpack('<II', li.read(8)))

        anonymouses = []
        li.seek(anonymous)
        for i in range(anonymousNum):
            anonymouses.append(struct.unpack('<II', li.read(8)))

        for i in indexeds:
            index, batchOffset = i
            do_import_batch(li, segmentAddress, batchOffset, "%s_%d"%(mname, index))

        for i in anonymouses:
            tag, batchOffset = i
            do_import_batch(li, segmentAddress, batchOffset, "%s_%08X"%(mname, tag))

    # export
    li.seek(ExportNamedSymbolTableOffset)
    exportNamedSymbolTable = []
    for i in range(ExportNamedSymbolNum):
        exportNamedSymbolTable.append(struct.unpack('<II', li.read(8)))

    for exportNamedSymbol in exportNamedSymbolTable:
        nameOffset, target = exportNamedSymbol
        target_offset = DecodeTag(segmentAddress, target)
        li.seek(nameOffset)
        name = ""
        while True:
            c = li.read(1)
            if c == '\0':
                break
            name += c
        idaapi.add_entry(target_offset, target_offset, name, idaapi.segtype(target_offset) == idaapi.SEG_CODE)
        idaapi.make_name_public(target_offset)

    li.seek(ExportIndexedSymbolTableOffset)
    for i in range(ExportIndexedSymbolNum):
        target, = struct.unpack('<I', li.read(4))
        target_offset = DecodeTag(segmentAddress, target)
        idaapi.add_entry(i, target_offset, "indexedExport_%d" % i, idaapi.segtype(target_offset) == idaapi.SEG_CODE)
        idaapi.make_name_public(target_offset)