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
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)
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)
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()
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))
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
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
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
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
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
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
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)
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)
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