Esempio n. 1
0
    def disasm_one_inst(self, inst, addr):

        if addr % 4 != 0:
            if not os.getenv("IDP_UNALIGNED_WARNING"):
                Warning("Unaligned instruction address: {:x} ".format(addr))
                os.environ["IDP_UNALIGNED_WARNING"] = "Warned."

            self.log_with_addr("Unaligned instruction address.")

        if len(self.disasm_cache) > 0x10000:
            # TODO: Ideally disasm_cache would be an OrderedDict, but there's no C implementation in Pyhton 2, and this really slows it down.
            self.disasm_cache = {}

        # I'm assuming the jumps are always to packet start addresses, so I also disassemble
        # the rest of the packet instructions
        # TODO: can i assume that? i still have to disassemble till the end of the packet, always.

        for packet_addr in range(addr, addr + PACKET_MAX_SIZE, INST_SIZE):

            if idaapi.isLoaded(packet_addr):
                hi = self.disasm_wrapper(idaapi.get_long(packet_addr),
                                         packet_addr)
                if addr == packet_addr:
                    self.log_with_addr(
                        "Disassembling packet {:08x}: {:s}".format(
                            packet_addr, str(hi.text)))
                if hi.end_packet:
                    break
            else:
                break

        return self.disasm_wrapper(inst, addr)
Esempio n. 2
0
    def disasm_one_inst(self, inst, addr):
        
        if addr % 4 != 0:
            if not os.getenv("IDP_UNALIGNED_WARNING"):
                Warning("Unaligned instruction address: {:x} ".format(addr))
                os.environ["IDP_UNALIGNED_WARNING"] = "Warned."

            self.log_with_addr("Unaligned instruction address.")
                    
        if len(self.disasm_cache) > 0x10000:
            # TODO: Ideally disasm_cache would be an OrderedDict, but there's no C implementation in Pyhton 2, and this really slows it down.
            self.disasm_cache = {}
        
        # I'm assuming the jumps are always to packet start addresses, so I also disassemble
        # the rest of the packet instructions
        # TODO: can i assume that? i still have to disassemble till the end of the packet, always.

        for packet_addr in range(addr, addr + PACKET_MAX_SIZE, INST_SIZE):

            if idaapi.isLoaded(packet_addr):
                hi = self.disasm_wrapper(idaapi.get_long(packet_addr), packet_addr)
                if addr == packet_addr:
                    self.log_with_addr("Disassembling packet {:08x}: {:s}".format(packet_addr, str(hi.text)))
                if hi.end_packet:
                    break
            else:
                break
                
        return self.disasm_wrapper(inst, addr)
def main():
    # begin to locate linker module base

    has_art = False
    module_base = GetFirstModule()
    while module_base != None:
        module_name = GetModuleName(module_base)
        if module_name.find('linker') >= 0:
            has_art = True
            break

        module_base = GetNextModule(module_base)

    if has_art == False:
        print '[*]unable to find libart.so module base'
        return

    module_size = GetModuleSize(module_base)
    print '[*]found linker base=>0x%08X, Size=0x%08X' % (module_base,
                                                         module_size)

    print("\t[-]begin to search DT_INIT And DT_INIT_ARRAY")
    init_func_ea = 0
    init_array_ea = 0
    for ea_offset in range(module_base, module_base + module_size):
        # i don't want to write a huge single line like 'if x and x and x and...', so many ifs apear

        if 0x4620 == idaapi.get_word(ea_offset):
            if 0x20F0F8D4 == idaapi.get_long(ea_offset + 2):
                if 0x4479 == idaapi.get_word(ea_offset + 6):
                    if 0xFEA9F7FF == idaapi.get_word(ea_offset + 8):
                        if 0x490D == idaapi.get_word(ea_offset + 12):
                            if 0x2200 == idaapi.get_long(ea_offset + 14):
                                if 0x9200 == idaapi.get_word(ea_offset + 16):
                                    init_func_ea = ea_offset + 8
                                    init_array_ea = ea_offset + 30
                                    break

    print "\t[-]found INIT=>0x%08X INIT_ARRAY=>0x%08X" % (init_func_ea,
                                                          init_array_ea)
    print("\t[-]try set breakpoint there")
    AddBpt(init_func_ea)
    AddBpt(init_array_ea)

    print("[*]script by freakish, enjoy~~")
    print("[*]script finish")
