Exemplo n.º 1
0
def push_comms():
    global skel_conn
    commBL = [
        "size_t", "int", "LPSTR", "char", "char *", "lpString", "unsigned int",
        "void *", "indirect table for switch statement", "this",
        "jump table for switch statement", "switch jump"
    ]
    for i in range(idc.MinEA(), idc.MaxEA()):
        if idc.GetCommentEx(
                i, 0) is not None and not idc.GetCommentEx(i, 0) in commBL:
            if not skel_conn.push_comment(i, idc.GetCommentEx(i, 0)):
                return -1
        elif idc.GetCommentEx(
                i, 1) is not None and not idc.GetCommentEx(i, 1) in commBL:
            if not skel_conn.push_comment(i, idc.GetCommentEx(i, 1)):
                return -1
    for function_ea in idautils.Functions(idc.MinEA(), idc.MaxEA()):
        fName = idc.GetFunctionName(function_ea)
        if hasSubNoppedPrefix(fName) is False:
            if not skel_conn.push_name(function_ea, fName):
                g_logger.error("Error sending function name %s" % (fName))
        # if idc.GetFunctionCmt(function_ea,0) != "":
        #    push_change("idc.SetFunctionCmt",shex(function_ea),idc.GetFunctionCmt(i,0))
        # elif idc.GetFunctionCmt(function_ea,1) != "":
        #    push_change("idc.SetFunctionCmt",shex(function_ea),idc.GetFunctionCmt(function_ea,1))
    return
Exemplo n.º 2
0
def sample_dest():
    global x
    src_hashes = {}
    for i in x.split("|"):
        z = i.split(":")
        if src_hashes.has_key(z):
            src_hashes[z] = "baadf00d"
        else:
            src_hashes[i[1]] = i[0]
    dst_hashes = {}
    for addr in idautils.Functions(idc.MinEA(), idc.MaxEA()):
        fname = idc.GetFunctionName(addr)
        if fname.startswith("sub_"):
            z = calc_hash(addr)
            if dst_hashes.has_key(z):
                src_hashes[z] = "baadf00d"
            else:
                src_hashes[z] = addr
    for x in dst_hashes:
        if dst_hashes[x] == "baadf00d":
            continue
        if src_hashes.has_key(x):
            if src_hashes[x] != "baadf00d":
                idc.MakeNameEx(dst_hashes[x], src_hashes[x], SN_NOWARN)
    print full_hash
Exemplo n.º 3
0
def main():
    if _IN_IDA:
        # # get dyld_shared_cache path from IDA's openFile dialog
        print "[+] Please choose the original dyld_shared_cache_arm64"
        dsc_path = idc.AskFile(0, "*.*", "dyld shared cache file")
    else:
        dsc_path = sys.argv[1]

    if not dsc_path or not os.path.exists(dsc_path):
        raise RuntimeError("Couldn't find the dyld shared cache file..")

    print "[+] about to parse %s.." % (dsc_path)
    dsc_file = open(dsc_path, "rb")
    adrfind = AddrFinder(dsc_file, cache_symbols=False)
    map_shared_bridges(dsc_file, adrfind)
    if _IN_IDA:
        addresses = sorted(set(get_bad_addresses()))
    else:
        addresses = sorted(set(eval(open("addrs.txt", "rb").read())))

    segments, exports = get_segments_and_exports_for_addresses(
        addresses, adrfind)
    # segments = join_neighbors(segments, threshold=0x1000)
    if _IN_IDA:
        map_segments(segments, dsc_file)
        map_exports(exports)
        idaapi.analyze_area(idc.MinEA(), idc.MaxEA())
Exemplo n.º 4
0
def msr_parse():
	start = idc.MinEA()
	stop = idc.MaxEA()
	rdmsr_addr = idaapi.find_binary(start, stop, "0F 32", 0, 0) 
	wrmsr_addr = idaapi.find_binary(start, stop, "0F 30", 0, 0)
	cpuid_addr = idaapi.find_binary(start, stop, "0F A2", 0, 0)
	idc.MakeCode(each)
