예제 #1
0
	def resolve_functions(self):

		self.addr = {
			"verifyNative": idc.get_name_ea_simple("BaseExecMgr::verifyNative"), 
			"setJit": idc.get_name_ea_simple("BaseExecMgr::setJit"), 
			"setInterp": idc.get_name_ea_simple("BaseExecMgr::setInterp"), 
			"setInterpRet": prev_head(
				idc.find_func_end(idc.get_name_ea_simple("BaseExecMgr::setInterp")), 
				idc.get_name_ea_simple("BaseExecMgr::setInterp")), 
			"getMethodName": idc.get_name_ea_simple("MethodInfo::getMethodName"), 
			"verifyJit": idc.get_name_ea_simple("BaseExecMgr::verifyJit"), 
			"writePrologue": idc.get_name_ea_simple("CodegenLIR::writePrologue"),
			"hasReachableExceptionsRet": prev_head(
				idc.find_func_end(idc.get_name_ea_simple("Verifier::hasReachableExceptions")), 
				idc.get_name_ea_simple("Verifier::hasReachableExceptions"))
		}
    def get_strings_per_function(self, start_func):
        strings = []
        fs = ''
        func_obj = idaapi.get_func(start_func)
        if func_obj:
            self.clear_comments(start_func, func_obj)
            for inst_list in idautils.Heads(start_func,
                                            idc.find_func_end(start_func)):
                try:
                    for string in [
                            self.get_string_type(xref_addr)
                            for xref_addr in idautils.DataRefsFrom(inst_list)
                    ]:
                        if len(string) > 2:
                            strings.append(string[2:-1])
                            self.string_counter += 1
                        else:
                            pass
                except StringException:
                    continue

            if strings:
                for c in strings:
                    if '\n' in c:
                        c = c.replace('\n', '')
                    fs += '"' + c + '" '
                idaapi.set_func_cmt(func_obj,
                                    'STR {}# {}'.format(len(strings), fs), 1)

        else:
            print("func_obj return 0")
            pass
예제 #3
0
 def items(self, start=0, stop=None):
     if stop is None:
         stop = find_func_end(self.__start)
     for item_ea in dropwhile(lambda x: x < start, FuncItems(self.__start)):
         if item_ea >= stop:
             break
         yield Instruction(item_ea)
예제 #4
0
def get_basic_block(ea):
    func = idaapi.get_func(ea)
    flow = idaapi.FlowChart(func)
    for bb in flow:
        if bb.startEA <= ea < bb.endEA:
            return bb.startEA, bb.endEA
    return get_func_start(ea), idc.find_func_end(ea)
예제 #5
0
def jump_addr_next_func():
    import idc
    end = 0x0402220
    ea = idc.get_screen_ea()
    while idc.find_func_end(ea) < end:
        next_func = get_next_func(ea)
        print(hex(next_func))
        idc.jumpto(next_func)
        ea = idc.get_screen_ea()
예제 #6
0
def process_mod_init_func_for_metaclasses(func, found_metaclass):
    class FindMetaclassEmulator(Arm64Emulator):
        def BL(self, bl_addr):
            # OSMetaClass::OSMetaClass(this, className, superclass, classSize)
            X0, X1, X3 = (self.regs[n] for n in ('X0', 'X1', 'X3'))
            if (X0 and X1 and X3
                    and idc.get_segm_name(X1).endswith("__cstring")
                    and idc.get_segm_name(X0)):
                found_metaclass(X0, idc.get_strlit_contents(X1))

    FindMetaclassEmulator().run(func, idc.find_func_end(func))
예제 #7
0
    def eliminate_deadcode(self, ea):
        instruction_list = []
        address_list = list(idautils.FuncItems(ea))
        lines = ''
        for i, row_begin_addr in enumerate(address_list):
            disasm = idc.GetDisasm(row_begin_addr)
            lines += disasm + '\n'
            try:
                next_row_begin_addr = address_list[i + 1]
                size = next_row_begin_addr - row_begin_addr
                if size < 0:  # when row_begin_addr is end basic block
                    row_end_addr = idc.find_func_end(row_begin_addr)
                    size = row_end_addr - row_begin_addr

            except IndexError:  # when next_row_begin_addr is not found
                last_row_begin_addr = row_begin_addr
                last_row_end_addr = idc.find_func_end(last_row_begin_addr)
                size = last_row_end_addr - last_row_begin_addr

            row_opcode = b''
            for i in range(size):
                int_opcode = ida_bytes.get_original_byte(row_begin_addr + i)
                opcode = struct.pack('B', int_opcode)
                row_opcode += opcode

            instruction_list.append([row_begin_addr, row_opcode, disasm])

        checked_instruction_list = eliminate.check_deadcode(instruction_list)
        lines = ''
        for i in checked_instruction_list:
            address = i[0]
            opcode = i[1]
            disasm = i[2]
            if not opcode.startswith(b'\x90'):  # check dead code
                lines += str(format(address,
                                    'x')).upper() + ':    ' + disasm + '\n'

        self.ClearLines()
        self.colorize(lines)

        return True