def main():
    # begin to locate linker module base
    
    has_art = False
    module_base = GetFirstModule()
    while module_base != None:
        module_name = GetModuleName(module_base)
        if module_name.find('linker') >= 0:
            has_art = True
            break
        
        module_base = GetNextModule(module_base)
    
    if has_art == False:
        print '[*]unable to find libart.so module base'
        return
    
    module_size = GetModuleSize(module_base)
    print '[*]found linker base=>0x%08X, Size=0x%08X' % (module_base, module_size)
    
    
    print("\t[-]begin to search DT_INIT And DT_INIT_ARRAY")
    init_func_ea = 0
    init_array_ea = 0
    for ea_offset in range(module_base, module_base + module_size):
        # i don't want to write a huge single line like 'if x and x and x and...', so many ifs apear
        
        if 0x4620 == idaapi.get_word(ea_offset):
            if 0x20F0F8D4 == idaapi.get_long(ea_offset + 2):
                if 0x4479 == idaapi.get_word(ea_offset + 6):
                    if 0xFEA9F7FF == idaapi.get_word(ea_offset + 8):
                        if 0x490D == idaapi.get_word(ea_offset + 12):
                            if 0x2200 == idaapi.get_long(ea_offset + 14):
                                if 0x9200 == idaapi.get_word(ea_offset + 16):
                                    init_func_ea = ea_offset + 8
                                    init_array_ea = ea_offset + 30
                                    break
    
    print "\t[-]found INIT=>0x%08X INIT_ARRAY=>0x%08X" % (init_func_ea, init_array_ea)
    print("\t[-]try set breakpoint there")
    AddBpt(init_func_ea)
    AddBpt(init_array_ea)
            
    print("[*]script by freakish, enjoy~~")    
    print("[*]script finish")
def decrypt(ea, key):

    # Virtual address to IMAGE_IMPORT_DESCRIPTOR->FirstThunk
    va_iat = 0
    # Virtual address to IMAGE_IMPORT_DESCRIPTOR->OriginalFirstThunk
    va_int = 0
    tmp_ea = ea

    # Back-tracing to locate the IMAGE_IMPORT_DESCRIPTOR from import address table passed from the callback
    for xref in idautils.XrefsTo(ea, 0):
        if XrefTypeName(xref.type) == 'Data_Offset':
            va_iat = xref.frm - 0x10

    if va_iat != 0:
        print "Import Name Table->%08x" % (idaapi.get_long(va_iat) + IMG_BASE)
        va_int = idaapi.get_long(va_iat) + IMG_BASE
    else:
        return

    if va_int != 0:
        va_itd = idaapi.get_long(va_int)
        # Enumerate array of IMAGE_THUNK_DATA
        while va_itd != 0:
            va_itd = va_itd + IMG_BASE
            if va_itd > IMG_BASE and va_itd <= IMG_END:
                print "Image thunk data->%08x" % va_itd
                va_ibn = va_itd + 2
                ch = idaapi.get_byte(va_ibn)
                str = ''
                while ch != 0 and ch != 255:
                    str += chr(ch ^ key)
                    va_ibn += 1
                    ch = idaapi.get_byte(va_ibn)

                # Save the decoded import name
                print "IMAGE_IMPORT_BY_NAME->Name (%08x): %s" % (va_itd + 2,
                                                                 str)
                idc.MakeName(tmp_ea, str)
                tmp_ea += 4

            # Next IMAGE_THUNK_DATA
            va_int += 4
            va_itd = idaapi.get_long(va_int)
    else:
        return