Exemplo n.º 5
0
def save_file(output_file):
    """ Save the patched file """
    DIFF_RE = re.compile(r'([A-F0-9]+): ([A-F0-9]+) ([A-F0-9]+)')

    idc.GenerateFile(idaapi.OFILE_DIF, output_file, 0, idc.MaxEA(), 0)
    diff_file = open(output_file, "rb").read()
    orig_file = open(idc.GetInputFilePath(), "rb").read()
    print "OK"
    diff_file = diff_file.split("\n")
    total = 0
    success = 0
    for line in diff_file:
        match = DIFF_RE.match(line)
        if match:
            groups = match.groups()
            total += 1
            offset = int(groups[0], 16)
            orig_byte = groups[1].decode('hex')
            new_byte = groups[2].decode('hex')
            if orig_file[offset] == orig_byte:
                orig_file = orig_file[:offset] + new_byte + orig_file[offset +
                                                                      1:]
                success += 1
            else:
                print "Error matching %02x at offset %x..." % (groups[1],
                                                               offset)

    new_file = open(output_file, 'wb')
    new_file.write(orig_file)
    new_file.close()
    print "%i/%i patches applied" % (success, total)
Exemplo n.º 6
0
def method_2():
    """
    Simple way to convert a table of strings into strings on IDA.
    """
    start = AskAddr(ScreenEA(), "Where do I start looking for strings?")
    end = idc.MaxEA()

    cur_string = ""
    last_byte = None
    for cur_ea in xrange(start, end):
        byte_ = chr(Byte(cur_ea))
        if not is_printable(byte_):
            # If this is a terminating byte, check if the collected bytes form a string.
            if byte_ == '\x00':
                if not len(cur_string):
                    print "Last string at 0x%.8x" % (cur_ea)
                    break

                else:
                    print "0x%.8x : %s" % (cur_ea - len(cur_string),
                                           cur_string)
                    MakeStr(cur_ea - len(cur_string), cur_ea + 1)
                    cur_string = ""
        else:
            cur_string += byte_

        last_byte = byte_
    def find_function_epilogue_bxlr(self, makecode=False):
        '''
        Find opcode bytes corresponding to BX LR.
        This is a common way to return from a function call.
        Using the IDA API, convert these opcodes to code. This kicks off IDA analysis.
        '''
        EAstart = idc.MinEA()
        EAend = idc.MaxEA()

        ea = EAstart
        length = 2  # this code isn't tolerant to values other than 2 right now

        fmt_string = "Possible BX LR 0x%08x == "
        for i in range(length):
            fmt_string += "%02x "

        while ea < EAend:
            instructions = []
            for i in range(length):
                instructions.append(idc.Byte(ea + i))

            if not ida_bytes.isCode(ida_bytes.getFlags(ea)) and instructions[
                    0] == 0x70 and instructions[1] == 0x47:
                if self.printflag:
                    print fmt_string % (ea, instructions[0], instructions[1])
                if makecode:
                    idc.MakeCode(ea)
            ea = ea + length
Exemplo n.º 8
0
def find_binary_instruction_start(search_start_location, search_direction, target, min_location=idc.MinEA(),
                                  max_location=idc.MaxEA()):
    """
    Description:
        Given a starting location, target, and direction, find an instruction starting with the target bytes.

    Input:
        search_start_location - The EA to start searching at
        search_direction - either idc.SEARCH_UP or idc.SEARCH_DOWN
        target - The target as space separated bytes (i.e. '55' for 'push ebp')
        min_location - The minimum EA to accept results for (default: idc.MinEA())
        max_location - The maximum EA to accept results for (default: idc.MaxEA())

    Output:
        Returns the first matching location if found, otherwise idc.BADADDR
    """
    target = target.upper()
    while search_start_location < max_location:
        ea = idc.FindBinary(search_start_location, search_direction, target)
        if (min_location <= ea < max_location
                and ea == idc.ItemHead(ea)
                and idaapi.get_many_bytes(ea, idc.ItemSize(ea)).encode('hex').upper().startswith(target.replace(' ', ''))):
            return ea
        else:
            search_start_location = ea + (1 if search_direction == idc.SEARCH_DOWN else -1)
    return idc.BADADDR
