def activate(self, ctx): self.file_id = netnode.bound_file_id self.function_gen = enumerate(Functions()) pd = QtWidgets.QProgressDialog(labelText="Processing functions...", minimum=0, maximum=len(list(Functions()))) self.progress = pd self.progress.canceled.connect(self.cancel) self.timer = QtCore.QTimer() self.timer.timeout.connect(self.perform) self.timer.start()
def main(): idaapi.auto_wait() base = idaapi.get_imagebase() tif = idaapi.tinfo_t() f = open(os.environ.get("DESTPATH", "functype_"), 'w') for ea in Segments(): # only code segment if idaapi.segtype(ea) != idaapi.SEG_CODE: continue for fva in Functions(get_segm_start(ea), get_segm_end(ea)): func_name = get_func_name(fva) has_type = idaapi.get_tinfo(tif, fva) or idaapi.guess_tinfo( tif, fva) if not has_type: continue info = serialize(tif) if info is None: continue print( hex(fva - base)[:-1], "|", func_name, "|", tif, "|", len(info['args'])) f.write("0x%x|%s|%s\n" % (fva - base, func_name, json.dumps(info))) f.close() idaapi.qexit(0)
def _fill_functions(self): """Fill the ``functions`` dict.""" functions = self.functions for ea in Functions(): if GetFunctionName(ea).startswith('_ZThn'): continue functions[ea] = Function(self, ea)
def getFuncEALike(funcName): found = False for ea in Functions(): iterFuncName = GetFunctionName(ea) if iterFuncName.find(funcName) != -1: print('0x{:x}'.format(ea), iterFuncName) found = True if not found: print('not found')
def _listFunctionsAddr(self) -> List[int]: """Lists all the starting addresses of the functions using IDA API. """ fn_list = list() for func in Functions(): start = get_func_attr(func, FUNCATTR_START) fn_list.append(start) return fn_list
def update_protocols(): for n in range(get_segm_qty()): seg = getnseg(n) if seg.type == SEG_CODE or get_segm_name(seg.start_ea) == ".code": seg_beg = seg.start_ea seg_end = seg.end_ea for function in map(lambda x: Function(x), Functions(seg_beg, seg_end)): _process_function(function) return protocols
def findPatchString(config): patchStringByteArray = [] for funcAddr in Functions(): if GetFunctionName(funcAddr) == config['srcFnName']: print('found ea for ' + config['name']) break for byteIndex in xrange(0, config['patchLength']): func_byte_char = GetManyBytes(funcAddr + config['offset'] + byteIndex, 1) if func_byte_char is not None: patchStringByteArray.append('{:02x}'.format(ord(func_byte_char))) PATCH_STRING = ' '.join(patchStringByteArray) print('patch found for ' + config['name'] + ' >> ' + PATCH_STRING) return PATCH_STRING
def resolve_functions(save_path): # get executable range executable_ranges = [] text_range = get_section_range('.text') if text_range[0] == idc.BADADDR: # no '.text' executable_ranges = get_executable_range() else: executable_ranges.append(text_range) funcs = Functions() all_func_start_addr = [f for f in funcs if is_func_in_section(f, executable_ranges)] json.dump(all_func_start_addr, open(save_path, 'w'))
def activate(self, ctx) -> int: """Collects types, user-defined variables, their locations in addition to the AST and raw code. """ print("Collecting vars and types.") for ea in (ea for ea in Functions() if ea in self.debug_functions): # Decompile f = ida.get_func(ea) cfunc = None try: cfunc = ida.decompile(f) except ida.DecompilationFailure: continue if cfunc is None: continue # Function info name: str = ida.get_func_name(ea) self.type_lib.add_ida_type(cfunc.type.get_rettype()) return_type = TypeLib.parse_ida_type(cfunc.type.get_rettype()) arguments = self.collect_variables(f.frsize, cfunc.get_stkoff_delta(), cfunc.arguments) local_vars = self.collect_variables( f.frsize, cfunc.get_stkoff_delta(), [v for v in cfunc.get_lvars() if not v.is_arg_var], ) raw_code = "" for line in cfunc.get_pseudocode(): raw_code += f"{' '.join(tag_remove(line.line).split())}\n" ast = AST(function=cfunc) decompiler = Function( ast=ast, name=name, return_type=return_type, arguments=arguments, local_vars=local_vars, raw_code=raw_code, ) self.functions.append( CollectedFunction( ea=ea, debug=self.debug_functions[ea], decompiler=decompiler, )) self.write_info() return 1
def findFuncBinary(self, funcName, funcBinary): for funcAddr in Functions(): if GetFunctionName(funcAddr) == funcName: self.ea = funcAddr break if self.ea is None: return self self.endEa = GetFunctionAttr(self.ea, FUNCATTR_END) if len(funcBinary) > 0: self.ea = FindBinary(self.ea, SEARCH_DOWN | SEARCH_NOSHOW, funcBinary, 16) # print('{:x} {:x} {:x}'.format(self.ea, binaryEA, self.ea + binaryEA)) if self.ea > self.endEa: self.ea = None return self
def find_chain_helper(chain, cfg_whitelist, startaddress, depth): xrefs = set() for xref in XrefsTo(startaddress, 0): for f in Functions(xref.frm, xref.frm): xrefs.add(f) for xref in xrefs: if xref in cfg_whitelist: newchain = chain[:] newchain.append(maybe_get_name(xref)) print_chain(newchain) if depth <= 1: return for xref in xrefs: newchain = chain[:] newchain.append(maybe_get_name(xref)) find_chain_helper(newchain, cfg_whitelist, xref, depth - 1)
def _loadLocals(self) -> None: """Enumerates functions using IDA API and loads them into the internal mapping. """ self._loadImports() for func in Functions(): start = get_func_attr(func, FUNCATTR_START) end = prev_addr(get_func_attr(func, FUNCATTR_END)) is_import = self._isImportStart(start) refs_list = self._listRefsTo(start) calling_list = self._listRefsFrom(func, start, end) func_info = FunctionInfo_t(start, end, refs_list, calling_list, is_import) self._functionsMap[va_to_rva(start)] = func_info self._functionsMap[va_to_rva(end)] = func_info self.funcList.append(func_info)
def dump_symbol_info(output_filename): """Dump information for BAP's symbolizer into output_filename.""" from idautils import Segments, Functions from idc import ( SegStart, SegEnd, GetFunctionAttr, FUNCATTR_START, FUNCATTR_END ) try: from idaapi import get_func_name2 as get_func_name # Since get_func_name is deprecated (at least from IDA 6.9) except ImportError: from idaapi import get_func_name # Older versions of IDA don't have get_func_name2 # so we just use the older name get_func_name def func_name_propagate_thunk(ea): current_name = get_func_name(ea) if current_name[0].isalpha(): return current_name func = idaapi.get_func(ea) temp_ptr = idaapi.ea_pointer() ea_new = idaapi.BADADDR if func.flags & idaapi.FUNC_THUNK == idaapi.FUNC_THUNK: ea_new = idaapi.calc_thunk_func_target(func, temp_ptr.cast()) if ea_new != idaapi.BADADDR: ea = ea_new propagated_name = get_func_name(ea) or '' # Ensure it is not `None` if len(current_name) > len(propagated_name) > 0: return propagated_name else: return current_name # Fallback to non-propagated name for weird times that IDA gives # a 0 length name, or finds a longer import name idaapi.autoWait() with open(output_filename, 'w+') as out: for ea in Segments(): fs = Functions(SegStart(ea), SegEnd(ea)) for f in fs: out.write('("%s" 0x%x 0x%x)\n' % ( func_name_propagate_thunk(f), GetFunctionAttr(f, FUNCATTR_START), GetFunctionAttr(f, FUNCATTR_END)))
def extract(self): """Extract the control flow graph from the binary.""" # Allocate a new graph self.graph = graph_alloc(0) # Initialize binary info self.info = get_inf_structure() # Initialize Capstone if self.info.is_64bit(): mode = capstone.CS_MODE_64 else: mode = capstone.CS_MODE_32 self.capstone = capstone.Cs(capstone.CS_ARCH_X86, mode) # Get the Entry Point entry = None try: start_ea = self.info.start_ea if start_ea != 0xffffffff: entry = start_ea except: try: entry = BeginEA() except: pass if entry is None: print("WARNING: Could not determine entrypoint") else: self.dis(ea=entry, is_child1=None, ifrom=None) # Scan all the functions for ea in Functions(): self.dis(ea=ea, is_child1=None, ifrom=None) update_children_fathers_number(self.graph) # Information print("%s graph has %d nodes" % (get_root_filename(), self.graph.nodes.size))
def __export_functions__(self): # Loop from start to end in the current segment for funcea in Functions(): func = get_func(funcea) cconv = guess_calling_conv(func) if cconv == CCONV_INVALID: print "Skiping function 0x%.8x, it has no clear start basic block" % func.startEA continue self.fd.write( "F;0x%x;0x%x;0x%x;%s\n" % (func.startEA - self.image_base, func.endEA - self.image_base, cconv, GetAddressName(func.startEA))) # Export all the basic blocks for block in idaapi.FlowChart(func): self.fd.write( "B;0x%x;0x%x;0x%x;0x%x\n" % (func.startEA - self.image_base, block.startEA - self.image_base, block.endEA - self.image_base, block.id))
def _saveFunctionsNames(self, file_name: Optional[str], ext: str) -> bool: """Saves functions names and offsets from the internal mappings into a file. Fromats: CSV (default), or TAG (PE-bear, PE-sieve compatibile). """ if file_name is None or len(file_name) == 0: return False delim = "," if ".tag" in ext: # a TAG format was chosen delim = ";" fn_list = list() for func in Functions(): start = get_func_attr(func, FUNCATTR_START) func_name = _getFunctionNameAt(start) start_rva = va_to_rva(start) line = "%lx%c%s" % (start_rva, delim, func_name) fn_list.append(line) idaapi.msg(str(file_name)) with open(file_name, 'w') as f: for item in fn_list: f.write("%s\n" % item) return True return False
from idautils import Segments, Functions, XrefsTo from idc import GetFunctionName, SegName, get_type from sys import exit current_function = GetFunctionName(get_screen_ea()) print('Will generate forwards for all calls from {}'.format(current_function)) called_functions = [] function_name_to_address = {} for segea in Segments(): if SegName(segea) != '.text': continue for funcea in Functions(segea, SegEnd(segea)): called_functions.extend( filter(lambda x: GetFunctionName(x.frm) == current_function, XrefsTo(funcea))) function_name_to_address[GetFunctionName(funcea)] = funcea called_functions = map(lambda x: GetFunctionName(x.to), called_functions) called_functions = list(set(called_functions)) print('It calls {} functions!'.format(len(called_functions))) def forwarder_generator(prototype, address): until_arguments = prototype[:prototype.find('(')].split(' ') arguments = prototype[prototype.find('(') + 1:-1] pointer_levels = ''
def getFuncEA(funcName): for ea in Functions(): iterFuncName = GetFunctionName(ea) if iterFuncName == funcName: return ea print('{} not found'.format(funcName))
def function_at(ea: int) -> Optional[int]: start = ea functions = Functions(start) for func in functions: return func return None