def decrypt(ea, key):
    
    # Virtual address to IMAGE_IMPORT_DESCRIPTOR->FirstThunk
    va_iat = 0
    # Virtual address to IMAGE_IMPORT_DESCRIPTOR->OriginalFirstThunk
    va_int = 0
    tmp_ea = ea
    
    # Back-tracing to locate the IMAGE_IMPORT_DESCRIPTOR from import address table passed from the callback
    for xref in idautils.XrefsTo(ea, 0):
        if XrefTypeName(xref.type) == 'Data_Offset':
            va_iat = xref.frm - 0x10

    if va_iat != 0:
        print "Import Name Table->%08x" % (idaapi.get_long(va_iat) + IMG_BASE)
        va_int = idaapi.get_long(va_iat) + IMG_BASE
    else:
        return
        
    if va_int != 0:
        va_itd = idaapi.get_long(va_int)
        # Enumerate array of IMAGE_THUNK_DATA
        while va_itd != 0:
            va_itd = va_itd + IMG_BASE
            if va_itd > IMG_BASE and va_itd <= IMG_END:
                print "Image thunk data->%08x" % va_itd
                va_ibn = va_itd + 2
                ch = idaapi.get_byte(va_ibn)
                str = ''
                while ch != 0 and ch != 255:
                    str += chr(ch ^ key)
                    va_ibn += 1
                    ch = idaapi.get_byte(va_ibn)
                
                # Save the decoded import name
                print "IMAGE_IMPORT_BY_NAME->Name (%08x): %s" % (va_itd+2, str)
                idc.MakeName(tmp_ea, str)
                tmp_ea += 4
                
            # Next IMAGE_THUNK_DATA
            va_int += 4
            va_itd = idaapi.get_long(va_int)
    else:
        return
Esempio n. 7
0
    def ev_ana_insn(self, insn):
        b1 = idaapi.get_byte(insn.ea)
        if b1 >= 0x70 and b1 <= 0x7F:
            d1 = idaapi.get_byte(insn.ea + 1)
            b2 = idaapi.get_byte(insn.ea + 2)
            d2 = idaapi.get_byte(insn.ea + 3)
            if b2 == b1 ^ 0x01 and d1 - 2 == d2:
                idaapi.put_byte(insn.ea, 0xEB)
                idaapi.put_word(insn.ea + 2, 0x9090)

        elif b1 == 0x0F:
            b1_1 = idaapi.get_byte(insn.ea + 1)
            d1 = idaapi.get_long(insn.ea + 2)
            b2 = idaapi.get_byte(insn.ea + 6)
            b2_1 = idaapi.get_byte(insn.ea + 7)
            d2 = idaapi.get_long(insn.ea + 8)
            if b2 == 0x0F and b1_1 ^ 0x01 == b2_1 and d1 - 6 == d2:
                idaapi.put_byte(insn.ea, 0xE9)
                idaapi.put_long(insn.ea + 1, d1 + 1)
                idaapi.put_byte(insn.ea + 5, 0x90)
                idaapi.put_word(insn.ea + 6, 0x9090)
                idaapi.put_long(insn.ea + 8, 0x90909090)

        return False
def main():
    # begin to locate libart.so module base
    
    has_art = False
    module_base = GetFirstModule()
    while module_base != None:
        module_name = GetModuleName(module_base)
        if module_name.find('libart.so') >= 0:
            has_art = True
            break
        
        module_base = GetNextModule(module_base)
    
    if has_art == False:
        print '[*]unable to find libart.so module base'
        return
    
    module_size = GetModuleSize(module_base)
    print '[*]found libart.so base=>0x%08X, Size=0x%08X' % (module_base, module_size)
    
    
    print("\t[-]begin to search JNI_OnLoad")
    blx_r12_ea = 0
    for ea_offset in range(module_base, module_base + module_size):
        # i don't want to write a huge single line like 'if x and x and x and...', so many ifs apear
        
        if 0x2100 == idaapi.get_word(ea_offset):
            if 0x4630 == idaapi.get_word(ea_offset + 2):
                if 0x47E0 == idaapi.get_word(ea_offset + 4):
                    if 0x6871 == idaapi.get_word(ea_offset + 6):
                        if 0x4684 == idaapi.get_word(ea_offset + 8):
                            if 0x02CCF8D1 == idaapi.get_long(ea_offset + 10):
                                if 0x1C03 == idaapi.get_word(ea_offset + 14):
                                    blx_r12_ea = ea_offset + 4
                                    break
    
    print "\t[-]found string JNI_OnLoad BLX R12 addr=>0x%X" % blx_r12_ea
    print("\t[-]try set breakpoint there")
    AddBpt(blx_r12_ea)
            
    print("[*]script by freakish, enjoy~~")    
    print("[*]script finish")