Exemplo n.º 9
0
def pushFunctionsNames():
    """
        update les noms de fonctions depuis l'idb actuel
    """
    global sample_id

    for addr in idautils.Functions(idc.MinEA(), idc.MaxEA()):
        fname = GetFunctionName(addr)
        if fname != "" and not hasSubNoppedPrefix(fname):
            if skel_conn.push_name(addr, fname) == -1:
                return -1
    return 0
Exemplo n.º 10
0
def save_call_graph():
    cur = idc.MinEA()
    end = idc.MaxEA()
    #D:\source\test1\test_dir\p_16
    #path_dir=os.path.dirname(idc.GetIdbPath())
    #p_dir=path_dir.split('\\')[-1]
    #elf_name=os.path.basename(idc.GetIdbPath()).split('.')[-2]
    i64_file = idc.GetIdbPath()
    first_dot = i64_file.find('.')
    no_dot_file = i64_file[:first_dot]
    gdl_path = no_dot_file + '.gdl'
    idc.GenCallGdl(gdl_path, 'Call Gdl', idc.CHART_GEN_GDL)
Exemplo n.º 11
0
def is_valid_ea(ea):
    """
    Description:
        Returns true for valid EAs, False for invalid ones.

    Input:
        ea - The EA to check

    Output:
        True if the EA is valid, False if it is not
    """
    return ea not in [INVALID, UNUSED, idc.BADADDR] and idc.MinEA() <= ea <= idc.MaxEA()
Exemplo n.º 12
0
def push_functions_names():
    """
        Push the defined function names
    """
    global skel_conn

    for addr in idautils.Functions(idc.MinEA(), idc.MaxEA()):
        fname = GetFunctionName(addr)
        if fname != "" and not hasSubNoppedPrefix(fname):
            if skel_conn.push_name(addr, fname) == -1:
                return False
    return True
Exemplo n.º 13
0
def autoCode(hex_value):
  start = idc.MinEA();
  len=idc.MaxEA()-start;
  addr=start;
  flag = False
  for x in range(len):
    addr = idc.FindBinary(addr, SEARCH_DOWN|SEARCH_CASE|SEARCH_NEXT, hex_value)
    if addr != idc.BADADDR:
      make_code(addr,addr+4)
      print "{:>8X} {:<32}".format(addr,idc.GetDisasm(addr))
    else:
      flag = False
    #addr=idc.NextHead(addr)
  return 0
Exemplo n.º 14
0
        def renamed(self, *args):
            g_logger.debug("[IDP Hook] Something is renamed")
            ea, new_name, is_local_name = args
            if ea >= idc.MinEA() and ea <= idc.MaxEA():
                if is_local_name:
                    g_logger.warning("Local names are unimplemented")
                    pass
                else:
                    if not SkelUtils.name_blacklist(new_name):
                        self.skel_conn.push_name(ea, new_name)
            else:
                g_logger.warning("ea outside program...")

            return idaapi.IDP_Hooks.renamed(self, *args)
Exemplo n.º 15
0
        def renamed(self, *args):
            g_logger.debug("[IDB Hook] Something is renamed")
            ea, new_name, is_local_name = args
            if ea > idc.MinEA() and ea < idc.MaxEA():
                if is_local_name:
                    # XXX push_new_local_name(ea, new_name)
                    pass
                else:
                    if not SkelUtils.name_blacklist(new_name):
                        self.skel_conn.push_name(ea, new_name)
            else:
                print "ea outside program..."

            return idaapi.IDP_Hooks.renamed(self, *args)
