def main(ea): # Get Function Bytes start = idc.GetFunctionAttr(ea, FUNCATTR_START) end = idc.GetFunctionAttr(ea, FUNCATTR_END) length = end - start code = "" for byte in idc.GetManyBytes(start, length): code += byte # Determine Architecture info = idaapi.get_inf_structure() proc = info.procName if info.is_64bit(): if proc == "metapc": md = Cs(CS_ARCH_X86, CS_MODE_64) elif proc == "ARM": md = Cs(CS_ARCH_ARM64, CS_MODE_ARM) elif info.is_32bit(): if proc == "metapc": md = Cs(CS_ARCH_X86, CS_MODE_32) elif proc == "ARM": md = Cs(CS_ARCH_ARM, CS_MODE_ARM) # If need change: CS_MODE_THUMB # Disassemble with Capstone and print for i in md.disasm(code, start): try: db = "" for ba in i.bytes: db += str("%X " %(ba)).rjust(3, "0") print("%x:\t%s\t%s\t%s" %(i.address, str(db).ljust(24, " "), i.mnemonic, i.op_str)) except Exception as e: print "Exception: {}".format(e)
def getRange(ea): '''tuple containing function start and end''' start, end = (idc.GetFunctionAttr(ea, idc.FUNCATTR_START), idc.GetFunctionAttr(ea, idc.FUNCATTR_END)) if (start == 0xffffffff) and (end == 0xffffffff): raise ValueError, 'address %x is not contained in a function' % ea return start, end
def FunctionAppendChunk(function_address, A, B_ex): # CAVEAT this function also adds successor hanging instructions! if idaapi.get_func(A) is not None: fn_print("0x%x-0x%x already in function" % (A, B_ex)) return False fn_print("append chunk 0x%x-0x%x to function 0x%x" % (A, B_ex, function_address)) # watch out with hanging instructions if (idaapi.get_func(A) is None) and (idaapi.get_func(idc.PrevHead(B_ex)) is not None): fn_print("chunk 0x%x-0x%x is part hanging, only moving hanging part" % (A, B_ex)) B_ex = A while idaapi.get_func(B_ex) is None: B_ex = idc.NextHead(B_ex) fn_print(" ... instead moving 0x%x-0x%x" % (A, B_ex)) result = idc.AppendFchunk(function_address, A, B_ex) if do_wait: idc.Wait() fn_print("append-chunk 0x%x-0x%x to 0x%x: %d" % (A, B_ex, function_address, result)) if result: now_address = idc.GetFunctionAttr(A, idc.FUNCATTR_START) f2 = idc.GetFunctionAttr(function_address, idc.FUNCATTR_START) assert f2 == now_address, "0x%x/0x%x/0x%x" % (function_address, now_address, f2) return result
def getMinorDispatchTableAddress(ea): """find address of last lea in function""" start = idc.GetFunctionAttr(ea, idc.FUNCATTR_START) end = idc.PrevHead(idc.GetFunctionAttr(ea, idc.FUNCATTR_END), start) res = prevMnemonic(end, 'lea', start) assert res != idc.BADADDR return idc.GetOperandValue(res, 1)
def main(self): for func in Functions(): if idc.SegName(func) == '__stubs': continue func_name = idc.GetFunctionName(func) print 'start parse ', func_name # if func_name != '-[JailbreakDetectionVC isJailbroken]': # continue self.cur_fun = func self.fun_start = idc.GetFunctionAttr(func, FUNCATTR_START) self.fun_end = idc.GetFunctionAttr(func, FUNCATTR_END) self.cur_fun_items = list(idautils.FuncItems(func)) regs = dict() regs['X0'] = self.getX0FromFuncName(func_name) regs['X1'] = 'Unknown' self._parse(regs, 0) self.conn.close()
def gen_skeleton_and_eas(reg): ea = idc.ScreenEA() start = idc.GetFunctionAttr(ea, idc.FUNCATTR_START) end = idc.GetFunctionAttr(ea, idc.FUNCATTR_END) ea = start eas = [] skeleton = {} while ea <= end: if idaapi.decode_insn(ea) == 0: print 'error in {0}'.format(GetDisasm(ea)) else: for opn in (0, 1): op = idaapi.cmd.Operands[opn] offset = 0 if op.type == idaapi.o_idpspec3: continue if op.type in (idaapi.o_phrase, idaapi.o_displ) and op.phrase == phrase[reg]: skeleton[op.addr] = ('field_{0}'.format(hex(op.addr)), dtyp[op.dtyp]) eas.append((ea, opn, offset)) ea = idc.NextHead(ea) skeleton = [(elem[0], elem[1][0], elem[1][1]) for elem in sorted(skeleton.items(), key=lambda x: x[0])] return [skeleton, eas]
def AuditApiCall(funcname, auditfunc): print funcname func = idc.LocByName(funcname) print funcname + " func addr " print hex(func) count = 0 if(func != BADADDR): for xref in idautils.XrefsTo(func,0): print xref.type,idautils.XrefTypeName(xref.type) print 'from',hex(xref.frm) print 'to',hex(xref.to) ####audit func##### ####not from an const#### func_start = idc.GetFunctionAttr(xref.frm, idc.FUNCATTR_START) func_end = idc.GetFunctionAttr(xref.frm, idc.FUNCATTR_END) local_size = idc.GetFunctionAttr(xref.frm, idc.FUNCATTR_FRSIZE) ###Data offset eg: lis r10, VOS_sprintf@h ### addi r10, r10, VOS_sprintf@l if(xref.type == 1): print "disass is "+idc.GetDisasm(xref.frm) if("add" in idc.GetDisasm(xref.frm)): caller = TraceApiCall(xref.frm) auditfunc(caller) break else: caller= xref.frm
def build_stack_args(f): stackArgs = dict() name = idc.Name(f) end = idc.GetFunctionAttr(f, idc.FUNCATTR_END) _locals = idc.GetFunctionAttr(f, idc.FUNCATTR_FRSIZE) _uses_bp = 0 != (idc.GetFunctionFlags(f) & idc.FUNC_FRAME) frame = idc.GetFrame(f) if frame is None: return stackArgs func_type = idc.GetType(f) if (func_type is not None) and ("(" in func_type): args = func_type[ func_type.index('(')+1: func_type.rindex(')') ] args_list = [ x.strip() for x in args.split(',')] if "..." in args_list: return stackArgs if name in RECOVER_DEBUG_FL: return stackArgs #grab the offset of the stored frame pointer, so that #we can correlate offsets correctly in referent code # e.g., EBP+(-0x4) will match up to the -0x4 offset delta = idc.GetMemberOffset(frame, " s") if -1 == delta: #indicates that it wasn't found. Unsure exactly what to do # in that case, punting for now delta = 0 offset = idc.GetFirstMember(frame) while -1 != _signed_from_unsigned(offset): memberName = idc.GetMemberName(frame, offset) if memberName is None: # gaps in stack usage are fine, but generate trash output # gaps also could indicate a buffer that IDA doesn't recognize offset = idc.GetStrucNextOff(frame, offset) continue if (memberName == " r" or memberName == " s"): #the return pointer and start pointer, who cares offset = idc.GetStrucNextOff(frame, offset) continue memberSize = idc.GetMemberSize(frame, offset) if offset >= delta: offset = idc.GetStrucNextOff(frame, offset) continue memberFlag = idc.GetMemberFlag(frame, offset) #TODO: handle the case where a struct is encountered (FF_STRU flag) flag_str = _get_flags_from_bits(memberFlag) stackArgs[offset-delta] = {"name":memberName, "size":memberSize, "flags":flag_str, "writes":list(), "referent":list(), "reads":list(), "safe": False} offset = idc.GetStrucNextOff(frame, offset) return stackArgs
def get_function(ea): func = idaapi.func_t() func.startEA = idc.GetFunctionAttr(ea, idc.FUNCATTR_START) func.endEA = idc.GetFunctionAttr(ea, idc.FUNCATTR_END) func.flags = idc.GetFunctionAttr(ea, idc.FUNCATTR_FLAGS) if idc.BADADDR == func.startEA or idc.BADADDR == func.endEA: return False else: return func
def get_non_sub_functions(): """ """ ret = [] for f in idautils.Functions(): name = idc.GetFunctionName(f) if not name.startswith("sub_") and not name.startswith("unknown"): ret.append( (idc.GetFunctionAttr(f, 0), idc.GetFunctionAttr(f, 4), name)) return ret
def analyze_invoke2(funcaddr): #print('funcaddr : %08X - %s' % (funcaddr, GetFunctionName(funcaddr))) func_st = idc.GetFunctionAttr(funcaddr, idc.FUNCATTR_START) func_en = idc.GetFunctionAttr(funcaddr, idc.FUNCATTR_END) funcname = idc.GetFunctionName(func_st) addr = func_st state = 0 if not funcname.startswith('sub_'): return while addr < func_en: mnem = idc.GetMnem(addr) #print(' %08X: %s' % (addr, mnem)) if mnem == 'lea': oprand1 = idc.GetOpnd(addr, 1) match = name_re.match(oprand1) #print(' %s' % (oprand1)) if match is not None: #print(' %s' % (match.group(1))) strname = match.group(1) nameaddr = idc.LocByName(strname) if strname.startswith('off'): idc.MakeStr(nameaddr, idc.BADADDR) name = idc.GetString(nameaddr, -1, idc.ASCSTR_C) #print(' opaddr: %X' % addr) #print(' strname: %s' % strname) #print(' nameaddr: %X' % nameaddr) #print(' name: %s' % name) if state == 0: libname = name state = 1 else: name = method_re.match(name).group(0) #print(' %X: %s @%s' % (func_st, name, libname)) idc.MakeNameEx(func_st, name, idc.SN_NOWARN | idc.SN_AUTO) break addr = idc.NextHead(addr, func_en) if addr == idc.BADADDR: break
def get_current_function_range(self, current_ea): current_function_begin = idaapi.BADADDR current_function_end = idaapi.BADADDR for functionAddr in idautils.Functions(): function_begin = idc.GetFunctionAttr(functionAddr, idc.FUNCATTR_START) function_end = idc.GetFunctionAttr(functionAddr, idc.FUNCATTR_END) if function_begin <= current_ea and function_end >= current_ea: current_function_begin = function_begin current_function_end = function_end break return current_function_begin, current_function_end
def hasCookie(self): end = idc.GetFunctionAttr(self.addr, idc.FUNCATTR_END) start = idc.GetFunctionAttr(self.addr, idc.FUNCATTR_START) count = 0 while ((start != end) and (start != idc.BADADDR)): line = idc.GetDisasm(start) if line.startswith('xor'): if 'ebp' in line: return True start = idc.NextAddr(start) count += 1 # security cookie check is usually at beginning of function (unless some crazy-ass prologue) if (count > 20): return False return False
def getCallGraph(): callGraph = nx.DiGraph() for func_addr in idautils.Functions(MinEA(), MaxEA()): #print func_addr #coderefler bulunur ve hepsi grapha eklenir fn = idc.GetFunctionName(func_addr) #print "for function ",fn, " caller functions listed below:" i = 0 callers = idautils.CodeRefsTo(func_addr, 1) #avoid if there is no caller if (len(callers) == 0): #print "empty set!" continue callGraph.add_node(func_addr, name=fn) for caller_addr in callers: cn = idc.GetFunctionName(caller_addr) #print i,".caller is ",cn, " address: 0x %x" %caller_addr i += 1 #avoid circle if (fn == cn): print fn continue cf_addr = idc.GetFunctionAttr(caller_addr, FUNCATTR_START) if cf_addr is None: #print "none function -> 0x%x"%caller_addr continue if not (cf_addr in callGraph): callGraph.add_node(cf_addr, name=cn) callGraph.add_edge(cf_addr, func_addr) return callGraph
def GetDataXrefString(ea): name = idc.GetFunctionName(ea) ea = idc.LocByName(name) f_start = ea f_end = idc.GetFunctionAttr(ea, idc.FUNCATTR_END) ret = [] for chunk in idautils.Chunks(ea): astart = chunk[0] aend = chunk[1] for head in idautils.Heads(astart, aend): # If the element is an instruction if idc.isCode(idc.GetFlags(head)): refs = list(idautils.DataRefsFrom(head)) for ref in refs: s = idc.GetString(ref, -1, idc.ASCSTR_C) if not s or len(s) <= 4: s = idc.GetString(ref, -1, idc.ASCSTR_UNICODE) if s: if len(s) > 4: ret.append(repr(s)) if len(ret) > 0: return "\n\n" + "\n".join(ret) else: return ""
def TraceApiCall(code): print "operand 0 is "+idc.GetOpnd(code,0) print "operand 1 is "+idc.GetOpnd(code,1) print "operand 2 is "+idc.GetOpnd(code,2) reg = idc.GetOpnd(code,0) ### search down to find caller it cannt deal with such situation: ### addi r10, r10, VOS_sprintf@l ### b addr ### in the above code, the trace should follow addr to find the right call ### func_end = idc.GetFunctionAttr(code, idc.FUNCATTR_END) instruct = "mtlr "+reg while(code < func_end): code = idc.FindCode(code, SEARCH_DOWN|SEARCH_NEXT) ### search "mtlr r10" if(("mtlr"==idc.GetMnem(code)) and (idc.GetOpnd(code,1) == reg)): print idc.GetOpnd(code,1) print "Get the instruct! "+ idc.GetDisasm(code) while(code < func_end): code = idc.FindCode(code, SEARCH_DOWN|SEARCH_NEXT) if("blrl" in idc.GetDisasm(code)): print "api call " + idc.GetDisasm(code)+" from ",hex(code) print "mnem "+idc.GetMnem(code) return code
def funXrefs(self): res = {} for s in idautils.Strings(): s_ea = s.ea s_v = str(s).rstrip() dprint("checking %x - %s" % (s_ea, s_v)) s_xrefs_eas = self.xrefsTo(s_ea) if not s_xrefs_eas: dprint("no xref found for %s" % (s_v)) s_xrefs_eas = [s_ea] # same string can be xref'ed by more than one function for fs_ea in s_xrefs_eas: dprint("looking for function of %x" % (fs_ea)) f_name = idc.GetFunctionName(fs_ea) f_ea = idc.GetFunctionAttr(fs_ea, idc.FUNCATTR_START) if not f_name or f_name == '': f_name = NO_FUNC if f_ea in res: res[f_ea]['strings'][s_v] = IdaString(s_v, s_ea, fs_ea) else: res[f_ea] = dict({ 'name': f_name, 'strings': { s_v: IdaString(s_v, s_ea, fs_ea) } }) return res
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 HandleFunc(func): global g_off_set_random global g_size_ins_block #for ins in idautils.FuncItems(start): # print(idc.GetDisasm(ins)) ea = func end = idc.GetFunctionAttr(func, idc.FUNCATTR_END) for ea in idautils.Heads(func, end): if IsInstrumentIns(ea): #print(idc.GetFunctionName(start)) #print(hex(ea), idc.GetDisasm(ea)) #idc.SetColor(ea+0x13, CIC_ITEM, 0x0000FF) #bbls = GetFunBbls(func) bbl_heads = () #for bbl in bbls: #bbl_heads.append(bbl[0]) write_head = [0] call_stack = [] #FindChildNode(func, ea+g_off_set_random, ea+g_size_ins_block, call_stack, 0) FindChildNode2(func, bbl_heads, ea + g_off_set_random, ea + g_size_ins_block, call_stack, 0, write_head) #ea += g_size_ins_block pass
def extractCode(): printAvd() start = idc.SelStart() end = idc.SelEnd() codeSize = end - start ea = start #print hex(ea) result="" for i in range(codeSize): op1 = idc.GetOpType(ea,0) op2 = idc.GetOpType(ea,1) instructionSize=idc.ItemSize(ea) if op1 == idc.o_reg and (op2 ==idc.o_reg or op2 == idc.o_void or op2 == idc.o_phrase): for b in range(0,instructionSize): result += formatByte(ea+b) elif (op1 == idc.o_reg and op2 == idc.o_displ) or (op1 == idc.o_displ and op2 == idc.o_reg) or (op1 == idc.o_displ and op2 == idc.o_imm): result += formatByte(ea) + formatByte(ea+1) for b in range(2,instructionSize): result=result+"*" elif op1 == idc.o_phrase and op2 == idc.o_reg: for b in range(0,instructionSize): result+=formatByte(ea+b) else: result+=calcStr(ea,instructionSize) ea = ea + instructionSize if ea >= (start + codeSize): break print ("%s Offset:%s") % (idc.GetFunctionName(start),hex(start - idc.GetFunctionAttr(start,0))) print result return result
def get_user_functions(): user_functions = [] for fva in idautils.Functions(): f_attr = idc.GetFunctionAttr(fva, idc.FUNCATTR_FLAGS) if not f_attr & idc.FUNC_LIB and not f_attr & idc.FUNC_THUNK: user_functions.append(fva) return user_functions
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 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 get_f5_comments(self): cmts = [] for seg in idautils.Segments(): ea = idc.SegStart(seg) if idc.GetSegmentAttr(ea, idc.SEGATTR_TYPE) != idaapi.SEG_CODE: continue seg_name = idc.SegName(seg) end = idc.SegEnd(seg) while ea < end: if ea != idc.BADADDR and idc.GetFunctionFlags( ea) != 0xffffffff: try: cfunc = idaapi.decompile(ea) for tl, citem in cfunc.user_cmts.items(): current_cmt = [ "%s:%-16X" % (seg_name, tl.ea), 'F5', idc.GetDisasm(tl.ea), citem.c_str() ] # F5 comments cmts.append(current_cmt) self.n += 1 except idaapi.DecompilationFailure: pass finally: ea = idc.GetFunctionAttr(ea, idc.FUNCATTR_END) else: ea = idc.next_head(ea, end) return cmts
def DeepSearch(self, function_name, line, max_deep, current_deep=0): data = {} opcode_offset = 0 function_start = idc.LocByName(function_name) function_end = idc.GetFunctionAttr(function_start, idc.FUNCATTR_END) while function_start + opcode_offset < function_end: opcode_index = function_start + opcode_offset dline = idc.GetDisasm(opcode_index) if idc.GetMnem(opcode_index) == "call": if current_deep >= max_deep: return elif idc.GetOpnd(opcode_index, 0)[:4] == "sub_": deep = self.DeepSearchWithRgx(idc.GetOpnd(opcode_index, 0), line, max_deep, current_deep + 1) if deep: data.update(deep) if dline == line: data["%x" % opcode_index] = dline opcode_offset += idc.ItemSize(opcode_index) return data
def __get_functions(self): functions = list(idautils.Functions()) for start_function in functions: tinfo = idc.GetTinfo(start_function) if tinfo is None: continue mangled_name = idc.GetFunctionName(start_function) demangled = {idc.INF_SHORT_DN: '', idc.INF_LONG_DN: ''} for record in demangled.iteritems(): (type, value) = record demangled[type] = idc.Demangle(mangled_name, idc.GetLongPrm(type)) ida_type, ida_fields = tinfo yield models_ida.IdaRawFunctions( start=start_function, end=idc.GetFunctionAttr(start_function, idc.FUNCATTR_END), ida_type=ida_type, ida_fields=ida_fields, mangled_name=mangled_name, short_name=demangled[idc.INF_SHORT_DN], long_name=demangled[idc.INF_LONG_DN])
def recover_variables(F, func_ea, blockset): """ Recover the stack variables from the function. It also collect the instructions referring to the stack variables. """ # Checks for the stack frame; return if it is None if not is_code_by_flags(func_ea) or \ not idc.GetFrame(func_ea): return functions = list() f_name = get_symbol_name(func_ea) f_ea = idc.GetFunctionAttr(func_ea, idc.FUNCATTR_START) f_vars = collect_function_vars(func_ea, blockset) functions.append({"ea": f_ea, "name": f_name, "stackArgs": f_vars}) for offset in f_vars.keys(): if f_vars[offset]["safe"] is False: continue var = F.stack_vars.add() var.sp_offset = offset var.name = f_vars[offset]["name"] var.size = f_vars[offset]["size"] for i in f_vars[offset]["writes"]: r = var.ref_eas.add() r.inst_ea = i["ea"] r.offset = i["offset"] for i in f_vars[offset]["reads"]: r = var.ref_eas.add() r.inst_ea = i["ea"] r.offset = i["offset"]
def iter_fn(self, startAddr): """ Generator function designed to walk all instructions within a function, parse and yield them. """ endAddr = idc.GetFunctionAttr(startAddr, idc.FUNCATTR_END) for head in idautils.Heads(startAddr, endAddr): yield head, idc.GetDisasm(head).split()[0], idc.GetOpnd(head, 0), idc.GetOpnd(head, 1)
def _get_user_selected_functions(self, many=False): functions = [] ea = idc.ScreenEA() try: current_function = idc.GetFunctionAttr(ea, idc.FUNCATTR_START) except: current_function = None while True: function = idc.ChooseFunction( "Select a function and click 'OK' until all functions have been selected. When finished, click 'Cancel' to display the graph." ) # ChooseFunction automatically jumps to the selected function # if the enter key is pressed instead of clicking 'OK'. Annoying. if idc.ScreenEA() != ea: idc.Jump(ea) if not function or function == idc.BADADDR or function == current_function: break elif function not in functions: functions.append(function) if not many: break return functions
def activate(self, ctx): hx_view = idaapi.get_tform_vdui(ctx.form) address = hx_view.cfunc.entry_ea xref_ea = idaapi.get_first_cref_to(address) xrefs = set() while xref_ea != idaapi.BADADDR: xref_func_ea = idc.GetFunctionAttr(xref_ea, idc.FUNCATTR_START) if xref_func_ea != idaapi.BADADDR: xrefs.add(xref_func_ea) else: print "[Warning] Function not found at 0x{0:08X}".format(xref_ea) xref_ea = idaapi.get_next_cref_to(address, xref_ea) for func_ea in xrefs: visitor = VariableLookupVisitor(address) try: cfunc = idaapi.decompile(func_ea) if cfunc: FunctionTouchVisitor(cfunc).process() visitor.apply_to(cfunc.body, None) for idx in visitor.result: scanner = DeepSearchVisitor(cfunc, 0, idx) scanner.process() for field in scanner.candidates: self.temporary_structure.add_row(field) except idaapi.DecompilationFailure: print "[Warning] Failed to decompile function at 0x{0:08X}".format(xref_ea) DeepSearchVisitor.clear()