def mark_calls(self, mem_area_id): if not self._from_idb: for tid in self._maze['process']['mem_areas'][mem_area_id]['tids']: for thread in self._maze['process']['threads']: if tid == thread['tid']: for call in thread['calls']: if 'name' in call: fname = call['name'].encode('ascii') if len(call['callees']) == 1: ref = call['callees'][0]['addr'] if idc.GetMnem(ref) == "jmp": while fname in self.dup_apis: fname += "_" self.dup_apis.add(fname) idc.MakeName( idc.GetOperandValue(ref, 0), fname) for wrap_call in thread['calls']: if wrap_call["target"] == ref: wrap_call['real_call'] = call continue for callee in call['callees']: op = idc.GetOpType(callee['addr'], 0) if op == 2: val = idc.GetOperandValue( callee['addr'], 0) if val is not None and val > 0: idc.MakeName(val, fname) else: fname = idc.GetFunctionName(call['target']) if len(fname) == 0: fname = "0x%x" % call['target'] if call['is_reg']: for callee in call['callees']: idc.MakeComm(callee['addr'], fname)
def search_reg(): global mod_addr_min global mod_addr_max code_reg = idc.LocByName('g_code_reg') meta_reg = idc.LocByName('g_meta_reg') print('searching metareg') if meta_reg == idc.BADADDR: meta_reg = search_meta_reg(mod_addr_min + 56, mod_addr_max - 256) if meta_reg == idc.BADADDR: print('Failed to search metareg') raise print('%08X: g_meta_reg' % meta_reg) idc.MakeName(meta_reg, 'g_meta_reg') if code_reg == idc.BADADDR: print('searching codereg') code_reg = search_code_reg(meta_reg - 256, meta_reg - 16) if code_reg == idc.BADADDR: print('Failed to search codereg') raise print('%08X: g_code_reg' % code_reg) idc.MakeName(code_reg, 'g_code_reg') #if code_reg == idc.BADADDR or meta_reg == idc.BADADDR: # return analyze_reg() return code_reg, meta_reg
def assign_kmdf_structure_types(address): # Get the jmp to de import jmp_import_ea = idautils.XrefsTo(address).next().frm # There is only one XREF to WdfVersionBind call_wdfVersionBind = idautils.XrefsTo(jmp_import_ea).next().frm print(hex(call_wdfVersionBind)) argument_WdfBindInfo = find_function_arg(call_wdfVersionBind, "lea", "r8", 0) if argument_WdfBindInfo is None: print("Error: Argument WdfBindInfo wasn't found!") return wdfBindInfo = idc.GetOperandValue(argument_WdfBindInfo, 1) idc.MakeName(wdfBindInfo, '_WdfBindInfo') print("WdfBindInfo Struct: ", hex(wdfBindInfo)) if not assign_struct_to_address(wdfBindInfo, "_WDF_BIND_INFO"): print("The _WDF_BIND_INFO struct wasn't found in the database") return g_vars["_WDF_BIND_INFO"] = wdfBindInfo # Assign ComponentGlobals Name argument_WdfComponentGlobals = find_function_arg(call_wdfVersionBind, "lea", "r9", 0) wdfComponentGlobals = idc.GetOperandValue(argument_WdfComponentGlobals, 1) g_vars["_WDF_COMPONENT_GLOBALS"] = wdfComponentGlobals idc.MakeName(wdfComponentGlobals, '_WdfComponentGlobals') # Now assign the WDFFUNCTIONS to FuncTable wdfFunctions = idc.Qword(wdfBindInfo + 0x20) g_vars["_WDFFUNCTIONS"] = wdfFunctions assign_struct_to_address(wdfFunctions, "_WDFFUNCTIONS") idc.MakeName(wdfFunctions, 'g_WdfF_Functions')
def rename(self, nuname=None, **kwargs): tp = self.currentType(**kwargs) cnm = tp['name'] if not nuname: nuname = idc.AskStr(cnm, "Set new type name for " + cnm + ":") if not nuname or nuname == cnm: Logger.debug("Rename cancelled") return sid = idc.GetStrucIdByName(nuname) if sid and sid != idc.BADADDR: raise self.WrongTypeError("Type already exists", nuname) Logger.debug("Renaming class %s to %s", str(tp), nuname) if tp.get('vtblea'): idc.MakeName(tp['vtblea'], 'vtbl_' + nuname) if tp.get('id'): idc.SetStrucName(tp['id'], nuname) if tp.get('vtblid'): tp['vtblnm'] = nuname + 'Vtbl' idc.SetStrucName(tp['vtblid'], tp['vtblnm']) for nm in idautils.Names(): if nm[1].startswith(cnm): fn = nm[1].replace(cnm, nuname) Logger.debug("Renaming function " + nm[1] + " to " + fn) idc.MakeName(nm[0], fn) self.typeid = nuname self.update()
def rename_func(begin, fname): global named fname = fname.replace('~', '__') fname = fname.replace('<', '_') fname = fname.replace('>', '_') try: ret = idc.MakeName(begin, fname) named += 1 except: if ret == 0 and idc.MakeName(begin, '_' + fname + '1') != 0: named += 1 elif ret == 0 and idc.MakeName(begin, '_' + fname + '2') != 0: named += 1
def set_name(self, name): # Cannot rename a non-head address # Silent fail is a good idea ? if not self.is_head: return if idc.MakeName(self.addr, name): return # Fail : autoname # Infinitellop seems a little bit extrem counter = itertools.count() for i in counter: if idc.MakeName(self.addr, name + "_{0}".format(i)): return True raise ValueError("Out of infinite loop")
def apply_labels(fun_names): new_sub = 0 new_som = 0 new_oth = 0 named_overwrittens = [] for f_ea, name in fun_names.iteritems(): name = re.sub('[^a-zA-Z0-9_]+', '', name) curr_name = idaapi.get_func_name(f_ea) if curr_name.startswith("sub_"): new_sub += 1 elif "_something" in curr_name: new_som += 1 else: new_oth += 1 named_overwrittens.append(curr_name) #so we don't overwrite these continue # stats counting aside, make sure we don't overwrite non-sub # functions from e.g. our IDC assignments if not curr_name.startswith("sub_") and not "_something" in curr_name: continue ret = idc.LocByName(name) count = 1 while (ret != 0xffffffff): count += 1 ret = idc.LocByName(name + "__" + "%d" % count) idc.MakeName(f_ea, name + ("__%d" % count) * (count > 1))
def load_export_renames(src): with open(path.expanduser(src), 'r') as f: exports = json.load(f) for addr, name in exports.items(): addr = int(addr) name = name.encode('utf-8') idc.MakeName(addr, name)
def MakeName(self, address, name): """ MakeName(int addr, string name]) => None Set the location pointed by `address` with the name specified as argument. Example: ida MakeName 0x4049de __entry_point """ addr = long(address, 16) if ishex(address) else long(address) return idc.MakeName(addr, name)
def activate(self, ctx): import json filepath = idc.AskFile(False, "*.zmu;*.overlay;*", "Load Zelos Overlay...") if filepath is None: return f = open(filepath, "r") zelos_data = f.read() f.close() zelos_data = zelos_data[len("DISAS\n"):] zelos_dump = json.loads(zelos_data) # Apply the overlay data for comment in zelos_dump["comments"]: ea = comment["address"] try: comment_text = str(comment["text"]) except UnicodeEncodeError: comment_text = "" color = comment.get("color", 0x73F0DF) # Set color of instruction line idaapi.set_item_color(ea, color) idaapi.set_cmt(ea, comment_text, False) # Set function name if not already changed idc.GetFunctionAttr(ea, idc.FUNCATTR_START) name = idc.GetFunctionName(ea) if len(name) > 0 and name.startswith("zmu_") is False: idc.MakeName(ea, "zmu_" + name) return 1
def import_symbols(names): """Import BN symbol names """ for addr, name in names.items(): addr = int(addr) name = sanitize_name(name).encode("utf-8") idc.MakeName(addr, name)
def setName(self, funcName): # type: (str) -> None """ Same as in Head. Kept for reference. :param funcName: (str) name of the function """ idc.MakeName(self.func_ea, funcName)
def rename_regex(self, n, regex_str="", dryrun=False): count = 0 if not regex_str: regex_str = idc.AskStr("", "Regex rename rule") if regex_str: if dryrun: print "Testing regex rename rule: '%s'" % regex_str regex = re.compile(regex_str) # Look at all the profiled functions for (function, xrefs) in self.profile.functions.iteritems(): new_function_name = "" # Don't rename functions that have already been renamed if not idc.Name(function).startswith("sub_"): continue # Look through all the strings referenced by this function for string in [x.string for x in xrefs if x.type == str]: # Does the string match the given regex? m = regex.search(string) if m: # Take the last group from the regex match potential_function_name = m.groups()[-1].split(" ")[0] # Replace common bad chars with underscores for c in ['-', '>']: potential_function_name = potential_function_name.replace( c, '_') # Make sure this is a valid name; should not include format strings if idaapi.isident( potential_function_name ) and '%' not in potential_function_name: # Use the longest of the matching strings if len(potential_function_name) > len( new_function_name): new_function_name = potential_function_name if new_function_name: # Append _n to the function name, if it already exists n = 1 orig_new_function_name = new_function_name while idc.LocByName(new_function_name) != idc.BADADDR: new_function_name = "%s_%d" % (orig_new_function_name, n) n += 1 if dryrun: print "%s => %s" % (idc.Name(function), new_function_name) count += 1 else: if idc.MakeName(function, new_function_name): count += 1 print "Renamed %d functions" % count
def analyze_init_array(): print('analyze_init_array') seg = idc.SegByName('.init_array') addr = idc.SegByBase(seg) seg_st = idc.GetSegmentAttr(addr, idc.SEGATTR_START) seg_en = idc.GetSegmentAttr(addr, idc.SEGATTR_END) print(' .init_array = %08X - %08X' % (seg_st, seg_en)) if addr == idc.BADADDR: return while addr < seg_en: funcaddr = idc.Dword(addr) if funcaddr > 0: name = idc.Name(funcaddr) if name is None or name.startswith('sub_'): idc.MakeName(funcaddr, 'INIT_%X' % funcaddr) print(' %08X: %s' % (funcaddr, idc.Name(funcaddr))) addr += 4 return seg_st
def __mark_calls(self): for thread in self["mem_areas"][0]['threads']: for call in thread['calls']: if not call['returns']: continue # generate name for the function fname = idc.GetFunctionName(call['target']) if len(fname) == 0: if len(call["name"]) > 0: fname = call["name"].encode('ascii') else: fname = "0x%x" % call["target"] # name all indirect calls for xref in call['xrefs']: idc.MakeCode(xref['addr']) op = idc.GetOpType(xref['addr'],0) if op == ida_ua.o_mem: val = idc.GetOperandValue(xref['addr'], 0) vname = idc.get_name(val) if val is not None and val > 0 and len(vname) > 0 and 'dword_' in vname: idc.MakeName(val, fname) elif op == ida_ua.o_reg or op == ida_ua.o_displ: idc.MakeComm(xref['addr'], fname)
def find_WdfControlDeviceInitAllocate(): function_offset = OFFSET_WdfControlDeviceInitAllocate call_pfn = None try: for xref in idautils.XrefsTo(g_vars["_WDFFUNCTIONS"] + function_offset): call_pfn = xref.frm except StopIteration: # this is case 2 or 3 pass if call_pfn is None: call_pfn = find_wdf_callback_through_immediate("call", 0, function_offset) if call_pfn: idc.OpStroffEx(call_pfn, 0, (idaapi.get_struc_id("_WDFFUNCTIONS")), 0) if call_pfn is None: call_pfn = find_wdf_callback_through_immediate("mov", 1, function_offset) if call_pfn: idc.OpStroffEx(call_pfn, 1, (idaapi.get_struc_id("_WDFFUNCTIONS")), 0) lea_sddl = find_function_arg(call_pfn, "lea", "r8", 0) unicode_sddl = idc.GetOperandValue(lea_sddl, 1) idc.MakeName(unicode_sddl, 'control_device_sddl') assign_struct_to_address(unicode_sddl, "_UNICODE_STRING") print("Control Device SDDL at: ", hex(unicode_sddl))
def rename_functions(self, debug=True, dry_run=False): ''' Renames functions starting with "sub_" based on unique string xrefs. @debug - Set to False to supress debug output. @dry_run - Set to True to perform a dry run (functions will not actually be renamed). Returns the number of renamed functions. ''' count = 0 for (function_address, function_name) in self.func2str_mappings().iteritems(): if idc.Name(function_address).startswith("sub_"): if dry_run == True or idc.MakeName(function_address, function_name) == True: if debug == True: print "0x%.8X => %s" % (function_address, function_name) count += 1 if debug == True: print "Renamed %d functions based on unqiue string xrefs!" % count return count
def activate(self, ctx): import json filepath = idc.AskFile(False, '*.zmu;*.overlay;*', 'Load Zemu Overlay...') if filepath is None: return f = open(filepath, 'r') zemu_data = f.read() f.close() zemu_data = zemu_data[len('DISAS\n'):] zemu_dump = json.loads(zemu_data) # Apply the overlay data for comment in zemu_dump['comments']: ea = comment['address'] comment_text = str(comment['text']) color = comment.get('color', 0x73f0df) # Set color of instruction line idaapi.set_item_color(ea, color) idaapi.set_cmt(ea, comment_text, False) # Set function name if not already changed idc.GetFunctionAttr(ea, idc.FUNCATTR_START) name = idc.GetFunctionName(ea) if len(name) > 0 and name.startswith('zmu_') == False: idc.MakeName(ea, 'zmu_' + name) return 1
def find_WdfDeviceCreateDeviceInterface(): function_offset = OFFSET_WdfDeviceCreateDeviceInterface calls_to_pfn_list = [] try: for xref in idautils.XrefsTo(g_vars["_WDFFUNCTIONS"]+function_offset): call_pfnWdfDeviceCreateDeviceInterface = xref.frm calls_to_pfn_list.append(call_pfnWdfDeviceCreateDeviceInterface) except StopIteration: # this is case 2 or 3 pass if len(calls_to_pfn_list) == 0: call_pfnWdfDeviceCreateDeviceInterface = find_wdf_callback_through_immediate("call", 0, function_offset) if call_pfnWdfDeviceCreateDeviceInterface: calls_to_pfn_list.append(call_pfnWdfDeviceCreateDeviceInterface) idc.OpStroffEx(call_pfnWdfDeviceCreateDeviceInterface,0,(idaapi.get_struc_id("_WDFFUNCTIONS")),0) if len(calls_to_pfn_list) == 0: call_pfnWdfDeviceCreateDeviceInterface = find_wdf_callback_through_immediate("mov", 1,function_offset) if call_pfnWdfDeviceCreateDeviceInterface: calls_to_pfn_list.append(call_pfnWdfDeviceCreateDeviceInterface) idc.OpStroffEx(call_pfnWdfDeviceCreateDeviceInterface,1,(idaapi.get_struc_id("_WDFFUNCTIONS")),0) for k, pfn_call in enumerate(calls_to_pfn_list): lea_guid = find_function_arg(pfn_call, "lea", "r8", 0) interface_guid = idc.GetOperandValue(lea_guid, 1) idc.MakeName(interface_guid, '_InterfaceGUID' + str(k)) assign_struct_to_address(interface_guid, "GUID") g_vars["_InterfaceGUID" + str(k)] = interface_guid print("_InterfaceGUID: ", hex(interface_guid)) guid_bytes = idc.GetManyBytes(interface_guid, 0x10) print_guid(guid_bytes)
def OnCommand(self, n, cmd): if cmd == self.show_all_toggle_cmd: if self.min_xrefs == self.MIN_XREFS: self.min_xrefs = 0 if self.min_xrefs != self.MIN_XREFS: self.min_xrefs = self.MIN_XREFS if self.must_have_loop == self.MUST_HAVE_LOOP: self.must_have_loop = False else: self.must_have_loop = self.MUST_HAVE_LOOP elif cmd == self.rename_cmd: if idc.AskYN( 0, "Are you sure you want to rename all 'sub_XXXXXX' functions to 'leaf_XXXXXX'?" ) == 1: for item in self.items: # Is this a leaf function? if item[-1] == True: current_name = item[0] if current_name.startswith('sub_'): new_name = current_name.replace('sub_', 'leaf_') idc.MakeName(idc.LocByName(current_name), new_name) self.populate_items() return 0
def remFuncChunks(): """ deletes all functions that have function chunks in them and appends "function_chunks_" to their names """ foundProblem = False for seg in idautils.Segments(): for ea in idautils.Functions(start=idc.SegStart(seg), end=idc.SegEnd(seg)): f = idaapi.get_func(ea) # chunk f if f.tailqty > 0: foundProblem = True print("Removing chunk function @ %07X" % f.startEA) idaapi.del_func(f.startEA) name = idc.Name(f.startEA) if "function_chunks_" not in name: newName = 'function_chunks_%s' % name print("Renaming %s -> %s" % ((name, newName))) idc.MakeName(f.startEA, newName) if foundProblem: print("Removed all function chunks!") else: print("No function chunks detected!")
def find_exported_eas(): """Find the address of all exported functions. Exported functions are entrypoints into this program that external code can execute.""" exported_eas = set() for index, ordinal, ea, name in idautils.Entries(): # Not sure how this happens, but IDA seemed to treat # `obstack_alloc_failed_handler` in `call cs:[obstack_alloc_failed_handler]` # as an entrypoint. num_data_refs = len(tuple(idautils.DataRefsTo(ea))) num_code_refs = len(tuple(idautils.CodeRefsTo(ea, True))) num_code_refs += len(tuple(idautils.CodeRefsTo(ea, True))) if num_data_refs and not num_code_refs: log.warning( "Ignoring entrypoint {:08x}, it's only referenced by data". format(ea)) continue if not has_segment_type(ea, idc.SEG_CODE): log.warning( "Ignoring entrypoint {:08x}, it is not in a code segment". format(ea)) continue if not idc.hasName(ea): old_name = name if name.startswith("."): name = idc.GetCommentEx(ea, 0) log.info("Renaming `{}` at {:08x} to `{}`".format( old_name, ea, name)) idc.MakeName(ea, name) return exported_eas
def setName(self, name): # type: (str) -> None """ Sets the name of the data item :param name: the string to rename the data item to """ idc.MakeName(self.ea, name)
def revise_syscall(rename=False): if not rename: print( 'Change the function name with `CGCHeler.revise_syscall(True)`.' ) # visit all instructions start_ea, end_ea = utils.get_seg_range('.text') eax = -1 ip = start_ea while ip < end_ea and ip != idaapi.BADADDR: if 'int' in idc.GetMnem(ip) and '80h' == idc.GetOpnd(ip, 0): if eax != -1: # fix comment and function name print('{}: {}'.format(hex(ip), syscall_table[eax])) idc.MakeComm(ip, 'CGC syscall: {}'.format(syscall_table[eax])) if rename: print('Change {} to {}'.format(idc.GetFunctionName(ip), syscall_table[eax])) idc.MakeName( idc.GetFunctionAttr(ip, idc.FUNCATTR_START), syscall_table[eax]) elif 'mov' in idc.GetMnem(ip) and 'eax' == idc.GetOpnd( ip, 0) and 5 == idc.GetOpType(ip, 1): value = idc.GetOpnd(ip, 1) if re.search('^[0-9]+$', value) != None: eax = int(value) if eax > 7 or eax < 1: eax = -1 ip = idc.NextHead(ip)
def updateIIDs(self, **kwargs): h = GuidHelper() inst = self.struct.instances() inst.update(self.struct2.instances()) busy = [] for x in inst: n = h.guidOfVals((inst[x]['Data1'], inst[x]['Data2'], inst[x]['Data3'], inst[x]['Data4'])) found = h.findGuid(n) if found: nm = found['name'] for c in " ,.:;-+<>/*": nm = nm.replace(c, '_') for c in nm: if ord(c) > 0x7F: nm = nm.replace(c, '_') if found['prefix'] and not nm.startswith(found['prefix']): nm = found['prefix'] + "_" + nm else: nm = "iid_" + str(n).replace('-', '_') rnm = nm if nm: if idc.Name(x).startswith(nm): busy += [nm] continue i = 2 while nm in busy and i < 10: nm = rnm + "__" + str(i) i += 1 while (idaapi.get_name_ea(idc.BADADDR, nm) != idc.BADADDR or not idc.MakeName(x, nm)) and i < 10: nm = rnm + "__" + str(i) i += 1 busy += [nm]
def visit_expr(self, i): """ From FLARE article Search for dw1234 = GetProcAddress("LoadLibrary") """ if i.op == idaapi.cot_call: # look for calls to GetProcAddress if idc.Name(i.x.obj_ea) == "GetProcAddress": # ASCSTR_C == 0 # Check to see if the second argument is a C string if idc.GetStringType(i.a[1].obj_ea) == 0: targetName = idc.GetString(i.a[1].obj_ea, -1, 0) # Found function name # Look for global assignment parent = self.cfunc.body.find_parent_of(i) if parent.op == idaapi.cot_cast: # Ignore casts and look for the parent parent = self.cfunc.body.find_parent_of(parent) if parent.op == idaapi.cot_asg: # We want to find the left hand side (x) self.results[targetName] = parent.cexpr.x.obj_ea idc.MakeName(parent.cexpr.x.obj_ea, targetName) return 0
def parse_function_tables(self): count = 0 for pattern in self.search(): name2func = {} ea = pattern.start while ea < pattern.stop: string_address = idc.Dword(ea + (pattern.name_element * pattern.element_size)) function_address = idc.Dword(ea + (pattern.function_element * pattern.element_size)) new_function_name = idc.GetString(string_address) current_function_name = idc.Name(function_address) if not self.valid_function_name(new_function_name): print "ERROR: '%s' is not a valid function name. This is likely not a function table, or I have parsed it incorrectly!" % new_function_name print " Ignoring all entries in the structures between 0x%X and 0x%X.\n" % ( pattern.start, pattern.stop) name2func = {} break elif current_function_name.startswith("sub_"): name2func[new_function_name] = function_address ea += (pattern.num_elements * pattern.element_size) for (name, address) in name2func.iteritems(): print "0x%.8X => %s" % (address, name) idc.MakeName(address, name) count += 1 print "Renamed %d functions!" % count
def run(self,arg): identified_func={} for func_ea in idautils.Functions(): #get the function name function_name=idc.GetFunctionName(func_ea) print function_name if not function_name.startswith("sub_"): continue func_byteStr32="" func_str=idc.GetManyBytes(func_ea, 32) for fb in func_str: byte_str=binascii.b2a_hex(fb) func_byteStr32+=byte_str print func_byteStr32 match_result=nampa.match_function(sig,func_byteStr32) print match_result if match_result[0]: function_names='' for function_name in match_result[1]: if len(function_names)==0: function_names=function_name continue function_names=function_names+"_"+function_name #set the function name num=0 print identified_func if identified_func.has_key(function_names): num=identified_func[function_names] num+=1 identified_func[function_names]=num else: identified_func[function_names]=num function_names=function_names+str(num) idc.MakeName(func_ea,function_names) warning("Ida plugin run(%d) called.\n"%arg)
def make_func(func, name): t_reg = func & 1 # 0 = ARM, 1 = THUMB func -= t_reg for i in range(4): idc.SetReg(func + i, "T", t_reg) idc.MakeFunction(func) if name: idc.MakeName(func, name)
def make_name(): """ Thread safe renaming wrapper """ return idaapi.execute_sync( idc.MakeName(name["address"], name["data"].encode('ascii', 'ignore')), idaapi.MFF_FAST)