Exemplo n.º 16
0
def find_string_table_refs(string_table_start, string_table_end, mark=False):
    image_start = idc.MinEA()
    image_end = idc.MaxEA()
    image_size = image_end - image_start

    print "Analyzing image from %.8x-%.8x of size %.8x" % (
        image_start, image_end, image_size)

    for cur_ea in xrange(image_start, image_end, 4):
        cur_long = Dword(cur_ea)
        if cur_long >= string_table_start and cur_long < string_table_end:
            if mark:
                SetType(cur_ea, "char *ptr;")

            print "Found string table ref at 0x%.8x to 0x%.8x (%s)" % (
                cur_ea, cur_long, GetDisasm(cur_ea))
    def nonfunction_first_instruction_heuristic(self, makefunction=False):
        EAstart = idc.MinEA()
        EAend = idc.MaxEA()
        ea = EAstart

        flag_code_outside_function = False
        self.printflag = False

        while ea < EAend:

            # skip functions, next instruction will be the target to inspect
            function_name = idc.GetFunctionName(ea)
            if function_name != "":

                flag_code_outside_function = False

                # skip to end of function and keep going
                # ea = idc.FindFuncEnd(ea)
                #if self.printflag:
                #    print "Skipping function %s" % (function_name)

                ea = ida_search.find_not_func(ea, 1)
                continue

            elif ida_bytes.isCode(ida_bytes.getFlags(ea)):

                # code that is not a function
                # get mnemonic to see if this is a push
                mnem = idc.GetMnem(ea)

                if makefunction and (mnem == "PUSH" or mnem == "PUSH.W"
                                     or mnem == "STM" or mnem == "MOV"):
                    if self.printflag:
                        print "nonfunction_first_instruction_heuristic() making function %08x" % ea
                    idc.MakeFunction(ea)
                    flag_code_outside_function = False
                    ea = ida_search.find_not_func(ea, 1)
                    continue

                else:
                    if self.printflag:
                        print "nonfunction_first_instruction_heuristic() other instruction %08x\t'%s'" % (
                            ea, mnem)
                    ea = idc.NextFunction(ea)
                    continue

            ea += 1
Exemplo n.º 18
0
def pci_analisys():
	# searching snippets:
	# ------------------- 
	# mov eax, 8000xxxxh ; optional line
	# mov dx, CF8h
	# out dx, eax
	# -------------------
	# mov dx, CF8h
	# mov eax, 8000xxxxh
	# out dx, eax
	# -------------------
	position_start = idc.MinEA()
	position_stop = idc.MaxEA()
	outdxeax = position_start
	while outdxeax :
		outdxeax = idaapi.find_binary(position_start, position_stop, "66 EF", 0, 0)
		if outdxeax:
			position_start = outdxeax + 1
    def make_new_functions_heuristic_push_regs(self, makefunction=False):
        '''
        After converting bytes to instructions, Look for PUSH instructions that are likely the beginning of functions.
        Convert these code areas to functions.
        '''
        EAstart = idc.MinEA()
        EAend = idc.MaxEA()
        ea = EAstart

        while ea < EAend:
            if self.printflag:
                print "EA %08x" % ea

            ea_function_start = idc.GetFunctionAttr(ea, idc.FUNCATTR_START)

            # If ea is inside a defined function, skip to end of function
            if ea_function_start != idc.BADADDR:
                ea = idc.FindFuncEnd(ea)
                continue

            # If current ea is code
            if ida_bytes.isCode(ida_bytes.getFlags(ea)):
                # Looking for prologues that do PUSH {register/s}
                mnem = idc.GetMnem(ea)

                #
                if (mnem == "PUSH"):
                    if makefunction:
                        if self.printflag:
                            print "Converting code to function @ %08x" % ea
                        idc.MakeFunction(ea)

                    eanewfunction = idc.FindFuncEnd(ea)
                    if eanewfunction != idc.BADADDR:
                        ea = eanewfunction
                        continue

            nextcode = ida_search.find_code(ea, idc.SEARCH_DOWN)

            if nextcode != idc.BADADDR:
                ea = nextcode
            else:
                ea += 1
    def find_pushpop_registers_arm(self, makecode=False):
        '''
        Find opcodes for PUSH/POP registers in ARM mode
        Using the IDA API, convert these opcodes to code. This kicks off IDA analysis.
        
        bigup jmitch
        ** ** 2d e9 and ** ** bd e8
        '''

        EAstart = idc.MinEA()
        EAend = idc.MaxEA()

        ea = EAstart
        length = 2  # this code isn't tolerant to values other than 2 right now

        fmt_string = "Possible %s {REGS} 0x%08x == "
        for i in range(length):
            fmt_string += "%02x "

        while ea < EAend:
            instructions = []
            for i in range(length):
                instructions.append(idc.Byte(ea + i))

            # print BX LR bytes
            if not ida_bytes.isCode(ida_bytes.getFlags(ea)) and      \
            (instructions[0] == 0xbd and instructions[1] == 0xe8):
                if self.printflag:
                    print fmt_string % ("POP ", ea, instructions[0],
                                        instructions[1])
                if makecode:
                    idc.MakeCode(ea)

            if not ida_bytes.isCode(ida_bytes.getFlags(ea)) and      \
            (instructions[0] == 0x2d and instructions[1] == 0xe9)    \
            :
                if self.printflag:
                    print fmt_string % ("PUSH", ea, instructions[0],
                                        instructions[1])
                if makecode:
                    idc.MakeCode(ea)
            ea = ea + length