Esempio n. 9
0
    def ev_ana_insn(self, insn):
        global hashesToNames

        insnbytes = idaapi.get_bytes(insn.ea, 3)
        if insnbytes == '\x0f\xff\xf0':
            apicrc = idaapi.get_long(insn.ea + 3)
            apiname = hashesToNames.get(apicrc)
            if apiname is None:
                print "ERROR: apicrc 0x%x NOT FOUND!" % (apicrc)
                #apiname = "UNKNOWN_APICALL"

            print "apicall: %s @ 0x%x" % (apiname, insn.ea)

            insn.itype = NN_apicall
            insn.Op1.type = idaapi.o_imm
            insn.Op1.value = apicrc
            insn.Op1.dtyp = idaapi.dt_dword
            insn.size = 7  #eat up 7 bytes

            return True
        return False
Esempio n. 10
0
    def out(self):
        """
        Generate text representation of an instruction in 'cmd' structure.
        This function shouldn't change the database, flags or anything else.
        All these actions should be performed only by u_emu() function.
        Returns: nothing
        """

        self.profiler.enable()

        #         self.log_custom("out({:s})".format(hex(self.cmd.ea)))

        buf = idaapi.init_output_buffer(1024)

        hi = self.disasm_one_inst(idaapi.get_long(self.cmd.ea), self.cmd.ea)
        # TODO: can I assume the cmd object is already set with the ana() information? as not to call the disasm again
        # and disrupt the packet disasm flow order

        if hi.template is None or hi.is_unknown or os.getenv(
                "IDP_OUT_SIMPLE_SYNTAX"):
            out_keyword(str(hi.text))
            # This simple syntax is useful to produce generic asm code for comparison
        else:
            self.out_operands_separately(hi)

        # The str() conversion is necessary because the HexagonDisassembler uses the
        # python future compatibility module that uses unicode as default strings,
        # and IDA can't handle that.
        # TODO: maybe I shoud convert everythin to str() in the disasm (or don't use the future.unicode import)

        # TODO: Split in out() and out_one_operand()

        term_output_buffer()
        cvar.gl_comm = 1  # show IDA comments (http://www.hexblog.com/?p=116)
        MakeLine(buf)

        self.profiler.disable()

        return
Esempio n. 11
0
def main():

	text_ea = None
	#for some reason SegByName() isn't working for me - maybe an IDA 7 regression?
	for seg in Segments():
		if get_segm_name(seg) == ".text":
			text_ea = seg

	if text_ea is None:
		print "ERROR: Unable to get .text segment!"
		return

	# first find all the functions
	for head in Heads(text_ea, SegEnd(text_ea)):
		func_ea = idaapi.get_func(head)
		if func_ea is None: 
			if idaapi.get_bytes(head, 13) == '\x8b\xff\xe8\x00\x00\x00\x00\x83\xc4\x04\x0f\xff\xf0':
				print  "Unrecognized apicall function at @ 0x%x"%(head)
				MakeFunction(head)

	#now name the functions
	for funcea in Functions(text_ea, SegEnd(text_ea)): 
		functionName = GetFunctionName(funcea)
		for (startea, endea) in Chunks(funcea):
			for head in Heads(startea, endea):

				insnbytes = idaapi.get_bytes(head, 3)

				if insnbytes == '\x0f\xff\xf0': 
					apicrc = idaapi.get_long(head+3)
					apiname = hashesToNames.get(apicrc)
					if apiname is None:
						print "ERROR: apicrc 0x%x NOT FOUND! @ 0x%x"%(apicrc, head)
					else:
						print "PROCESS - apicall: %s @ 0x%x"%(apiname, head)
						func_ea = idaapi.get_func(head).start_ea
						fname = idc.GetFunctionName(func_ea)
						if fname.startswith("sub_"):
							MakeName(func_ea, "apicall_" + apiname) 
