def main(): ea = idaapi.get_screen_ea() # export entry = tuple(index, ordinal, address, name) exports = {export[2]: export for export in idautils.Entries()} # list of tuple(xref_address, export_name, xref_offset) exported_xrefs = [] xrefs = [x.frm for x in idautils.XrefsTo(ea)] for xref in xrefs: func = idaapi.get_func(xref) if func and func.startEA in exports: exported_xrefs.append( (xref, exports[func.startEA][3], xref - func.startEA)) if exported_xrefs: delim = "=" * 80 print delim print "Dumping exported xrefs for: %s %s" % (idaapi.get_name( ea, ea), idahex(ea)) print delim for exported_xref in exported_xrefs: print "%s %s + 0x%X" % (idahex( exported_xref[0]), exported_xref[1], exported_xref[2]) else: print "%s %shas no exported xrefs." % (idahex(ea), idaapi.get_name(ea, ea) or "")
def _replace_with_check_helper(self, ctx, l): # type: (...) -> None type_name_ea = ctx.type_info_obj.obj_ea name = idaapi.demangle_name(idaapi.get_name(type_name_ea), 0) if not name: name = idaapi.get_name(type_name_ea) type_name = name var_type = None if "::getRuntimeTypeInfoStatic(void)::typeInfo" in name: type_name = name.split("::getRuntimeTypeInfoStatic(void)::typeInfo")[0] var_type = idaapi.tinfo_t() idaapi.parse_decl2(idaapi.cvar.idati, type_name + "*;", var_type, idaapi.PT_TYP) if not str(var_type): var_type = None call_expr = make_helper_call("void*", "dynamic_cast<" + type_name + ">", ["void*"]) call_expr.a.push_back(make_carg_t(ctx.original_var)) asg_expr = hr.cexpr_t() asg_expr.op = hr.cot_asg asg_expr.x = hr.cexpr_t() asg_expr.x.assign(ctx.dynamic_cast_var) asg_expr.y = call_expr asg_expr.type = var_type if var_type else idaapi.tinfo_t(idaapi.BT_VOID) if var_type: self._types_to_set.append((ctx.dynamic_cast_var.v.idx, var_type)) replace_expr_with(l[0].cexpr, asg_expr) for item in l[1:]: item.cleanup()
def check(addr): # 1 - name is defined here == has xref(s) # 2 - at least MIN_FUNCTIONS_REQUIRED valid function pointers MIN_FUNCTIONS_REQUIRED = 3 # 1 if len(idaapi.get_name(addr)) == 0: return False # 2 functions_counted = 0 while True: if not FunctionPointer.check( util.get_ptr(addr + functions_counted * const.PTR_SIZE)): break functions_counted += 1 if len(idaapi.get_name(addr + functions_counted * const.PTR_SIZE)) != 0: break if functions_counted < MIN_FUNCTIONS_REQUIRED: return False return functions_counted
def rename(self, new_name): ''' Description: Attempts to apply new_name to the object at <ea>. If more than one object starts at <ea>, the largest object will be renamed. If that name already exists, let IDA resolve the collission and then return that name. If new_name is "", reset the name to IDA's default. Input: new_name - The desired new name for the function. Output: The name that ended up getting set (unless no name was set, then return None). ''' if new_name == '': if idaapi.set_name(self.function_obj.startEA, new_name): return idaapi.get_name(self.function_obj.startEA, self.function_obj.startEA) else: append_debug('Failed to reset name at 0x%X' % self.function_obj.startEA) elif idaapi.do_name_anyway(self.function_obj.startEA, new_name): self.name = idaapi.get_name(self.function_obj.startEA, self.function_obj.startEA) if self.name != new_name: append_debug('IDA changed name "%s" to "%s"' % (new_name, self.name)) return self.name else: append_debug('Failed to rename at 0x%X' % self.function_obj.startEA)
def parse_vtable_name(address): name = idaapi.get_name(address) if idaapi.is_valid_typename(name): if name[0:3] == 'off': # off_XXXXXXXX case return "Vtable" + name[3:], False elif "table" in name: return name, True print "[Warning] Weird virtual table name -", name return "Vtable_" + name, False name = idc.demangle_name(idaapi.get_name(address), idc.INF_SHORT_DN) assert name, "Virtual table must have either legal c-type name or mangled name" return common.demangled_name_to_c_str(name), True
def main(): key_str_ea = find_key_str("basic_string::_M_construct null not valid") key_func_ea = find_key_func("._ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE9_M_createERmm") all_possible_funcs = collect_all_possible_funcs(key_str_ea, key_func_ea) print("all possible funcs") for func in all_possible_funcs: print(idaapi.get_name(func.start_ea)) print("all funcs") all_funcs = filter_func(all_possible_funcs, 4, False) for func in all_funcs: print(idaapi.get_name(func.start_ea)) process_funcs(all_funcs)
def update_rule_status(self, rule_text): """ """ if self.view_rulegen_editor.root is None: self.set_rulegen_preview_border_neutral() self.view_rulegen_status_label.clear() return self.set_rulegen_preview_border_error() try: rule = capa.rules.Rule.from_yaml(rule_text) except Exception as e: self.set_rulegen_status("Failed to compile rule! %s" % e) return # create deep copy of current rules, add our new rule rules = copy.copy(self.rules_cache) rules.append(rule) try: func_matches, bb_matches = find_func_matches( self.rulegen_current_function, capa.rules.RuleSet( list( capa.rules.get_rules_and_dependencies( rules, rule.name))), self.rulegen_func_features_cache, self.rulegen_bb_features_cache, ) except Exception as e: self.set_rulegen_status("Failed to match rule! %s" % e) return if tuple( filter( lambda m: m[0] == rule.name, itertools.chain(func_matches.items(), bb_matches.items()))): # made it here, rule compiled and match was found self.set_rulegen_preview_border_success() self.set_rulegen_status( "Rule compiled, match found for %s" % idaapi.get_name(self.rulegen_current_function.start_ea)) else: # made it here, rule compiled but no match found, may be intended so we warn user self.set_rulegen_preview_border_warn() self.set_rulegen_status( "Rule compiled, but no match found for %s" % idaapi.get_name(self.rulegen_current_function.start_ea))
def parse_vtable_name(address): name = idaapi.get_name(address) if idaapi.is_valid_typename(name): if name[0:3] == 'off': # off_XXXXXXXX case return "Vtable" + name[3:], False elif "table" in name: return name, True print("[Warning] Weird virtual table name -", name) return "Vtable_" + name, False name = idc.demangle_name(idaapi.get_name(address), idc.get_inf_attr(idc.INF_SHORT_DN)) assert name, "Virtual table must have either legal c-type name or mangled name" return demangled_name_to_c_str(name).replace("const_", "").replace( "::_vftable", "_vtbl"), True
def dump_address_names(): selected = get_selected_bytes() if selected: with open("out.txt", "w") as fi: for ea in range(selected[1], selected[2], 4): if not cool_to_clobber(ea): print "[-] Error: Something that we shouldn't clobber at 0x%x" % ea break print "[+] Processed %x,%s,%x" % (ea, idaapi.get_name(ea), idaapi.get_dword(ea)) fi.write("%x,%s,%x\n" % (ea, idaapi.get_name(ea), idaapi.get_dword(ea))) else: print "[-] Error: EA is not currently a selection endpoint %x" % idc.ScreenEA( )
def extract_insn_api_features(f, bb, insn): """parse instruction API features args: f (IDA func_t) bb (IDA BasicBlock) insn (IDA insn_t) example: call dword [0x00473038] """ if not insn.get_canon_mnem() in ("call", "jmp"): return for api in check_for_api_call(f.ctx, insn): dll, _, symbol = api.rpartition(".") for name in capa.features.extractors.helpers.generate_symbols(dll, symbol): yield API(name), insn.ea # extract IDA/FLIRT recognized API functions targets = tuple(idautils.CodeRefsFrom(insn.ea, False)) if not targets: return target = targets[0] target_func = idaapi.get_func(target) if not target_func or target_func.start_ea != target: # not a function (start) return if target_func.flags & idaapi.FUNC_LIB: name = idaapi.get_name(target_func.start_ea) yield API(name), insn.ea
def _get_member(self, offset, cexpr, obj, tinfo=None, obj_ea=None): cexpr_ea = helper.find_asm_address(cexpr, self.parents) if offset < 0: logger.error("Considered to be impossible: offset - {}, obj - {}".format( offset, helper.to_hex(cexpr_ea))) raise AssertionError applicable = not self.crippled scan_obj = ScannedObject.create(obj, cexpr_ea, self.__origin, applicable) if obj_ea: if temporary_structure.VirtualTable.check_address(obj_ea): vtable_name = idaapi.get_name(obj_ea) if vtable_name.endswith("::vt"): member = temporary_structure.Member(offset, tinfo, scan_obj, self.__origin) member.set_override_other_members(True) if member.parse_type_declaration(vtable_name.replace("::vt", "")): return member mapping = { '_ZTVN3agl3utl9ParameterIbEE': 'agl::utl::Parameter$bool$', '_ZTVN3agl3utl9ParameterIfEE': 'agl::utl::Parameter$float$', '_ZTVN3agl3utl9ParameterIiEE': 'agl::utl::Parameter$int$', '_ZTVN3agl3utl9ParameterIjEE': 'agl::utl::Parameter$uint$', '_ZTVN3agl3utl9ParameterIN4sead7Vector2IfEEEE': 'agl::utl::Parameter_Vec2', '_ZTVN3agl3utl9ParameterIN4sead7Vector3IfEEEE': 'agl::utl::Parameter$sead::Vector3f$', '_ZTVN3agl3utl9ParameterIN4sead7Vector4IfEEEE': 'agl::utl::Parameter_Vec4', '_ZTVN3agl3utl9ParameterIN4sead7Color4fEEE': 'agl::utl::Parameter$sead::Color4f$', '_ZTVN3agl3utl9ParameterIN4sead15FixedSafeStringILi32EEEEE': 'agl::utl::Parameter$sead::FixedSafeString20$', '_ZTVN3agl3utl9ParameterIN4sead15FixedSafeStringILi64EEEEE': 'agl::utl::Parameter$sead::FixedSafeString40$', '_ZTVN3agl3utl9ParameterIN4sead15FixedSafeStringILi256EEEEE': 'agl::utl::Parameter$sead::FixedSafeString100$', '_ZTVN3agl3utl9ParameterIN4sead14SafeStringBaseIcEEEE': 'agl::utl::Parameter$sead::SafeString$', } for x in mapping: if vtable_name.startswith(x): member = temporary_structure.Member(offset, tinfo, scan_obj, self.__origin) member.set_override_other_members(True) if member.parse_type_declaration(mapping[x]): return member return temporary_structure.VirtualTable(offset, obj_ea, scan_obj, self.__origin) if helper.is_code_ea(obj_ea): cfunc = helper.decompile_function(obj_ea) if cfunc: tinfo = cfunc.type tinfo.create_ptr(tinfo) else: tinfo = const.DUMMY_FUNC return temporary_structure.Member(offset, tinfo, scan_obj, self.__origin) # logger.warn("Want to see this ea - {},".format(Helper.to_hex(cexpr_ea))) if not tinfo or tinfo.equals_to(const.VOID_TINFO) or tinfo.equals_to(const.CONST_VOID_TINFO): return temporary_structure.VoidMember(offset, scan_obj, self.__origin) if tinfo.equals_to(const.CONST_PCHAR_TINFO): tinfo = const.PCHAR_TINFO elif tinfo.equals_to(const.CONST_PVOID_TINFO): tinfo = const.PVOID_TINFO else: tinfo.clr_const() return temporary_structure.Member(offset, tinfo, scan_obj, self.__origin)
def check_address(address): # Checks if given address contains virtual table. Returns True if more than 2 function pointers found # Also if table's addresses point to code in executable section, than tries to make functions at that addresses if helper.is_code_ea(address): return False if not idaapi.get_name(address): return False functions_count = 0 while True: func_address = helper.get_ptr(address) # print "[INFO] Address 0x{0:08X}".format(func_address) if helper.is_code_ea(func_address) or helper.is_imported_ea( func_address): functions_count += 1 address += const.EA_SIZE else: segment = idaapi.getseg(func_address) if segment and segment.perm & idaapi.SEGPERM_EXEC: idc.del_items(func_address, 1, idaapi.DELIT_SIMPLE) if idc.add_func(func_address): functions_count += 1 address += const.EA_SIZE continue break idaapi.auto_wait() return functions_count
def find_interesting_xors(self): next_xor = idc.FindText(idc.MinEA(), idc.SEARCH_DOWN | idc.SEARCH_NEXT, 0, 0, "xor") while next_xor != idc.BADADDR: if idc.GetOpnd(next_xor, 0) != idc.GetOpnd(next_xor, 1): entry = { "func": "", "addr": next_xor, "loop": False, "disasm": idc.GetDisasm(next_xor) } func = idaapi.get_func(next_xor) if func: entry["func"] = idaapi.get_name(idc.BADADDR, func.startEA) heads = idautils.Heads(next_xor, func.endEA) lxors = [] for head in heads: if idc.GetMnem(head).startswith('j'): jmp_addr = idc.GetOperandValue(head, 0) if jmp_addr < next_xor and jmp_addr > func.startEA: entry["loop"] = True break self._interesting_xors.append(entry) next_xor = idc.FindText(idc.NextHead(next_xor), idc.SEARCH_DOWN | idc.SEARCH_NEXT, 0, 0, "xor")
def main() -> None: all_vtables = ai_common.get_vtables() names = ai_common.get_action_vtable_names() not_decompiled = {func.addr for func in utils.get_functions() if func.status == utils.FunctionStatus.NotDecompiled} new_names: Dict[int, str] = dict() order = ai_common.topologically_sort_vtables(all_vtables, "Action") for vtable_addr in order: if vtable_addr in BaseClasses: continue class_name = names.get(vtable_addr) for i, fn_ea in enumerate(iterate_vtable(vtable_addr)): if idaapi.get_name(fn_ea) == "__cxa_pure_virtual": continue real_fn_ea = fn_ea & ~_ida_base if real_fn_ea not in new_names: if i < len(_vtable_fn_names): new_names[real_fn_ea] = format_fn_name(_vtable_fn_names[i], class_name) else: # Unknown member function. new_names[real_fn_ea] = f"uking::action::{class_name}::m{i}" if real_fn_ea in not_decompiled: idaapi.set_name(fn_ea, new_names[real_fn_ea]) utils.add_decompiled_functions(dict(), new_names)
def __init__(self, *args): """ Creates a module with the name moduleName. This could be exported from the database, or it could be a new module to include in the database! :param *args: fromName(moduleName:str) :moduleName: name of the module, '<moduleName>_' will be used to identify names within it. Because of this, the name is NOT allowed to have a '_' in it. fromEA(nameEA:int) Extracts the name of the module from the item specified by moduleEA. the name is the item name up until the first '_'. :moduleEA: an EA of a Name within the module :raise ModuleException: if more than one arg is passed or name contains '_' in it! if a moduleEA has no name associated with it, or if the name associated with moduleEA has no '_' in it! """ if len(args) > 1: raise (ModuleException("incompatible *args passed")) if type(args[0]) == str: self.name = args[0] if '_' in self.name: raise (ModuleException( "passed Module name must not contain '_' in it")) elif type(args[0]) == int: self.name = idaapi.get_name(args[0]) if '_' not in self.name: raise (ModuleException( "Invalid nameEA passed, or not part of any module")) self.name = self.name[0:self.name.index('_')] else: raise (ModuleException("incompatible *args passed")) self.files = self.getModuleFiles()
def global_var(addr): name = idaapi.get_name(addr) if not name: return None size = idaapi.get_item_size(addr) return GlobalVariable(addr, name, size=size, last_change=int(time()))
def name(fn, name=None): fn = by(fn) if name is None: res = idaapi.get_func_name(fn.startEA) if not res: res = idaapi.get_name(-1, fn.startEA) if not res: res = idaapi.get_true_name(fn.startEA, fn.startEA) return res return idaapi.set_name(fn.startEA, name, idaapi.SN_PUBLIC)
def name(key=None, name=None): '''Returns the name of the function or import identified by key.''' rt,ea = __addressOfRtOrSt(ui.current.address() if key is None else key) if rt: if name is None: res = idaapi.get_name(-1, ea) return internal.declaration.extract.fullname(internal.declaration.demangle(res)) if res.startswith('?') else res # FIXME: shuffle the new name into the prototype and then re-mangle it return database.name(ea, name) if name is None: res = idaapi.get_func_name(ea) if not res: res = idaapi.get_name(-1, ea) if not res: res = idaapi.get_true_name(ea, ea) return internal.declaration.extract.fullname(internal.declaration.demangle(res)) if res.startswith('?') else res #return internal.declaration.extract.name(internal.declaration.demangle(res)) if res.startswith('?') else res return idaapi.set_name(ea, name, idaapi.SN_PUBLIC)
def iterate_vtable(vtable_addr): ea = vtable_addr while True: fn_ea = struct.unpack('<Q', idaapi.get_bytes(ea, 8))[0] if idaapi.get_name(fn_ea) != "__cxa_pure_virtual" and not idaapi.is_func(idaapi.get_flags(fn_ea)): return yield fn_ea ea += 8
def GetName(self,Address): if type(Address).__name__ == 'int': Name = idaapi.get_name(Address,Address) if Name: return Name return hex( Address ) return str( Address )
def extract_file_function_names(): """ extract the names of statically-linked library functions. """ for ea in idautils.Functions(): if idaapi.get_func(ea).flags & idaapi.FUNC_LIB: name = idaapi.get_name(ea) yield FunctionName(name), ea
def tag_read(ea, key=None, repeatable=0): res = idaapi.get_cmt(ea, int(bool(repeatable))) dict = internal.comment.toDict(res) name = idaapi.get_name(-1,ea) if name is not None: dict.setdefault('name', name) if key is None: return dict return dict[key]
def GetName(self, Address): if type(Address).__name__ == 'int': Name = idaapi.get_name(Address, Address) if Name: return Name return hex(Address) return str(Address)
def tag_read(ea, key=None, repeatable=0): res = idaapi.get_cmt(ea, int(bool(repeatable))) dict = _comment.toDict(res) name = idaapi.get_name(-1, ea) if name is not None: dict.setdefault('name', name) if key is None: return dict return dict[key]
def isDefined(ea): flags = idaapi.getFlags(ea) if not idc.isStruct(flags): return False if not idc.isHead(flags): return False if idaapi.get_name(idaapi.BADADDR, ea) != TypeDescriptor.makeName(ea): return False return True
def __init__(self, parent, location, can_check=True): """initialize item @param parent: parent node @param location: virtual address of function as seen by IDA """ super(CapaExplorerFunctionItem, self).__init__( parent, [self.fmt % idaapi.get_name(location), location_to_hex(location), ""], can_check )
def get_jlocs(self, sw): jlocs = [] ncases = sw.ncases if sw.jcases == 0 else sw.jcases for i in range(ncases): addr = idc.Dword(sw.jumps+i*4) name = idaapi.get_name(idc.BADADDR, addr) comm = idc.GetCommentEx(idc.LocByName(name), 1) comm = comm[comm.find('case'):] if comm is not None and comm.startswith('jumptable') else comm jlocs.append((name, idc.LocByName(name), comm)) return jlocs
def dump_address_names(): selected = get_selected_bytes() if selected: for ea in range(selected[1], selected[2], 4): if not cool_to_clobber(ea): print "[-] Error: Something that we shouldn't clobber at 0x%x" % ea break print "[+] Processed %x,%s" % (ea, idaapi.get_name(ea)) else: print "[-] Error: EA is not currently a selection endpoint %x" % idc.ScreenEA( )
def name(self): name = idaapi.get_name(self.addr) demangled_name = idc.demangle_name(name, idc.get_inf_attr(idc.INF_SHORT_DN)) if demangled_name: name = demangled_name_to_c_str(demangled_name) if len(name) == 0: name = 'func_%X' % (self.addr) return name
def get_OSMetaClass_ctor_args(ea): # args = idaapi.get_arg_addrs(ea) # Lazy solution - just let unicorn emulate it up to the BL # First we gotta figure out the start of this function fxnstart = ida_funcs.get_func(ea).start_ea # Then we emulate it up to the function call params = emulate(fxnstart, ea) # for i in range(len(params)): # print("x{}: {}".format(i+1, hex(params[i]))) classname = read_cstring(params[0]) superclass = params[1] superclass_name = None if superclass != 0: superclass_name = idc.demangle_name(idaapi.get_name(params[1]), get_inf_attr(idc.INF_LONG_DN)) # In case the superclass pointer references a pointer that is # meant to be resolved later if superclass_name == None: superclass_name = idaapi.get_name(ida_bytes.get_qword(params[1])) superclass_name = idc.demangle_name(superclass_name, get_inf_attr(idc.INF_LONG_DN)) superclass_name = superclass_name[0:superclass_name.find("::")] args = [superclass_name, classname.decode(), params[2]] # if superclass_name == "AUAUnitDictionary": # for i in range(len(params)): # print("x{}: {}".format(i+1, hex(params[i]))) # print(args) # return return args
def getName(ea): '''fetches the function name, or the global name''' res = idaapi.get_func_name(ea) if res is None: res = idaapi.get_name(-1, ea) if res is None: res = idaapi.get_true_name(ea, ea) # if name is mangled... and version <= 6.4 if res and res.startswith('@'): return '$' + res return res
def getName(ea): '''fetches the function name, or the global name''' res = idaapi.get_func_name(ea) if res is None: res = idaapi.get_name(-1, ea) if res is None: res = idaapi.get_true_name(ea, ea) # if name is mangled... and version <= 6.4 if res and res.startswith('@'): return '$'+res return res
def rename(self, new_name): """ Attempts to apply new_name to the object at <ea>. If more than one object starts at <ea>, the largest object will be renamed. If that name already exists, let IDA resolve the collision and then return that name. If new_name is "", reset the name to IDA's default. :param str new_name: The desired new name for the function. :return str: The name that ended up getting set (unless no name was set, then return None). """ if new_name == '': if idaapi.set_name(self.start_ea, new_name): return idaapi.get_name(self.function_obj.start_ea) else: logger.warning('Failed to reset name at 0x%X' % self.start_ea) elif ida_name.force_name(self.start_ea, new_name): self.name = idaapi.get_name(self.start_ea) if self.name != new_name: logger.info('IDA changed name "%s" to "%s"' % (new_name, self.name)) return self.name else: logger.warning('Failed to rename at 0x%X' % self.start_ea)
def find_interesting_xors(self): next_xor = idc.FindText(idc.MinEA(), idc.SEARCH_DOWN|idc.SEARCH_NEXT, 0, 0, "xor") while next_xor != idc.BADADDR: if idc.GetOpnd(next_xor, 0) != idc.GetOpnd(next_xor, 1): entry = {"func":"", "addr": next_xor, "loop":False, "disasm": idc.GetDisasm(next_xor)} func = idaapi.get_func(next_xor) if func: entry["func"] = idaapi.get_name(idc.BADADDR, func.startEA) heads = idautils.Heads(next_xor, func.endEA) lxors = [] for head in heads: if idc.GetMnem(head).startswith('j'): jmp_addr = idc.GetOperandValue(head,0) if jmp_addr < next_xor and jmp_addr > func.startEA: entry["loop"] = True break self._interesting_xors.append(entry) next_xor = idc.FindText(idc.NextHead(next_xor), idc.SEARCH_DOWN|idc.SEARCH_NEXT, 0, 0, "xor")
def __init__(self, ea, dec): self.name = idaapi.get_name(ea,ea) self.dec = dec self.type = "dword"
def __init__(self, ea, insn): self.name = idaapi.get_name(ea,ea) self.insn = insn
def name_wrap_insn(ea, insn): if idaapi.get_name(ea,ea) == None: return insn else: return named_code_node(ea, insn)
def name_wrap_data(ea, dec): if idaapi.get_name(ea,ea) == None: return dec else: return named_data_node(ea, dec)
def fix_all(): # wait till autoanalysis is done idaapi.autoWait() ea = 0 numInst = 0 numAddRegPc = 0 numFixed = 0 t0 = time.clock() # last MOV/MOVT inst targeting the register, key=register number movVal = dict() movtVal = dict() global refs cnt = 0 while True: cnt += 1 ea = idc.NextHead(ea) if cnt & 0xfff == 0: print "[progress] ea: %x" % ea if ea == idc.BADADDR: break if not idaapi.isCode(idaapi.getFlags(ea)): continue numInst += 1 # slow, is there any way to avoid it?.. i = idautils.DecodeInstruction(ea) if not i: continue mnem = i.get_canon_mnem() if i[0].type != 1: # only interested in register target operands continue target_reg = i[0].phrase if mnem == 'ADD': if i[1].type == 1 and i[1].phrase == 15: numAddRegPc += 1 (val, mov_ea) = movVal.get(target_reg, (0, 0)) (val_t, movt_ea) = movtVal.get(target_reg, (0, 0)) if not mov_ea: # No preceding MOV, bailing.. continue numFixed += 1 target_addr = 0xffffFFFF & (ea + 4 + val + 0x10000 * val_t) # could be THUMB proc.. if target_addr & 1 and idaapi.isCode(idaapi.getFlags(target_addr - 1)): target_name = idaapi.get_name(target_addr - 1, target_addr - 1) else: target_name = idaapi.get_name(target_addr,target_addr) refs.append((ea, target_addr, target_name)) if i[1].type == 5: if mnem == 'MOV': movVal[target_reg] = (i[1].value, ea) movtVal[target_reg] = (0, 0) # since movw clears top bits anyway elif mnem == 'MOVT': movtVal[target_reg] = (i[1].value, ea) else: movVal[target_reg] = (0, 0) movtVal[target_reg] = (0, 0) print "%u instructions scanned in %f seconds" % (numInst, time.clock() - t0) add_refs() # work around an IDA bug for i in range (1, 5): idaapi.autoWait() add_refs() if numAddRegPc == 0: successRate = 100 else: successRate = numFixed * 100.0 / numAddRegPc print "%u 'ADD Reg, PC' found, %u fixed: %u%%" % (numAddRegPc, numFixed, successRate) global g_done g_done = 1