Exemplo n.º 21
0
def find_push_thumb(mark=False):
    def is_push(opcode):
        return (0xfffffe00 & opcode) == 0x0000b400

    image_start = idc.MinEA()
    image_end = idc.MaxEA()
    image_size = image_end - image_start

    print "Analyzing image from %.8x-%.8x of size %.8x" % (
        image_start, image_end, image_size)

    for cur_ea in xrange(image_start, image_end, 2):
        cur_word = Word(cur_ea)
        if is_push(cur_word) and "DCB" in GetDisasm(cur_ea):
            print "Found  candidate at 0x%.8x -> %s" % (cur_ea,
                                                        GetDisasm(cur_ea))
            if mark:
                MakeCode(cur_ea)
                print "Marked candidate at 0x%.8x -> %s" % (cur_ea,
                                                            GetDisasm(cur_ea))
Exemplo n.º 22
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
Exemplo n.º 23
0
def find_nops(mark=False):
    """
	Look for THUMB nops (0xbf00).
	"""
    def is_nop(opcode):
        return opcode == 0xbf00

    image_start = idc.MinEA()
    image_end = idc.MaxEA()
    image_size = image_end - image_start

    print "Analyzing image from %.8x-%.8x of size %.8x" % (
        image_start, image_end, image_size)

    for cur_ea in xrange(image_start, image_end, 2):
        cur_word = Word(cur_ea)
        if is_nop(cur_word):
            print "Found candidate at 0x%.8x -> %s" % (cur_ea,
                                                       GetDisasm(cur_ea))
            if mark:
                MakeCode(cur_ea)
Exemplo n.º 24
0
def find_prologs():
    push_masks = [(0x0fff0000, 0x092d0000), (0x0fff0fff, 0x052d0004)]

    def is_push(opcode):
        for mask in push_masks:
            if (mask[0] & opcode) == mask[1]:
                return True

        return False

    image_start = idc.MinEA()
    image_end = idc.MaxEA()
    image_size = image_end - image_start

    print "Analyzing image from %.8x-%.8x of size %.8x" % (
        image_start, image_end, image_size)

    for cur_ea in xrange(image_start, image_end, 4):
        cur_long = Dword(cur_ea)
        if is_push(cur_long):
            print "Found candidate at 0x%.8x -> %s" % (cur_ea,
                                                       GetDisasm(cur_ea))