예제 #8
0
def find_function_code_references(func_ea):
    end_ea = idc.find_func_end(func_ea)
    if end_ea == idaapi.BADADDR:
        return []

    results = []
    for line in idautils.Heads(func_ea, end_ea):
        refs = list(idautils.CodeRefsFrom(line, 1))
        if len(refs) > 1:
            results.append(refs[1])

    return results
예제 #9
0
	def get_func_end(self, start):

		if (idc.add_func(start)):
			return idc.find_func_end(start)

		ea = start
		while (idc.get_wide_byte(ea) != 0xCC):
			idc.create_insn(ea)
			ea += idc.get_item_size(ea)

			if (ea - start > self.jit_max_size):
				return 0

		return ea
예제 #10
0
def find_com_references():
    """
    This function will try to find data references that match GUIDs
    and return a list of COMModule object with function name
    :return: list of tuble (function_name, COMMOdule)
    :rtype: tuple(str, COMModule)
    """
    result = []
    for seg in idautils.Segments():
        for funcea in idautils.Functions(seg, idc.get_segm_end(seg)):
            result += [(idaapi.ida_funcs.get_func_name(funcea), x)
                       for x in find_guid_in_address_space(
                           funcea, idc.find_func_end(funcea))]

    return result
예제 #11
0
def find_function_strings(func_ea):
    end_ea = idc.find_func_end(func_ea)
    if end_ea == idaapi.BADADDR:
        return []

    strings = []
    for line in idautils.Heads(func_ea, end_ea):
        refs = idautils.DataRefsFrom(line)
        for ref in refs:
            try:
                strings.append(String(line, ref))
            except StringParsingException:
                continue

    return strings
예제 #12
0
def find_func_containing(ea):
    for segment_ea in idautils.Segments():
        if segment_ea > ea:
            continue
        segment_end = idc.get_segm_end(segment_ea)
        if segment_end < ea:
            continue
            
        for func_ea in idautils.Functions(segment_ea, segment_end):
            if func_ea > ea:
                continue
            func_end = idc.find_func_end(func_ea)
            if func_end <= ea:
                continue
            return func_ea
    return None
예제 #13
0
def _process_mod_init_func_for_metaclasses(func, found_metaclass):
    """Process a function from the __mod_init_func section for OSMetaClass information."""
    _log(4, 'Processing function {}', idc.get_func_name(func))

    def on_BL(addr, reg):
        X0, X1, X3 = reg['X0'], reg['X1'], reg['X3']
        if not (X0 and X1 and X3):
            return
        _log(5, 'Have call to {:#x}({:#x}, {:#x}, ?, {:#x})', addr, X0, X1, X3)
        # OSMetaClass::OSMetaClass(this, className, superclass, classSize)
        if not idc.get_segm_name(X1).endswith(
                "__TEXT.__cstring") or not idc.get_segm_name(X0):
            return
        found_metaclass(X0, ida_bytes.get_strlit_contents(X1), X3, reg['X2']
                        or None)

    _emulate_arm64(func, idc.find_func_end(func), on_BL=on_BL)
예제 #14
0
def find_framescript_register(game_init):
    game_init_end = idc.find_func_end(game_init)
    magic_string_found = False
    for head in idautils.Heads(game_init, game_init_end):
        disasm = idc.generate_disasm_line(head, 2)
        if not magic_string_found and '"FrameXML_Debug"' in disasm:
            magic_string_found = True
            continue
            
        if magic_string_found and disasm.startswith('call '):
            result = int(idc.get_operand_value(head, 0))
            func_name = idc.get_func_name(result)
            mangled_name = '__Z28FrameScript_RegisterFunctionPKcPFiP9lua_StateE'
            
            if func_name != mangled_name:
                idc.set_name(result, mangled_name, SN_CHECK)

            print('FrameScript::Register: 0x%08x' % result)
            return result
            
    raise RuntimeError('Unable to find FrameScript::Register (%d)' % \
        2 if magic_string_found else 1)
