def resolve_unknown_functions(): proc_name = get_proc_name() if proc_name.startswith("mips"): prolog_pattern = FUNCTION_PROLOGS.get(proc_name, "BAD ARCH") elif proc_name.startswith("ARM"): prolog_pattern = FUNCTION_PROLOGS.get(proc_name, "BAD ARCH") else: # TODO: support another arch return ea = get_start_ea(idaapi.SEG_CODE) if ea == idc.BADADDR: ea = idc.FirstSeg() cur_seg_end = idc.SegEnd(ea) while ea != idc.BADADDR: if ea < cur_seg_end and idc.GetSegmentAttr(ea, idc.SEGATTR_TYPE) == idaapi.SEG_CODE: if idc.GetFunctionFlags(ea) == -1: # not function raw_data_hex = read_addr(ea) if re.match(prolog_pattern, raw_data_hex.decode('hex')): idc.MakeFunction(ea) ea = ea + 4 else: ea = idc.NextSeg(ea) cur_seg_end = idc.SegEnd(ea)
def codeify(self, ea=idc.BADADDR): func_count = 0 code_count = 0 if ea == idc.BADADDR: ea = self.get_start_ea(self.CODE) if ea == idc.BADADDR: ea = idc.FirstSeg() self.say("\nLooking for undefined code starting at: %s:0x%X" % (idc.SegName(ea), ea)) while ea != idc.BADADDR: try: if idc.GetSegmentAttr(ea, idc.SEGATTR_TYPE) == self.CODE: if idc.GetFunctionName(ea) != '': ea = idc.FindFuncEnd(ea) continue else: if idc.MakeFunction(ea): func_count += 1 elif idc.MakeCode(ea): code_count += 1 except: pass ea = idc.NextAddr(ea) self.say("Created %d new functions and %d new code blocks\n" % (func_count, code_count))
def LocatePointerLists(): seg = idc.FirstSeg() initArrayAddr = 0 while seg != idc.BADADDR: seg = idc.NextSeg(seg) segName = idc.SegName(seg) if segName == ".init_array": initArrayAddr = idc.SegStart(seg) break # find Il2CppCodeRegistrationOffset from init_array Il2CppCodeRegistrationOffset = initArrayAddr + 30 * (BITS / 8) print "find Il2CppCodeRegistrationOffset %x" % Il2CppCodeRegistrationOffset Il2CppCodeRegistrationCpp = GetVarFromAddr(Il2CppCodeRegistrationOffset) print "Il2CppCodeRegistrationCpp: %x" % Il2CppCodeRegistrationCpp idc.MakeName(Il2CppCodeRegistrationCpp, "Il2CppCodeRegistrationCpp") #Il2CppCodegenRegistration = 0 #for r in idautils.XrefsFrom(Il2CppCodeRegistrationAddr + 0x14, 0): # Il2CppCodegenRegistration = hex(r.to) #g_CodeRegistration = 0 #for r in idautils.XrefsFrom(Il2CppCodegenRegistration + 0x18, 0): # g_CodeRegistration = hex(r.to) opndValue = idc.GetOperandValue(Il2CppCodeRegistrationCpp + 0x8, 1) offset = GetVarFromAddr(opndValue) _GLOBAL_OFFSET_TABLE_ = idc.LocByName("_GLOBAL_OFFSET_TABLE_") print "_GLOBAL_OFFSET_TABLE_ %x" % _GLOBAL_OFFSET_TABLE_ Il2CppCodegenRegistration = (_GLOBAL_OFFSET_TABLE_ + offset) & 0xFFFFFFFF idc.MakeName(Il2CppCodegenRegistration, "Il2CppCodegenRegistration") print "Il2CppCodegenRegistration %x" % Il2CppCodegenRegistration opndValue = idc.GetOperandValue(Il2CppCodegenRegistration + 0xC, 1) offset = GetVarFromAddr(opndValue) g_CodeRegistration = (_GLOBAL_OFFSET_TABLE_ + offset) & 0xFFFFFFFF idc.MakeName(g_CodeRegistration, "g_CodeRegistration") print "g_CodeRegistration %x" % g_CodeRegistration g_MethodPointers = GetVarFromAddr(g_CodeRegistration + 0x4) idc.MakeName(g_MethodPointers, "g_MethodPointers") print "g_MethodPointers %x" % g_MethodPointers opndValue = idc.GetOperandValue(Il2CppCodegenRegistration + 0x04, 1) offset = GetVarFromAddr(opndValue) g_MetadataRegistration = GetVarFromAddr((_GLOBAL_OFFSET_TABLE_ + offset) & 0xFFFFFFFF) idc.MakeName(g_MetadataRegistration, "g_MetadataRegistration") print "g_MetadataRegistration %x" % g_MetadataRegistration g_MetadataUsages = GetVarFromAddr(g_MetadataRegistration + 0x3C) idc.MakeName(g_MetadataUsages, "g_MetadataUsages") print "g_MetadataUsages %x" % g_MetadataUsages return (g_MethodPointers, g_MetadataUsages)
def getSegBoundaries(segName) : s = idc.FirstSeg(); while s != idc.BADADDR : if idc.SegName(s) == segName : return (s, idc.SegEnd(s)) s = idc.NextSeg(s) return None
def codeify(self, ea=idc.BADADDR): func_count = 0 code_count = 0 if ea == idc.BADADDR: ea = self.get_start_ea(self.CODE) if ea == idc.BADADDR: ea = idc.FirstSeg() print "\nLooking for undefined code starting at: %s:0x%X" % ( idc.SegName(ea), ea) if self.get_start_ea(self.DATA) == idc.BADADDR: print "WARNING: No data segments defined! I don't know where the code segment ends and the data segment begins." while ea != idc.BADADDR: try: if idc.GetSegmentAttr(ea, idc.SEGATTR_TYPE) == self.CODE: if idc.GetFunctionName(ea) != '': ea = idc.FindFuncEnd(ea) continue else: if idc.MakeFunction(ea): func_count += 1 elif idc.MakeCode(ea): code_count += 1 except: pass ea = idc.NextAddr(ea) print "Created %d new functions and %d new code blocks\n" % ( func_count, code_count)
def get_all_segments(): segments = [] seg = idc.FirstSeg() while seg != idc.BADADDR: segments.append((seg, idc.SegEnd(seg))) seg = idc.NextSeg(seg) return segments
def LocateStringLiterals(): seg = idc.FirstSeg() initArrayAddr = 0 while seg != idc.BADADDR: seg = idc.NextSeg(seg) segName = idc.SegName(seg) if segName == ".data.rel.ro": data_rel_ro = idc.SegStart(seg) break addr = data_rel_ro referedVars = [] while idc.SegName(addr) == ".data.rel.ro": for r in idautils.XrefsTo(addr, 0): referedVars.append(addr) break addr += 4 candidateMetadaUsages = [] for idx, var in enumerate(referedVars): if idx < (len(referedVars) - 1) and (referedVars[idx + 1] - referedVars[idx]) >= 1024: if idc.Dword(var) == 0x0: continue if IsDataFollowing(var) and idc.SegName(idc.Dword(var)) == '.bss': candidateMetadaUsages.append(var) for candidate in candidateMetadaUsages: for referedVar in referedVars: if referedVar == candidate: nextVar = referedVars[referedVars.index(referedVar) + 1] print "candidate: 0x%x, candidate end: 0x%x, data numbers: %d" % ( candidate, nextVar, (nextVar - candidate) / 4) break
def LocateMethodPointers(): seg = idc.FirstSeg() initArrayAddr = 0 while seg != idc.BADADDR: seg = idc.NextSeg(seg) segName = idc.SegName(seg) if segName == ".data.rel.ro": data_rel_ro = idc.SegStart(seg) break addr = data_rel_ro referedVars = [] while idc.SegName(addr) == ".data.rel.ro": for r in idautils.XrefsTo(addr, 0): #print "is refered: 0x%x" % addr referedVars.append(addr) break addr += 4 candidateMethodPointers = [] for var in referedVars: if IsSubFollowing(var): candidateMethodPointers.append(var) for candidate in candidateMethodPointers: for referedVar in referedVars: if referedVar == candidate: nextVar = referedVars[referedVars.index(referedVar) + 1] print "candidate: 0x%x, candidate end: 0x%x, method numbers: %d" % ( candidate, nextVar, (nextVar - candidate) / 4) break
def find_all_pattern(pat): first = idc.FirstSeg() last = idc.BADADDR result = [] ea = idaapi.find_binary(first, last, pat, 16, idaapi.SEARCH_DOWN) while ea != idaapi.BADADDR and ea < last: result.append(ea) ea = idaapi.find_binary(ea, last, pat, 16, idaapi.SEARCH_DOWN | idaapi.SEARCH_NEXT) return result
def get_start_ea(self, attr): ea = idc.BADADDR seg = idc.FirstSeg() while seg != idc.BADADDR: if idc.GetSegmentAttr(seg, idc.SEGATTR_TYPE) == attr: ea = seg break else: seg = idc.NextSeg(seg) return ea
def makeFuncsFromPreamble(funcpreamble, startea=idc.FirstSeg(), endea = idaapi.BADADDR): """ This method makes functions everywhere that the sequence 'funpreamble' is found. NOTE: this method is generally unsafe, because it will attempt to make functions where there may be no function. Use it with caution. """ ea = startea i = 0 while (ea != idaapi.BADADDR and ea < endea): ea = idc.FindBinary(ea, SEARCH_DOWN, funcpreamble) idc.MakeFunction(ea) idc.Wait() ea = ea + 1 # idc.FindBinary(ea) returns ea if ea matches, silly
def get_seg_range_by_name(self, seg_name): ''' 获取指定名字的seg的范围 ''' start_addr = idc.FirstSeg() while start_addr != idaapi.BADADDR: end_addr = idc.SegEnd(start_addr) name = idc.SegName(start_addr) #print '%s : 0x%08x - 0x%08x'%(seg_name, start_addr, seg_end_addr) if name.lower() == seg_name.lower(): return [start_addr, end_addr] start_addr = idc.NextSeg(start_addr) return None
def get_data_section(self): ea = idc.BADADDR seg = idc.FirstSeg() while seg != idc.BADADDR: if ea == idc.BADADDR and idc.GetSegmentAttr(seg, idc.SEGATTR_TYPE) == 2: ea = seg stop = idc.SegEnd(seg) seg = idc.NextSeg(seg) return (ea, stop)
def _get_segments(self, attr): segments = [] start = idc.BADADDR end = idc.BADADDR seg = idc.FirstSeg() while seg != idc.BADADDR: if idc.GetSegmentAttr(seg, idc.SEGATTR_TYPE) == attr: start = idc.SegStart(seg) end = idc.SegEnd(seg) segments.append((start, end)) seg = idc.NextSeg(seg) return segments
def get_segments(): """ Returns a set of of (segment name, segment start, segment end). The end is exclusive - last byte of segment is one byte before. """ segments = set() segment_start = idc.FirstSeg() while segment_start != idc.BADADDR: segment_name = idc.SegName(segment_start) segment_end = idc.SegEnd(segment_start) segments.add((segment_name, segment_start, segment_end)) segment_start = idc.NextSeg(segment_start) return segments
def datify(self): ea = self.get_start_ea(self.DATA) if ea == idc.BADADDR: ea = idc.FirstSeg() print "Converting remaining data to DWORDs...", while ea != idc.BADADDR: flags = idc.GetFlags(ea) if idc.isUnknown(flags) or idc.isByte(flags): idc.MakeDword(ea) idc.OpOff(ea, 0, 0) ea = idc.NextAddr(ea) print "done."
def stringify(self): n = 0 ea = self.get_start_ea(self.DATA) if ea == idc.BADADDR: ea = idc.FirstSeg() print("Looking for possible strings starting at: %s:0x%X..." % (idc.SegName(ea), ea)), for s in idautils.Strings(): if s.ea > ea: if not idc.isASCII(idc.GetFlags(s.ea)) and idc.MakeStr( s.ea, idc.BADADDR): n += 1 print "created %d new ASCII strings" % n
def static_breakpoint(target_type): try: base = idc.FirstSeg() if base == idc.BADADDR: print("can't find first seg") return filepath = idaapi.get_input_file_path() print("filename:", filepath) idbFile = open(filepath, "rb") e_phoff = get_ushort(idbFile, 0x1C) e_phentsize = get_ushort(idbFile, 0x2A) e_phnum = get_ushort(idbFile, 0x2C) print(e_phoff, e_phentsize, e_phnum) dynamic = -1 for i in xrange(e_phnum): idbFile.seek(e_phoff + e_phentsize * i) p_type = get_ulong(idbFile, e_phoff + e_phentsize * i) # define PT_DYNAMIC 2 if p_type == 2: dynamic = get_ulong(idbFile, e_phoff + e_phentsize * i + 4) break if dynamic == -1: print("\tcan't find dynamic") return dynamic_type = get_ulong(idbFile, dynamic) init = -1 while dynamic_type != 0: dynamic += 8 dynamic_type = get_ulong(idbFile, dynamic) if dynamic_type == target_type: init = get_ulong(idbFile, dynamic + 4) break if init == -1: print("\tcan't find init") return idc.AddBpt(base + init) print('\tbp the init on the %x' % (base + init)) print("\nbp init finished") except BaseException, e: print(e)
def datify(self): ea = self.get_start_ea(self.DATA) if ea == idc.BADADDR: ea = idc.FirstSeg() self.say("Converting remaining data to DWORDs...", ) while ea != idc.BADADDR: flags = idc.GetFlags(ea) if (idc.isUnknown(flags) or idc.isByte(flags)) and ((ea % 4) == 0): idc.MakeDword(ea) idc.OpOff(ea, 0, 0) ea = idc.NextAddr(ea) self.say("done.") self._fix_data_offsets()
def analyze(cu): objc_meth_map = {} methnamebegin = 0 methnameend = 0 forbitmeth = [ "alloc", "allocWithZone:", "allowsWeakReference", "autorelease", "class", "conformsToProtocol:", "copy", "copyWithZone:", "dealloc", "debugDescription", "description", "doesNotRecognizeSelector:", "finalize", "forwardingTargetForSelector:", "forwardInvocation:", "hash", "init", "initialize", "instanceMethodForSelector:" "instanceMethodSignatureForSelector:", "instancesRespondToSelector:", "isEqual", "isKindOfClass:", "isMemberOfClass:", "isProxy", "isSubclassOfClass:", "load", "methodForSelector:", "methodSignatureForSelector:", "mutableCopy", "mutableCopyWithZone:", "performSelector:", "performSelector:withObject:", "performSelector:withObject:withObject:", "respondsToSelector:", "release", "resolveClassMethod:", "resolveInstanceMethod:", "retain", "retainCount", "retainWeakReference", "superclass", "zone", ".cxx_construct", ".cxx_destruct", ] # find the segment which contains objc method names curseg = idc.FirstSeg() while curseg != 0xffffffff: if "__objc_methname" == idc.SegName(curseg): methnamebegin = idc.SegStart(curseg) methnameend = idc.SegEnd(curseg) break curseg = idc.NextSeg(curseg) # get objc method names if methnamebegin != 0: while methnamebegin < methnameend: funcname = idc.GetString(methnamebegin) objc_meth_map[funcname] = methnamebegin methnamebegin = methnamebegin + len(funcname) + 1 # get objc func table funcmap = {} addr = idc.PrevFunction(-1) while addr != 0xffffffff: curname = idc.GetFunctionName(addr) if -1 != curname.find('['): curname = curname.replace("[", "").replace("]", "") curname = curname.split(" ")[1] # may be more than one function with same sel but differenct class if curname not in funcmap: funcmap[curname] = [] funcmap[curname].append(addr) addr = idc.PrevFunction(addr) # make xref result = [] indx = 0 for (k, v) in objc_meth_map.items(): # find corresponding func addr if k in funcmap and k not in forbitmeth: farr = funcmap[k] # find xref to code and make xref for each curref = idc.DfirstB(v) while curref != 0xffffffff: for f in farr: cu.execute('insert into xref values (?,?,?,?,?)', [indx, curref, f, v, k]) indx += 1 curref = idc.DnextB(v, curref) return result