Esempio n. 12
0
def check_ubfm_shift(ea):
    if idaapi.getseg(ea).use64():
        opcode = idaapi.get_long(ea)
        # opc
        o = (opcode >> 29) & 3
        # constant
        k = (opcode >> 23) & 0x3F
        if (o & 1) == 0 and k == 0x26:
            # sf
            s = (opcode >> 31) & 1
            # N
            N = (opcode >> 22) & 1
            if s == N:
                # imm
                imms = (opcode >> 10) & 0x3F
                immr = (opcode >> 16) & 0x3F
                mask = 0x1F | ((s & N) << 5)
                if imms == mask:
                    return idaapi.ARM_lsr if o else idaapi.ARM_asr, opcode, s, immr
                elif immr == imms + 1:
                    return idaapi.ARM_lsl if o else idaapi.ARM_null, opcode, s, mask - imms
    return idaapi.ARM_null, 0, 0, 0
Esempio n. 13
0
def check_mov_sequence(ea):
    oldea = ea
    reg = -1
    total = 0
    is64 = False
    while idaapi.getseg(ea).use64():
        d = idaapi.get_long(ea)
        # reg
        r = d & 0x1F
        if reg >= 0 and reg != r:
            break
        newval = DecodeMov(d, total, reg < 0)
        if newval is None:
            break
        if reg >= 0 and idaapi.get_first_fcref_to(ea) != idaapi.BADADDR:
            break
        if (d >> 31) & 1:
            is64 = True
        total = newval
        reg = r
        ea += 4
    return ea - oldea, reg, is64, total
Esempio n. 14
0
    def out(self):
        """
        Generate text representation of an instruction in 'cmd' structure.
        This function shouldn't change the database, flags or anything else.
        All these actions should be performed only by u_emu() function.
        Returns: nothing
        """
        
        self.profiler.enable()

#         self.log_custom("out({:s})".format(hex(self.cmd.ea)))

        buf = idaapi.init_output_buffer(1024)

        hi = self.disasm_one_inst(idaapi.get_long(self.cmd.ea), self.cmd.ea)
        # TODO: can I assume the cmd object is already set with the ana() information? as not to call the disasm again
        # and disrupt the packet disasm flow order

        if hi.template is None or hi.is_unknown or os.getenv("IDP_OUT_SIMPLE_SYNTAX"):
            out_keyword(str(hi.text))
            # This simple syntax is useful to produce generic asm code for comparison
        else:
            self.out_operands_separately(hi)

        # The str() conversion is necessary because the HexagonDisassembler uses the
        # python future compatibility module that uses unicode as default strings,
        # and IDA can't handle that.
        # TODO: maybe I shoud convert everythin to str() in the disasm (or don't use the future.unicode import)
        
        # TODO: Split in out() and out_one_operand()
        
        term_output_buffer()
        cvar.gl_comm = 1 # show IDA comments (http://www.hexblog.com/?p=116)
        MakeLine(buf)
        
        self.profiler.disable()
        
        return