Exemplo n.º 25
0
def find_pairs():
    ea = idc.MinEA()
    movh = [None] * MAX_REGISTERS
    while ea < idc.MaxEA():
        insn = idautils.DecodeInstruction(ea)
        if insn:
            mnem = insn.get_canon_mnem()
            reg1 = insn.Op1.reg
            reg2 = insn.Op2.reg
            val1 = insn.Op2.value
            val2 = insn.Op3.value
            size = insn.size

            if mnem == "movh" and insn.Op2.type == o_imm:
                movh[reg1] = (val1, insn.ea)
            elif movh[reg1] is not None:
                other = movh[reg1]
                if mnem == "add3" and reg1 == reg2:
                    target = (other[0] << 16) + val2
                    print "Found a add3 pointer pair to ", hex(target), " at ", hex(insn.ea)
                    idc.add_dref(insn.ea, target, dr_O)
                    idc.add_dref(other[1], target, dr_O)
                    idaapi.set_refinfo(insn.ea, 2, REF_LOW16, target, 0, 0)
                    idaapi.set_refinfo(other[1], 1, REF_HIGH16, target, 0, 0)
                elif mnem == "or3" and reg1 == reg2:
                    target = (other[0] << 16) | val2
                    print "Found a or3 pointer pair to ", hex(target), " at ", hex(insn.ea)
                    idc.add_dref(insn.ea, target, dr_O)
                    idc.add_dref(other[1], target, dr_O)
                    idaapi.set_refinfo(insn.ea, 2, REF_LOW16, target, 0, 0)
                    idaapi.set_refinfo(other[1], 1, REF_HIGH16, target, 0, 0)
                movh[reg1] = None

            if insn.get_canon_feature() & (idaapi.CF_STOP | idaapi.CF_CALL):
                movh = [None] * MAX_REGISTERS
        else:
            size = 2
        ea += size
    def find_pushpop_registers_thumb(self, makecode=False):
        '''
        Look for opcodes that push registers onto the stack, which are indicators of function prologues.
        Using the IDA API, convert these opcodes to code. This kicks off IDA analysis.
        '''
        '''
        thumb register list from [email protected]
        '''

        thumb_reg_list = [
            0x00, 0x02, 0x08, 0x0b, 0x0e, 0x10, 0x1c, 0x1f, 0x30, 0x30, 0x38,
            0x3e, 0x4e, 0x55, 0x70, 0x72, 0x73, 0x7c, 0x7f, 0x80, 0x90, 0xb0,
            0xf0, 0xf3, 0xf7, 0xf8, 0xfe, 0xff
        ]

        EAstart = idc.MinEA()
        EAend = idc.MaxEA()

        ea = EAstart
        length = 2  # this code isn't tolerant to values other than 2 right now

        fmt_string = "Possible Function 0x%08x == "
        for i in range(length):
            fmt_string += "%02x "

        while ea < EAend:
            instructions = []
            for i in range(length):
                instructions.append(idc.Byte(ea + i))

            if not ida_bytes.isCode(ida_bytes.getFlags(
                    ea)) and instructions[0] in thumb_reg_list and (
                        instructions[1] == 0xb5 or instructions[1] == 0xbd):
                if self.printflag:
                    print fmt_string % (ea, instructions[0], instructions[1])
                if makecode:
                    idc.MakeCode(ea)
            ea = ea + length
Exemplo n.º 27
0
def method_1():
    """
    This method does not work very well so far.
    """
    dictionary = enchant.Dict("en_US")

    # Get the image base of the database.
    image_start = idc.MinEA()
    image_end = idc.MaxEA()
    image_size = image_end - image_start

    print "Analyzing image from %.8x-%.8x of size %.8x" % (
        image_start, image_end, image_size)

    cur_string = ""
    for cur_ea in xrange(image_start, image_end):
        byte_ = chr(Byte(cur_ea))
        if not is_printable(byte_):
            # If this is a terminating byte, check if the collected bytes form a string.
            if byte_ == '\x00' and len(cur_string):
                cur_string = cur_string.replace("-", " ").replace("_", " ")
                words = cur_string.split()

                nwords = 0
                for word in words:
                    if len(word) > 2 and dictionary.check(word) and (
                            not word[0] in string.digits):
                        nwords += 1
                        if nwords > 1:
                            print "0x%.8x : %s" % (cur_ea, cur_string)
                            break

                cur_string = ""

        else:
            cur_string += byte_