예제 #15
0
    def DoDescentParser(self, Prologue):
        '''
            @brief Walk the function leveraging a recursive descent parser. 

            @detail Starting with a prologue walk each instruction until the associated epilogue is reached. For functions 
                    with multiple epilogues, iterate over each one. 

                    As each instruction is traversed, do the following three
                    things:

                        - Undefine the instruction
                        - Mark the instruction as code
                        - Check to see if the instruction is already a member of another function
                    
                    If an instruction is a member of another function, undefine that function and place it in a queue. At the end
                     of traversing each function, a new function is going to be created with the new prologue and the new epilogue.
                     In addition, the undefined function queue is going to be iterated over and each function will be redefined. This
                     should clean up messy function
                    
                    much thanks to the author of "Practical Malware Analysis" for the break down of the algorithm in Chapter 8.
        '''

        #
        #   jmps = [eval("idaapi."+name) for name in dir(idaapi) if "NN_j" in name]
        #
        jcc_terminators = [
            'jnz', 'jz', 'jo', 'jno', 'js', 'jns', 'je', 'jne', 'jb', 'jnae',
            'jc', 'jnb', 'jae', 'jnc', 'jbe', 'jna', 'ja', 'jnbe', 'jl',
            'jnge', 'jge', 'jnl', 'jle', 'jng', 'jg', 'jnle', 'jp', 'jpe',
            'jnp', 'jpo', 'jcxz', 'jecxz'
        ]

        #print EndAddresses

        while len(self.deferred_targets) > 0:

            curr_insn_ea = self.deferred_targets.pop()

            if curr_insn_ea in self.instructions_walked:
                #
                #   skip instructions that were already walked
                #
                continue

            #for target in self.deferred_targets:
            #    print "deferred target: %08x" % target

            while curr_insn_ea not in Prologue.possible_epilogues:
                #
                # walk only to a known epilogue
                #

                #print "Current EA: %08x" % (curr_insn_ea)

                self.instructions_walked.append(curr_insn_ea)

                #
                #   Verify current instruction information
                #
                curr_insn = ida_ua.insn_t()
                decode_result = ida_ua.decode_insn(curr_insn, curr_insn_ea)
                if decode_result < 1:
                    #
                    #   break if instruction invalid
                    #
                    break

                represented_insn_dism = idc.generate_disasm_line(
                    curr_insn_ea, 0)
                curr_insn_dism = idc.generate_disasm_line(curr_insn_ea, 1)
                if curr_insn_dism != represented_insn_dism:
                    #
                    #   If the item shown at this address in IDA does not match
                    #     what should be shown (due to obfuscation), fix it
                    #

                    #print "Instructions don't match: %08x" % (curr_insn_ea)
                    idc.del_items(curr_insn_ea, 1)
                    #idc.plan_and_wait(curr_insn_ea, curr_insn_ea+curr_insn.size)
                    idc.create_insn(curr_insn_ea)
                    #idc.plan_and_wait(curr_insn_ea, curr_insn_ea+curr_insn.size)

                curr_func_name = idc.get_func_name(curr_insn_ea)
                if curr_func_name:
                    #
                    #   check if in function, undefine function, add to list to redefine later
                    #

                    #print "Part of another function: %08x" % (curr_insn_ea)
                    curr_func_ea = idc.get_name_ea_simple(curr_func_name)
                    func_end_ea = idc.find_func_end(curr_func_ea)
                    idc.del_func(curr_func_ea)

                    for curr_function in self.wrong_functions:
                        if curr_function not in curr_function:
                            self.wrong_functions.append(
                                [curr_func_ea, func_end_ea])

                if curr_insn_dism.startswith(tuple(jcc_terminators)):
                    #
                    #   JCC conditionals, recursion control case
                    #

                    #print "Adding jcc target: %08x" % (curr_insn_ea)
                    jmp_target_ea = self.GetInstuctionTargetAddress(curr_insn)
                    if jmp_target_ea not in self.deferred_targets:
                        self.deferred_targets.append(jmp_target_ea)

                    curr_insn_ea = curr_insn_ea + curr_insn.size

                elif curr_insn_dism.startswith("jmp"):
                    jmp_target_ea = self.GetInstuctionTargetAddress(curr_insn)

                    #print "Adding jump target: %08x" % (curr_insn_ea)
                    if jmp_target_ea not in self.deferred_targets:
                        self.deferred_targets.append(jmp_target_ea)
                    break

                elif curr_insn_dism.startswith("retn"):
                    break

                else:
                    curr_insn_ea = curr_insn_ea + curr_insn.size

            if curr_insn_ea in Prologue.possible_epilogues:
                Prologue.connected_epilogues.append(curr_insn_ea)
                continue