def RenameMod(orig, new): i = idc.NextFunction(0) while (i != idc.BADADDR): n = idc.GetFunctionName(i) if n.startswith(orig+"_"): RenameFuncWithNewMod(i,new) i = idc.NextFunction(i)
def NFuncDown( fun, n ) : i=0 f=fun while ((i<n) and (f!=idc.BADADDR)): f=idc.NextFunction(f) i=i+1 return f
def RenameRangeWithAddr(start,end,s): x = start while (x<=end): n = idc.GetFunctionName(x) if (n.startswith("sub_")): RenameFuncWithAddr(x,s) else: NameCanonical(x,s,n) x = idc.NextFunction(x)
def PrefixRange(start, end, prefix) : x = start while x < end: n = idc.GetFunctionName(x) if n.startswith("sub_"): nn = prefix + n print "Renaming %s to %s\n" % (n, nn) idc.MakeName(x,nn) x = idc.NextFunction(x)
def enumerate_function_names(): func_name = dict() for seg_ea in idautils.Segments(): # For each of the functions function_ea = seg_ea while function_ea != 0xffffffffL: function_name = idc.GetFunctionName(function_ea) # if already analyzed if func_name.get(function_name, None) != None: function_ea = idc.NextFunction(function_ea) continue image_base = idaapi.get_imagebase(function_ea) addr = function_ea - image_base addr = str(hex(addr)) addr = addr.replace("L", "") addr = addr.replace("0x", "") func_name[function_name] = get_list_of_function_instr(function_ea) function_ea = idc.NextFunction(function_ea) return func_name
def CompileFuncNamesFromRangeAsText(start,end,sep): x = start s = "" while (x<=end): n = idc.GetFunctionName(x) if (not n.startswith("sub_")): s += " " + sep + " " + n x = idc.NextFunction(x) return s
def NextFunctionCall(ea, maxea=None): if not maxea: maxea = idc.NextFunction(ea) # skip the input instruction for inst in idautils.Heads(idc.NextHead(ea, maxea), maxea): inst = idautils.DecodeInstruction(inst) # skip ahead if it is not a call instruction if inst.itype == 16: return inst.ea return None
def getFunc(self, ea=None, next=False): if ea == None: ea = idaapi.get_screen_ea() if next: ea = idc.NextFunction(ea) if ea == -1: return (0xFFFFFFFFL, 0xFFFFFFFFL) if ea < 0: return (0xFFFFFFFFL, 0xFFFFFFFFL) elif idc.GetFunctionName(ea) == idc.GetFunctionName(idc.PrevAddr(ea)): ea = idc.PrevFunction(ea) return (ea, idc.FindFuncEnd(ea))
def CompileTextFromRange(start,end,sep): x = start s = "" while (x<=end): #print "Function %x" % x faddr = list(idautils.FuncItems(x)) for c in range(len(faddr)): for d in idautils.DataRefsFrom(faddr[c]): #print "Found ref at %x" % faddr[c] if idc.GetStringType(d) == 0 and idc.GetString(d): s += " "+ sep + " " + idc.GetString(d) elif idc.GetStringType(d) == 3 and idc.GetString(d, -1, idc.ASCSTR_UNICODE): s += " " + sep + " " + idc.GetString(d,-1,idc.ASCSTR_UNICODE) x = idc.NextFunction(x) return s
def CanonicalizeRange(start,end,mod): x = start while (x<=end): n = idc.GetFunctionName(x) #if it already starts with mod name, assume it's canonical if (not n.startswith(mod+"_")): if (n.startswith("sub_")): RenameFuncWithAddr(x,mod) #this should be contains "_" elif ("_" in n): n = snakeToCamelCase(n) NameCanonical(x,mod,n) else: NameCanonical(x,mod,n) x = idc.NextFunction(x)
def find_function(function): for seg_ea in idautils.Segments(): # For each of the functions function_ea = seg_ea while function_ea != 0xffffffffL: function_name = idc.GetFunctionName(function_ea) function = function.replace("\n", "") function = function.replace("\r", "") function = function.replace(" ", "") if function.lower() == function_name.lower(): print "Found function ", function_name print hex(function_ea) return function_ea function_ea = idc.NextFunction(function_ea) return -1
def gen_map_file(): global g_module_list c=0 root_name = basicutils.GetInputFile() file = open(root_name + "_lfa_map.map", "wb") while (c<len(g_module_list)): m=g_module_list[c] mlen = idc.NextFunction(m.end) - m.start mlen_str = "0x%x" % mlen file.write("%s0x%016x%s %s\n" % (" .text".ljust(16),m.start,mlen_str.rjust(11),m.name)) c+=1 file.close()
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
def get_function_bounds(ea): """Get the bounds of the function containing `ea`. We want to discover jump table targets that are missed by IDA, and it's possible that they aren't marked as being part of the current function, and perhaps are after the assumed range of the current function. Ideally they will fall before the beginning of the next function, though. We need to be pretty careful with the case that one function tail-calls another. IDA will sometimes treat the end of the tail-called function (e.g. a thunk) as if it is the end of the caller. For this reason, we start with loose bounds using the prev/next functions, then try to narrow with the bounds of the function containing `ea`. TODO(pag): Handle discontinuous regions (e.g. because of function chunks). It may be worth to return an object here that can we queried for membership using the `__in__` method. """ seg_start, seg_end = idc.SegStart(ea), idc.SegEnd(ea) min_ea = seg_start max_ea = seg_end if is_invalid_ea(min_ea) or not is_code(ea): return ea, ea # Get an upper bound using the next function. next_func_ea = idc.NextFunction(ea) if not is_invalid_ea(next_func_ea): max_ea = min(next_func_ea, max_ea) # Get a lower bound using the previous function. prev_func_ea = idc.PrevFunction(ea) if not is_invalid_ea(prev_func_ea): min_ea = max(min_ea, prev_func_ea) prev_func = idaapi.get_func(prev_func_ea) if prev_func and prev_func.endEA < ea: min_ea = max(min_ea, prev_func.endEA) # Try to tighten the bounds using the function containing `ea`. func = idaapi.get_func(ea) if func: min_ea = max(min_ea, func.startEA) max_ea = min(max_ea, func.endEA) return min_ea, max_ea
def NextFunction(x): return idc.NextFunction(x)
bstr += "%02x" % (0x00FF & b) return bstr # Iterate over all the functions, querying from the database and printing them. fnhandled = 0 qstr = "" start = 0 end = 0 start = idc.SegByBase(idc.SegByName(".text")) if (start != idc.BADADDR): end = idc.SegEnd(start) else: start = idc.NextFunction(0) end = idc.BADADDR f = start while (f != idc.BADADDR) and (f <= end): iname = idc.GetFunctionName(f) adr = f adrstr = "%x" % f res = None bstr = ida_functionprefix(f) # We query the server in batches of 64 functions to reduce HTTP overhead. qstr += "%s=%s&" % (adrstr, bstr) f = idc.NextFunction(f)
def def_functions(s_start): num_added_functions = 0 s_addr = s_start s_end = idc.GetSegmentAttr(s_start, SEGATTR_END) #idc.SegEnd(segm) print "0x%08x 0x%08x" % (s_start, s_end) while (s_addr < s_end): print "Testing address 0x%08x" % s_addr #optimization assumes that function chunks are consecutive (no "function-in-function" monkey business) if (idaapi.get_func(s_addr)): next_func = idc.NextFunction(s_addr) ea = s_addr for c in idautils.Chunks(s_addr): #only use chunks in lookahead that do not jump over the next function and that are not smaller than where we are atm. if (c[1] > ea) and (c[1] <= next_func): ea = c[1] if ea == s_addr: s_addr += 2 else: s_addr = ea #s_addr += 4 continue else: #This is not a good optimization, there WILL be data refs to function start addresses sometimes. ''' if sum(1 for _ in (CodeRefsTo(s_addr, 1))) != 0: s_addr += 4 continue ''' #also add STMFD if ((idc.GetMnem(s_addr) == "STM") and ("SP!" in idc.GetOpnd(s_addr, 0)) and ("LR" in idc.GetOpnd(s_addr, 1))) or ( ((idc.GetMnem(s_addr) == "PUSH") or (idc.GetMnem(s_addr) == "PUSH.W") or (idc.GetMnem(s_addr) == "STR.W")) and ("LR" in idc.GetOpnd(s_addr, 0))): print "Found function at 0x%08x" % s_addr idc.MakeFunction(s_addr) f = idaapi.get_func(s_addr) if (type(f) == type(None)): print "Failed to create function! Undefined instructions?" s_addr += 2 else: num_added_functions += 1 ea = -1 for c in idautils.Chunks(s_addr): if c[1] > ea: ea = c[1] if ea != -1: s_addr = ea #failed? else: s_addr += 2 else: s_addr += 2 print "finished segment" return num_added_functions
def def_functions(s_start): num_added_functions = 0 s_addr = s_start s_end = idc.GetSegmentAttr(s_start, SEGATTR_END) #idc.SegEnd(segm) print "0x%08x 0x%08x" % (s_start, s_end) while (s_addr < s_end): #print "Testing address 0x%08x" % s_addr #optimization assumes that function chunks are consecutive (no "function-in-function" monkey business) if (idaapi.get_func(s_addr)): next_func = idc.NextFunction(s_addr) ea = s_addr for c in idautils.Chunks(s_addr): #only use chunks in lookahead that do not jump over the next function and that are not smaller than where we are atm. if (c[1] > ea) and (c[1] <= next_func): ea = c[1] if ea == s_addr: s_addr += 2 else: s_addr = ea #s_addr += 4 continue else: #This is not a good optimization, there WILL be data refs to function start addresses sometimes. ''' if sum(1 for _ in (CodeRefsTo(s_addr, 1))) != 0: s_addr += 4 continue .text:00000000000130C4 SUB SP, SP, #0x80 .text:00000000000130C8 STP X24, X23, [SP,#0x70+var_30] LOAD:0000000000015F20 STP X29, X30, [SP,#-0x10+var_s0]! LOAD:0000000000015F24 MOV X29, SP LOAD:00000000000178A4 STP X20, X19, [SP,#-0x10+var_10]! LOAD:00000000000178A8 STP X29, X30, [SP,#0x10+var_s0] LOAD:000000000001A1B0 MOV W8, #0x70 ; 'p' LOAD:000000000001A1B4 STR WZR, [X0] LOAD:000000000001C020 MOV X8, X1 LOAD:000000000001C024 MOV X9, X0 LOAD:000000000001D48C STP X24, X23, [SP,#-0x10+var_30]! LOAD:000000000001D490 STP X22, X21, [SP,#0x30+var_20] LOAD:000000000001F07C SUBS W8, W2, #1 LOAD:000000000001F080 B.LT loc_1F0B0 LOAD:00000000000000B0 ADRP X16, #off_A4060@PAGE LOAD:00000000000000B4 LDR X17, [X16,#off_A4060@PAGEOFF] LOAD:000000000000AAF8 000 28 00 40 39 LDRB W8, [X1] ; Load from Memory LOAD:000000000000AAFC 000 29 04 40 F9 LDR X9, [X1,#8] ; Load from Memory ''' if ((idc.GetMnem(s_addr) == "STP") and \ # ("X29" in idc.GetOpnd(s_addr, 0)) and \ # ("X30" in idc.GetOpnd(s_addr, 1)) and \ ("SP" in idc.GetOpnd(s_addr, 2))) \ or \ ((idc.GetMnem(s_addr) == "ADRP") and \ # ("X" in idc.GetOpnd(s_addr, 0)) and \ ("X" in idc.GetOpnd(s_addr, 0))) \ or \ ((idc.GetMnem(s_addr) == "LDRB")): # \ # or \ # (((idc.GetMnem(s_addr) == "PUSH") or (idc.GetMnem(s_addr) == "PUSH.W") or (idc.GetMnem(s_addr) == "STR.W") ) and \ # ("LR" in idc.GetOpnd(s_addr, 0))): print "Found function at 0x%08x" % s_addr idc.MakeFunction(s_addr) f = idaapi.get_func(s_addr) if (type(f) == type(None)): print "Failed to create function! Undefined instructions?" s_addr += 2 else: num_added_functions += 1 ea = -1 for c in idautils.Chunks(s_addr): if c[1] > ea: ea = c[1] if ea != -1: s_addr = ea #failed? else: s_addr += 2 else: s_addr += 2 print "finished segment" return num_added_functions
def func_call_weight(f_start, f_end): global g_function_list c = 1 f = f_start fe = f_end if f==0: f = basicutils.NextFunction(0) f_end = basicutils.BADADDR prevscore = 0 prevscore_1 = 0 prevscore_2 = 0 z1 = 0 z2 = 0 #for each function in range while (f < fe): #get both LFA scores for the function score_1 = func_callers_weight(f) score_2 = func_callee_weight(f) #if both scores are 0 (i.e. no references for the function or all refs are above the threshold) #then skip the function altogether if (score_1 == 0) and (score_2 == 0): print "Skipping 0x%08x\n" % f prevscore_1 = 0 prevscore_2 = 0 z1 = 1 z2 = 1 f = idc.NextFunction(f) continue #if 1st or 2nd score is zero, interpolate using previous score and an assumed negative linear slope #otherwise use the score if (score_1 == 0): score_1 = prevscore_1 - z1 * .4 z1 += 1 else: prevscore_1 = score_1 z1 = 1 if (score_2 == 0): score_2 = prevscore_2 - z2 * .4 z2 += 1 else: prevscore_2 = score_2 z2 = 1 total_score = score_1 + score_2 #Output scores in log window print "0x%08x, %d , %f, %f, %f" % (f, c,score_1, score_2, total_score) #Add scores to the global function score list finf = func_info(f,score_1,score_2) g_function_list.append(finf) line = "0x%08x, %d , %f, %f, %f\n" % (f,c,score_1, score_2, total_score) f=basicutils.NextFunction(f) c+=1
def hasNextFunction(ea): return False if isBad(ea) else not isBad(idc.NextFunction(ea))
def getNextFunction(ea): return idc.BADADDR if warnBad(ea) else idc.NextFunction(ea)
def ProgramAddrRange() : return idc.PrevFunction(idc.BADADDR) - idc.NextFunction(0)
def RenameModRange(start, end, new): x = start while (x<=end): n = idc.GetFunctionName(x) RenameFuncWithNewMod(x,new) x = idc.NextFunction(x)
def ForEveryFuncInDb( fun ): f = idc.NextFunction(0) while (f != idc.BADADDR): """print "ev: %#x" % f""" fun(f) f=idc.NextFunction(f)
print "Start:0x%x,End:0x%x" % (idc.GetFunctionAttr( 0x10003F3BD, FUNCATTR_START), idc.GetFunctionAttr(0x10003F3BD, FUNCATTR_END)) #查看类有哪些属性 dir(func) #获取类型 type(func) #获取指定地址所在函数的前一个函数的起始地址 func = idc.PrevFunction(0x10000646D) print idc.GetFunctionName(func), hex(func) #获取指定地址所在函数的后一个函数的起始地址 func = idc.NextFunction(0x10000646D) print idc.GetFunctionName(func), hex(func) #获取下一条指令的地址 idc.NextHead() #遍历某个地址所在函数的所有指令 ea = here() start = idc.GetFunctionAttr(ea, FUNCATTR_START) end = idc.GetFunctionAttr(ea, FUNCATTR_END) cur_addr = start while cur_addr < end: print hex(cur_addr), idc.GetDisasm(cur_addr) cur_addr = idc.NextHead(cur_addr, end)