Esempio n. 15
0
    def load_one_file(li, options, idx, basename=None):
        bypass_plt = OPT_BYPASS_PLT in options

        f = load_nxo(li)

        if idx == 0:
            if f.armv7:
                idc.SetShortPrm(idc.INF_LFLAGS, idc.GetShortPrm(idc.INF_LFLAGS) | idc.LFLG_PC_FLAT)
            else:
                idc.SetShortPrm(idc.INF_LFLAGS, idc.GetShortPrm(idc.INF_LFLAGS) | idc.LFLG_64BIT)

            idc.SetCharPrm(idc.INF_DEMNAMES, idaapi.DEMNAM_GCC3)
            idaapi.set_compiler_id(idaapi.COMP_GNU)
            idaapi.add_til2('gnulnx_arm' if f.armv7 else 'gnulnx_arm64', 1)
            # don't create tails
            idc.set_inf_attr(idc.INF_AF, idc.get_inf_attr(idc.INF_AF) & ~idc.AF_FTAIL)

        if OPT_LOAD_31_BIT in options:
            loadbase = 0x8000000
            step = 0x1000000
        elif f.armv7:
            loadbase = 0x60000000
            step = 0x10000000
        else:
            loadbase = 0x7100000000
            step = 0x100000000
        loadbase += idx * step

        f.binfile.seek(0)
        as_string = f.binfile.read(f.bssoff)
        idaapi.mem2base(as_string, loadbase)

        seg_prefix = basename if basename is not None else ''
        for start, end, name, kind in f.sections:
            if name.startswith('.got'):
                kind = 'CONST'
            idaapi.add_segm(0, loadbase+start, loadbase+end, seg_prefix+name, kind)
            segm = idaapi.get_segm_by_name(seg_prefix+name)
            if kind == 'CONST':
                segm.perm = idaapi.SEGPERM_READ
            elif kind == 'CODE':
                segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_EXEC
            elif kind == 'DATA':
                segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE
            elif kind == 'BSS':
                segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE
            idaapi.update_segm(segm)
            idaapi.set_segm_addressing(segm, 1 if f.armv7 else 2)

        # do imports
        # TODO: can we make imports show up in "Imports" window?
        undef_count = 0
        for s in f.symbols:
            if not s.shndx and s.name:
                undef_count += 1
        last_ea = max(loadbase + end for start, end, name, kind in f.sections)
        undef_entry_size = 8
        undef_ea = ((last_ea + 0xFFF) & ~0xFFF) + undef_entry_size # plus 8 so we don't end up on the "end" symbol

        undef_seg = basename + '.UNDEF' if basename is not None else 'UNDEF'
        idaapi.add_segm(0, undef_ea, undef_ea+undef_count*undef_entry_size, undef_seg, 'XTRN')
        segm = idaapi.get_segm_by_name(undef_seg)
        segm.type = idaapi.SEG_XTRN
        idaapi.update_segm(segm)
        for i,s in enumerate(f.symbols):
            if not s.shndx and s.name:
                idc.MakeQword(undef_ea)
                idaapi.do_name_anyway(undef_ea, s.name)
                s.resolved = undef_ea
                undef_ea += undef_entry_size
            elif i != 0:
                assert s.shndx
                s.resolved = loadbase + s.value
                if s.name:
                    if s.type == STT_FUNC:
                        idaapi.add_entry(s.resolved, s.resolved, s.name, 0)
                    else:
                        idaapi.do_name_anyway(s.resolved, s.name)

            else:
                # NULL symbol
                s.resolved = 0

        funcs = set()
        for s in f.symbols:
            if s.name and s.shndx and s.value:
                if s.type == STT_FUNC:
                    funcs.add(loadbase+s.value)
                    symend = loadbase+s.value+s.size
                    if Dword(symend) != 0:
                        funcs.add(symend)

        got_name_lookup = {}
        for offset, r_type, sym, addend in f.relocations:
            target = offset + loadbase
            if r_type in (R_ARM_GLOB_DAT, R_ARM_JUMP_SLOT, R_ARM_ABS32):
                if not sym:
                    print 'error: relocation at %X failed' % target
                else:
                    idaapi.put_long(target, sym.resolved)
            elif r_type == R_ARM_RELATIVE:
                idaapi.put_long(target, idaapi.get_long(target) + loadbase)
            elif r_type in (R_AARCH64_GLOB_DAT, R_AARCH64_JUMP_SLOT, R_AARCH64_ABS64):
                idaapi.put_qword(target, sym.resolved + addend)
                if addend == 0:
                    got_name_lookup[offset] = sym.name
            elif r_type == R_AARCH64_RELATIVE:
                idaapi.put_qword(target, loadbase + addend)
                if addend < f.textsize:
                    funcs.add(loadbase + addend)
            else:
                print 'TODO r_type %d' % (r_type,)
            ida_make_offset(f, target)

        for func, target in f.plt_entries:
            if target in got_name_lookup:
                addr = loadbase + func
                funcs.add(addr)
                idaapi.do_name_anyway(addr, got_name_lookup[target])

        if not f.armv7:
            funcs |= find_bl_targets(loadbase, loadbase+f.textsize)

            if bypass_plt:
                plt_lookup = f.plt_lookup
                for pco in xrange(0, f.textsize, 4):
                    pc = loadbase + pco
                    d = Dword(pc)
                    if (d & 0x7c000000) == (0x94000000 & 0x7c000000):
                        imm = d & 0x3ffffff
                        if imm & 0x2000000:
                            imm |= ~0x1ffffff
                        if 0 <= imm <= 2:
                            continue
                        target = (pc + imm * 4) - loadbase
                        if target in plt_lookup:
                            new_target = plt_lookup[target] + loadbase
                            new_instr = (d & ~0x3ffffff) | (((new_target - pc) / 4) & 0x3ffffff)
                            idaapi.put_long(pc, new_instr)

            for pco in xrange(0, f.textsize, 4):
                pc = loadbase + pco
                d = Dword(pc)
                if d == 0x14000001:
                    funcs.add(pc + 4)

        for pc, _ in f.eh_table:
            funcs.add(loadbase + pc)

        for addr in sorted(funcs, reverse=True):
            idaapi.auto_make_proc(addr)

        return 1