Exemplo n.º 28
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)
Exemplo n.º 29
0
            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)


def make_offsets(segname):
    segea = idc.SegByBase(idc.SegByName(segname))
    segend = idc.SegEnd(segea)

    while segea < segend:
        idc.OpOffset(segea, 0)
        ptr = idc.Dword(segea)
        idc.OpOffset(ptr, 0)
        segea += 4


if __name__ == '__main__':
    make_offsets('__cls_refs')
    make_offsets('__message_refs')
    idaapi.analyze_area(idc.MinEA(), idc.MaxEA())
    fix_callgraph(idc.LocByName('_objc_msgSend'), 'msgSend', 4, 4)
    fix_callgraph(idc.LocByName('_objc_msgSendSuper'), 'msgSendSuper', 4, 4)
    idaapi.analyze_area(idc.MinEA(), idc.MaxEA())
    print 'Done.'
    def fix_names(self):
        """ 
            Fix the table of imports and map enums to apis.
        """
        start_addr  = idc.AskAddr(idc.here(), "Enter table start address")

        ## check if address is within the base address and maximum address
        if (start_addr < idc.MinEA()) or (start_addr > idc.MaxEA()):
            idc.Warning("You have entered an invalid start address")
            idc.Exit

        self.start_addr = start_addr    
        current_addr = self.start_addr

        #Current size of PoisonIvy IAT
        end_addr = current_addr + 568

        # Walk the table 8 bytes at a time
        while current_addr <= end_addr:

            idc.MakeQword(current_addr)
            print "DEBUG: Current address - 0x%08x" % current_addr
            addr = idc.Qword(current_addr)
            print "DEBUG: address - 0x%08x" % addr
            if addr == -1:
                print "[!] Skipping address 0x%08x - 0x%08x" % (current_addr, addr)
                current_addr += 8
                continue

            # Make the current address an offset
            idc.OpOff(current_addr,0,0)
            # We need to undefine the bytes incase IDA autoanalysis had converted an incorrect byte
            idc.MakeUnkn(addr, 1)
            # Create code at this address 
            idc.MakeCode(addr)
            # Create function at the same address
            idc.MakeFunction(addr, addr+16)
            # Read the second operand at the address which should be the negative API address value
            imp_addr = idc.GetOperandValue(addr, 1)

            if imp_addr == -1:
                print "[!] Couldn't get operand at address - 0x%08x" % addr
                current_addr +=8
                continue             

            # try:
            #     int_addr = int(imp_addr,16)
            # except ValueError as e:
            #     print "[!] Failed on: %s - %s\n" % (imp_addr, e)
            #     current_addr +=8 
            #     continue
            
            # if we know about this value then let's do the work
            if imp_addr in self.enums.keys():
                enum_id = self.enums[imp_addr]
                # Convert operand to enum 
                idc.OpEnumEx(addr, 1, enum_id,0)
                const_id = idc.GetConstEx(enum_id, imp_addr, 0, -1)
                fn_name = "fn_"+idc.GetConstName(const_id)
                off_name = "ptr_"+idc.GetConstName(const_id)
                # Rename the function to the symbol name.
                # We append fn_ to the symbol for the function name
                # and ptr_ to the offset in the table.
                if not idc.MakeNameEx(addr, fn_name, idaapi.SN_NOWARN):
                    print "[!] Failed to rename function %s at 0x%08x\n" % (fn_name, addr)
                if not idc.MakeNameEx(current_addr, off_name, idaapi.SN_NOWARN):
                    print "[!] Failed to rename offset %s at 0x%08x\n" % (off_name,current_addr)

            current_addr += 8

        return