Esempio n. 16
0
def do_import_name(ea, name):
    idaapi.do_name_anyway(ea, "_import_" + name)

    #guess wrapper
    if idaapi.get_long(ea - 4) == 0xE51FF004: # "ldr pc, [pc, #-4]"
        idaapi.do_name_anyway(ea - 4, name)
Esempio n. 17
0
    def load_file(li, neflags, format):
        idaapi.set_processor_type("arm",
                                  idaapi.SETPROC_ALL | idaapi.SETPROC_FATAL)
        f = load_nxo(li)
        if f.armv7:
            SetShortPrm(INF_LFLAGS, GetShortPrm(INF_LFLAGS) | LFLG_PC_FLAT)
        else:
            SetShortPrm(INF_LFLAGS, GetShortPrm(INF_LFLAGS) | LFLG_64BIT)

        SetCharPrm(INF_DEMNAMES, idaapi.DEMNAM_GCC3)
        idaapi.set_compiler_id(idaapi.COMP_GNU)
        idaapi.add_til2('gnulnx_arm' if f.armv7 else 'gnulnx_arm64', 1)

        loadbase = 0x60000000 if f.armv7 else 0x7100000000

        f.binfile.seek(0)
        as_string = f.binfile.read(f.bssoff)
        idaapi.mem2base(as_string, loadbase)
        if f.text[1] != None:
            li.file2base(f.text[1], loadbase + f.text[2],
                         loadbase + f.text[2] + f.text[3], True)
        if f.ro[1] != None:
            li.file2base(f.ro[1], loadbase + f.ro[2],
                         loadbase + f.ro[2] + f.ro[3], True)
        if f.data[1] != None:
            li.file2base(f.data[1], loadbase + f.data[2],
                         loadbase + f.data[2] + f.data[3], True)

        for start, end, name, kind in f.sections:
            if name.startswith('.got'):
                kind = 'CONST'
            idaapi.add_segm(0, loadbase + start, loadbase + end, name, kind)
            segm = idaapi.get_segm_by_name(name)
            if kind == 'CONST':
                segm.perm = idaapi.SEGPERM_READ
            elif kind == 'CODE':
                segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_EXEC
            elif kind == 'DATA':
                segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE
            elif kind == 'BSS':
                segm.perm = idaapi.SEGPERM_READ | idaapi.SEGPERM_WRITE
            idaapi.update_segm(segm)
            idaapi.set_segm_addressing(segm, 1 if f.armv7 else 2)

        # do imports
        # TODO: can we make imports show up in "Imports" window?
        undef_count = 0
        for s in f.symbols:
            if not s.shndx and s.name:
                undef_count += 1
        last_ea = max(loadbase + end for start, end, name, kind in f.sections)
        undef_entry_size = 8
        undef_ea = (
            (last_ea + 0xFFF) & ~0xFFF
        ) + undef_entry_size  # plus 8 so we don't end up on the "end" symbol
        idaapi.add_segm(0, undef_ea, undef_ea + undef_count * undef_entry_size,
                        "UNDEF", "XTRN")
        segm = idaapi.get_segm_by_name("UNDEF")
        segm.type = idaapi.SEG_XTRN
        idaapi.update_segm(segm)
        for i, s in enumerate(f.symbols):
            if not s.shndx and s.name:
                MakeQword(undef_ea)
                idaapi.do_name_anyway(undef_ea, s.name)
                s.resolved = undef_ea
                undef_ea += undef_entry_size
            elif i != 0:
                assert s.shndx
                s.resolved = loadbase + s.value
                if s.name:
                    if s.type == STT_FUNC:
                        print hex(s.resolved), s.name
                        idaapi.add_entry(s.resolved, s.resolved, s.name, 0)
                    else:
                        idaapi.do_name_anyway(s.resolved, s.name)

            else:
                # NULL symbol
                s.resolved = 0

        funcs = set()
        for s in f.symbols:
            if s.name and s.shndx and s.value:
                if s.type == STT_FUNC:
                    funcs.add(loadbase + s.value)

        got_name_lookup = {}
        for offset, r_type, sym, addend in f.relocations:
            target = offset + loadbase
            if r_type in (R_ARM_GLOB_DAT, R_ARM_JUMP_SLOT, R_ARM_ABS32):
                if not sym:
                    print 'error: relocation at %X failed' % target
                else:
                    idaapi.put_long(target, sym.resolved)
            elif r_type == R_ARM_RELATIVE:
                idaapi.put_long(target, idaapi.get_long(target) + loadbase)
            elif r_type in (R_AARCH64_GLOB_DAT, R_AARCH64_JUMP_SLOT,
                            R_AARCH64_ABS64):
                idaapi.put_qword(target, sym.resolved + addend)
                if addend == 0:
                    got_name_lookup[offset] = sym.name
            elif r_type == R_AARCH64_RELATIVE:
                idaapi.put_qword(target, loadbase + addend)
                if addend < f.textsize:
                    funcs.add(loadbase + addend)
            else:
                print 'TODO r_type %d' % (r_type, )
            ida_make_offset(f, target)

        for func, target in f.plt_entries:
            if target in got_name_lookup:
                addr = loadbase + func
                funcs.add(addr)
                idaapi.do_name_anyway(addr, got_name_lookup[target])

        funcs |= find_bl_targets(loadbase, loadbase + f.textsize)

        for addr in sorted(funcs, reverse=True):
            AutoMark(addr, AU_CODE)
            AutoMark(addr, AU_PROC)

        return 1
Esempio n. 18
0
def do_import_name(ea, name):
    idaapi.do_name_anyway(ea, "_import_" + name)

    #guess wrapper
    if idaapi.get_long(ea - 4) == 0xE51FF004:  # "ldr pc, [pc, #-4]"
        idaapi.do_name_anyway(ea - 4, name)