def make_head(ea): flags = idc.GetFlags(ea) if not idc.isHead(flags): idc.SetFlags(ea, flags | idc.FF_DATA) idaapi.autoWait() return is_head(ea) return True
def try_mark_as_function(ea): if not idc.MakeFunction(ea, idc.BADADDR): idc.MakeUnknown(ea, 1, idc.DOUNK_SIMPLE) idaapi.autoWait() if not idc.MakeFunction(ea, idc.BADADDR): debug("Unable to convert code to function:", hex(ea)) return False idaapi.autoWait() return True
def __init__(self): """Constructor for SPIDA. Waits for IDA Pro to finish analyzing the .exe, then builds a dictionary mapping EA's to imported APIs' names""" idaapi.autoWait() self.import_dict = dict() self.curr_mod_name = "" self.firstImport = True self.imports_segment_name = "" self.buildImportDictionary() self.makeMissedProcedures()
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 dump_loader_info(output_filename): """Dump information for BAP's loader into output_filename.""" from idautils import Segments import idc idaapi.autoWait() with open(output_filename, 'w+') as out: info = idaapi.get_inf_structure() size = "r32" if info.is_32bit else "r64" out.write("(%s %s (" % (info.get_proc_name()[1], size)) for seg in Segments(): out.write("\n(%s %s %d (0x%X %d))" % ( idaapi.get_segm_name(seg), "code" if idaapi.segtype(seg) == idaapi.SEG_CODE else "data", idaapi.get_fileregion_offset(seg), seg, idaapi.getseg(seg).size())) out.write("))\n")
def try_mark_as_code(address, end_address=0): flags = idc.GetFlags(address) if idc.isAlign(flags): return False if idc.isCode(flags): return True if idc.MakeCode(address): idaapi.autoWait() return True end_address = max(end_address, address + 1) idc.MakeUnknown(address, end_address - address + 1, idc.DOUNK_SIMPLE) if idc.MakeCode(address): idaapi.autoWait() return True return False
def dump_brancher_info(output_filename): """Dump information for BAP's brancher into output_filename.""" from idautils import CodeRefsFrom idaapi.autoWait() def dest(ea, flow): # flow denotes whether normal flow is also taken return set(CodeRefsFrom(ea, flow)) def pp(l): return ' '.join('0x%x' % e for e in l) with open(output_filename, 'w+') as out: for ea in all_valid_ea(): branch_dests = dest(ea, False) if len(branch_dests) > 0: out.write('(0x%x (%s) (%s))\n' % ( ea, pp(dest(ea, True) - branch_dests), pp(branch_dests) ))
def dump_brancher_info(output_filename): """Dump information for BAP's brancher into output_filename.""" from idautils import CodeRefsFrom idaapi.autoWait() def dest(ea): return list(CodeRefsFrom(ea, flow=True)) def branch(ea): return list(CodeRefsFrom(ea, flow=False)) def fall(ea): return list(set(dest(ea)) - set(branch(ea))) def is_branch_insn(ea): # Unconditional branches are also counted return len(branch(ea)) > 0 def is_jump_insn(ea): # Only unconditional branches return len(branch(ea)) == len(dest(ea)) == 1 def labeled(addrs, label): l = lambda d: '(0x%x %s)' % (d, label) return ' '.join(map(l, addrs)) with open(output_filename, 'w+') as out: out.write('(\n') for ea in all_valid_ea(): if is_jump_insn(ea): out.write('(0x%x (%s))\n' % ( ea, labeled(dest(ea), 'Jump'))) elif is_branch_insn(ea): out.write('(0x%x (%s %s))\n' % ( ea, labeled(branch(ea), 'Cond'), labeled(fall(ea), 'Fall'))) else: pass # Normal instruction, uninteresting out.write(')\n')
def init_analysis(): analysis_flags = idc.GetShortPrm(idc.INF_START_AF) analysis_flags &= ~idc.AF_IMMOFF idc.SetShortPrm(idc.INF_START_AF, analysis_flags) idaapi.autoWait()
def wait(cls): '''Wait until IDA's autoanalysis queues are empty.''' return idaapi.autoWait( ) if idaapi.__version__ < 7.0 else idaapi.auto_wait()
def wait_for_analysis_to_finish(self): logger.debug("[+] waiting for analysis to finish...") idaapi.autoWait() idc.Wait() logger.debug("[+] analysis finished.")
def try_mark_as_code(ea): if is_code(ea) and not is_code_by_flags(ea): idc.MakeCode(ea) idaapi.autoWait() return True return False
def main(): imp_funcs = [] xrefs = [] cg = CallGraph() file_name = idc.get_root_filename() file_path = idc.GetInputFilePath() def get_file_ssdeep(): if 'ssdeep' in sys.modules: return ssdeep.hash_from_file(file_path) else: return 'No ssdeep Modules. Please Install ssdeep.' def imp_cb(ea, name, ord): imp_funcs.append(ea) return True if 'batch' in idc.ARGV: idaapi.autoWait() for fea in Functions(): func_flags = get_func_flags(fea) # NORMAL = 0 # LIBRARY = 1 # IMPORTED = 2 # THUNK = 3 if func_flags & FUNC_LIB: func_type = 1 elif func_flags & FUNC_THUNK: func_type = 3 else: func_type = 0 cg.add_vertex(fea, func_type) cg.add_root(fea) items = FuncItems(fea) for item in items: for xref in XrefsFrom(item, 0): # https://www.hex-rays.com/products/ida/support/idadoc/313.shtml if xref.type != fl_F: xrefs.append([fea, xref.to]) # List Import Functions and Add to cg num_imp_module = idaapi.get_import_module_qty() for i in range(0, num_imp_module): idaapi.enum_import_names(i, imp_cb) imp_funcs.sort() for imp_func_ea in imp_funcs: cg.add_vertex(imp_func_ea, 2) for xref in xrefs: if xref[1] in cg.vertices: cg.connect_vertex(xref[0], xref[1]) cg.set_roots() for root in cg.roots: cg.build_graph_pattern(root) if len(idc.ARGV) == 0: print('Graph MD5: %s' % cg.get_graph_md5()) print('Graph SHA1: %s' % cg.get_graph_sha1()) print('Graph SHA256: %s' % cg.get_graph_sha256()) print('Graph SSDEEP: %s' % cg.get_graph_ssdeep()) print('File SSDEEP: %s' % get_file_ssdeep()) if 'out_pattern' in idc.ARGV: if not os.path.isdir('./out'): os.mkdir('./out') f = open('./out/' + file_name + '.bin', 'wb') f.write(cg.graph_pattern) f.close() if 'batch' in idc.ARGV: if not os.path.isdir('./out'): os.mkdir('./out') f = open('./out/result', 'a+') f.write('%s,%s,%s,%s\n' % (file_name, cg.get_graph_md5(), cg.get_graph_ssdeep(), get_file_ssdeep())) f.close() idc.Exit(0)
print('Vars collected.') return 1 class dump_info(custom_action_handler): def activate(self, ctx): with open(os.environ['COLLECTED_VARS'], 'wb') as vars_fh: pickle.dump(varmap, vars_fh) vars_fh.flush() return 1 if hasattr(idaapi, "auto_wait"): # IDA 7.4+ idaapi.auto_wait() else: idaapi.autoWait() # Old IDA if not idaapi.init_hexrays_plugin(): idaapi.load_plugin('hexrays') idaapi.load_plugin('hexx64') if not idaapi.init_hexrays_plugin(): print('Unable to load Hex-rays') else: print(('Hex-rays version %s has been detected' % idaapi.get_hexrays_version())) def main(): cv = collect_vars() cv.activate(None) dv = dump_info() dv.activate(None)
def try_mark_as_function(address): if not idaapi.add_func(address, idc.BADADDR): DEBUG("Unable to convert code to function: {}".format(address)) return False idaapi.autoWait() return True
def parse_str_ptr(addr): if idc.GetMnem(addr) != 'mov': return False # Validate that the string offset actually exists inside the binary if idc.get_segm_name(idc.GetOperandValue(addr, 1)) is None: return False # Check the operands' type: # - first one must be a register; # - second one must be a memory address if idc.GetOpType(addr, 0) != 1 or idc.GetOpType(addr, 1) != 2: return False addr_2 = idc.FindCode(addr, idaapi.SEARCH_DOWN) # same operands' type for addr_2 if idc.GetMnem(addr_2) != 'mov' or idc.GetOpType( addr_2, 0) != 1 or idc.GetOpType(addr_2, 1) != 2: return False opnd_val_1 = idc.GetOperandValue(addr, 1) opnd_val_2 = idc.GetOperandValue(addr_2, 1) opnd_diff = opnd_val_1 - opnd_val_2 # The 2 operands, one of addr of string length, another one is the addr of string pointer # and they must be side by side if opnd_diff != common.ADDR_SZ and opnd_diff != -common.ADDR_SZ: return False if opnd_diff > 0: str_len_addr, str_ptr_addr = opnd_val_1, opnd_val_2 else: str_len_addr, str_ptr_addr = opnd_val_2, opnd_val_1 str_len = common.read_mem(str_len_addr) str_ptr = common.read_mem(str_ptr_addr) str_addr = common.read_mem(str_ptr) # set max str len if str_len > 64: return False if 'rodata' not in idc.get_segm_name( str_ptr) and 'text' not in idc.get_segm_name(str_ptr): return False common._debug("------------------------------") common._debug("Possible str ptr:") common._debug("Code addr: 0x%x , str_ptr_addr: 0x%x , str_len_addr: 0x%x" % (addr, str_ptr_addr, str_len_addr)) common._debug("str_addr: 0x%x , str_len: 0x%x" % (str_ptr, str_len)) #if create_string(str_addr, str_len): if str_len > 1: if idc.MakeStr(str_ptr, str_ptr + str_len): idaapi.autoWait() if opnd_diff > 0: idc.MakeComm(addr, "length: %d" % str_len) idaapi.add_dref(addr_2, str_ptr, idaapi.dr_O) else: idc.MakeComm(addr_2, "length: %d" % str_len) idaapi.add_dref(addr, str_ptr, idaapi.dr_O) idaapi.autoWait() return True return False
def parse(self, is_test=False): if is_test: common._info("Test firstmoduledata addr: 0x%x" % self.start_addr) self.pclntbl_addr = read_mem(self.start_addr, read_only=is_test) self.pclntbl_sz = read_mem(self.start_addr+ADDR_SZ, read_only=is_test) self.pclntbl_cap = read_mem(self.start_addr+2*ADDR_SZ, read_only=is_test) self.ftab_addr = read_mem(self.start_addr+3*ADDR_SZ, read_only=is_test) self.func_num = read_mem(self.start_addr+4*ADDR_SZ, read_only=is_test) self.ftab_cap = read_mem(self.start_addr+5*ADDR_SZ, read_only=is_test) self.filetab_addr = read_mem(self.start_addr+6*ADDR_SZ, read_only=is_test) self.srcfile_num = read_mem(self.start_addr+7*ADDR_SZ, read_only=is_test) self.srcfile_tab_cap = read_mem(self.start_addr+8*ADDR_SZ, read_only=is_test) self.findfunctab = read_mem(self.start_addr+9*ADDR_SZ, read_only=is_test) self.min_pc = read_mem(self.start_addr+10*ADDR_SZ, read_only=is_test) self.max_pc = read_mem(self.start_addr+11*ADDR_SZ, read_only=is_test) self.text_addr = read_mem(self.start_addr+12*ADDR_SZ, read_only=is_test) self.etext_addr = read_mem(self.start_addr+13*ADDR_SZ, read_only=is_test) if is_test: return self.noptrdata_addr = read_mem(self.start_addr+14*ADDR_SZ, read_only=is_test) self.enoptrdata_addr = read_mem(self.start_addr+15*ADDR_SZ, read_only=is_test) self.data_addr = read_mem(self.start_addr+16*ADDR_SZ, read_only=is_test) self.edata_addr = read_mem(self.start_addr+17*ADDR_SZ, read_only=is_test) self.bss_addr = read_mem(self.start_addr+18*ADDR_SZ, read_only=is_test) self.ebss_addr = read_mem(self.start_addr+19*ADDR_SZ, read_only=is_test) self.noptrbss_addr = read_mem(self.start_addr+20*ADDR_SZ, read_only=is_test) self.enoptrbss_addr = read_mem(self.start_addr+21*ADDR_SZ, read_only=is_test) self.end_addr = read_mem(self.start_addr+22*ADDR_SZ, read_only=is_test) self.gcdata_addr = read_mem(self.start_addr+23*ADDR_SZ, read_only=is_test) self.gcbss_addr = read_mem(self.start_addr+24*ADDR_SZ, read_only=is_test) self.types_addr = read_mem(self.start_addr+25*ADDR_SZ, read_only=is_test) self.etypes_addr = read_mem(self.start_addr+26*ADDR_SZ, read_only=is_test) self.textsecmap_addr = read_mem(self.start_addr+27*ADDR_SZ, read_only=is_test) self.textsecmap_len = read_mem(self.start_addr+28*ADDR_SZ, read_only=is_test) self.textsecmap_cap = read_mem(self.start_addr+29*ADDR_SZ, read_only=is_test) self.typelink_addr = read_mem(self.start_addr+30*ADDR_SZ, read_only=is_test) self.type_num = read_mem(self.start_addr+31*ADDR_SZ, read_only=is_test) self.type_cap = read_mem(self.start_addr+32*ADDR_SZ, read_only=is_test) self.itablink_addr = read_mem(self.start_addr+33*ADDR_SZ, read_only=is_test) self.itab_num = read_mem(self.start_addr+34*ADDR_SZ, read_only=is_test) self.itab_cap = read_mem(self.start_addr+35*ADDR_SZ, read_only=is_test) self.ptab_addr = read_mem(self.start_addr+36*ADDR_SZ, read_only=is_test) self.ptab_num = read_mem(self.start_addr+37*ADDR_SZ, read_only=is_test) self.ptab_cap = read_mem(self.start_addr+38*ADDR_SZ, read_only=is_test) pluginpath_addr = read_mem(self.start_addr+39*ADDR_SZ, read_only=is_test) pluginpath_len = read_mem(self.start_addr+40*ADDR_SZ, read_only=is_test) self.pluginpath = str(idc.GetManyBytes(pluginpath_addr, pluginpath_len)) modulename_addr = read_mem(self.start_addr+44*ADDR_SZ, read_only=is_test) modulename_len = read_mem(self.start_addr+45*ADDR_SZ, read_only=is_test) self.modulename = str(idc.GetManyBytes(modulename_addr, modulename_len)) self.hasmain = idc.Byte(self.start_addr+49*ADDR_SZ) self.next = read_mem(self.start_addr+54*ADDR_SZ+1, read_only=is_test) if not is_test: idc.MakeNameEx(self.start_addr, "runtime.firstmoduledata", flags=idaapi.SN_FORCE) idaapi.autoWait() idc.MakeComm(self.start_addr, "pclntbl addr") idc.MakeComm(self.start_addr + ADDR_SZ, "pclntbl size") idc.MakeComm(self.start_addr + 2*ADDR_SZ, "pclntbl capacity") idc.MakeComm(self.start_addr + 3*ADDR_SZ, "funcs table addr") idc.MakeComm(self.start_addr + 4*ADDR_SZ, "funcs number") idc.MakeComm(self.start_addr + 5*ADDR_SZ, "funcs table capacity") idc.MakeComm(self.start_addr + 6*ADDR_SZ, "source files table addr") idc.MakeComm(self.start_addr + 7*ADDR_SZ, "source files number") idc.MakeComm(self.start_addr + 8*ADDR_SZ, "source files table capacity") idc.MakeComm(self.start_addr + 9*ADDR_SZ, "findfunctable addr") idc.MakeComm(self.start_addr + 10*ADDR_SZ, "min pc") idc.MakeComm(self.start_addr + 11*ADDR_SZ, "max pc") idc.MakeComm(self.start_addr + 12*ADDR_SZ, "text start addr") idc.MakeComm(self.start_addr + 13*ADDR_SZ, "text end addr") idc.MakeComm(self.start_addr + 14*ADDR_SZ, "noptrdata start addr") idc.MakeComm(self.start_addr + 15*ADDR_SZ, "noptrdata end addr") idc.MakeComm(self.start_addr + 16*ADDR_SZ, "data section start addr") idc.MakeComm(self.start_addr + 17*ADDR_SZ, "data section end addr") idc.MakeComm(self.start_addr + 18*ADDR_SZ, "bss start addr") idc.MakeComm(self.start_addr + 19*ADDR_SZ, "bss end addr") idc.MakeComm(self.start_addr + 20*ADDR_SZ, "noptrbss start addr") idc.MakeComm(self.start_addr + 21*ADDR_SZ, "noptrbss end addr") idc.MakeComm(self.start_addr + 22*ADDR_SZ, "end addr of whole image") idc.MakeComm(self.start_addr + 23*ADDR_SZ, "gcdata addr") idc.MakeComm(self.start_addr + 24*ADDR_SZ, "gcbss addr") idc.MakeComm(self.start_addr + 25*ADDR_SZ, "types start addr") idc.MakeComm(self.start_addr + 26*ADDR_SZ, "types end addr") idc.MakeComm(self.start_addr + 27*ADDR_SZ, "test section map addr") idc.MakeComm(self.start_addr + 28*ADDR_SZ, "test section map length") idc.MakeComm(self.start_addr + 29*ADDR_SZ, "test section map capacity") idc.MakeComm(self.start_addr + 30*ADDR_SZ, "typelink addr") idc.MakeComm(self.start_addr + 31*ADDR_SZ, "types number") idc.MakeComm(self.start_addr + 32*ADDR_SZ, "types table capacity") idc.MakeComm(self.start_addr + 33*ADDR_SZ, "itabslink addr") idc.MakeComm(self.start_addr + 34*ADDR_SZ, "itabs number") idc.MakeComm(self.start_addr + 35*ADDR_SZ, "itabs caapacity") idc.MakeComm(self.start_addr + 36*ADDR_SZ, "ptab addr") idc.MakeComm(self.start_addr + 37*ADDR_SZ, "ptab num") idc.MakeComm(self.start_addr + 38*ADDR_SZ, "ptab capacity") idc.MakeComm(self.start_addr + 39*ADDR_SZ, "plugin path addr") idc.MakeComm(self.start_addr + 40*ADDR_SZ, "plugin path length") idc.MakeComm(self.start_addr + 44*ADDR_SZ, "module name addr") idc.MakeComm(self.start_addr + 45*ADDR_SZ, "module name length") idc.MakeComm(self.start_addr + 49*ADDR_SZ, "hasmain flag") idc.MakeComm(self.start_addr + 54*ADDR_SZ+1, "next moduledata addr") idaapi.autoWait() idc.MakeStr(modulename_addr, modulename_addr+modulename_len) idaapi.autoWait() idc.MakeStr(pluginpath_addr, pluginpath_addr+pluginpath_len) idaapi.autoWait()
def wait_for_analysis_to_finish(): idaapi.autoWait() idc.Wait()
def open(f): ## we are allready inside inside ida idaapi.autoWait() return True
def load_file(fd, neflags, format): global prologues size = 0 base_addr = 0 ea = 0 nfunc = 0 idaapi.set_processor_type("arm", idaapi.SETPROC_ALL) idaapi.get_inf_structure().lflags |= idaapi.LFLG_64BIT if (neflags & idaapi.NEF_RELOAD) != 0: return 1 fd.seek(0, idaapi.SEEK_END) size = fd.tell() segm = idaapi.segment_t() segm.bitness = 2 # 64-bit segm.start_ea = 0 segm.end_ea = size idaapi.add_segm_ex(segm, "iBoot", "CODE", idaapi.ADDSEG_OR_DIE) fd.seek(0) fd.file2base(0, 0, size, false) idaapi.add_entry(0, 0, "start", 1) idc.MakeFunction(ea) print("[+] Marked as code") # heuristic while (true): mnemonic = idc.GetMnem(ea) if "LDR" in mnemonic: base_str = idc.GetOpnd(ea, 1) base_addr = int(base_str.split("=")[1], 16) break ea += 4 print("[+] Rebasing to address 0x%x" % (base_addr)) idaapi.rebase_program(base_addr, idc.MSF_NOFIX) idaapi.autoWait() segment_start = base_addr segment_end = idc.GetSegmentAttr(segment_start, idc.SEGATTR_END) ea = segment_start print("[+] Searching and defining functions") for prologue in prologues: while ea != idc.BADADDR: ea = idc.FindBinary(ea, idc.SEARCH_DOWN, prologue, 16) if ea != idc.BADADDR: ea = ea - 2 if (ea % 4) == 0 and idc.GetFlags(ea) < 0x200: # print("[+] Defining a function at 0x%x" % (ea)) idc.MakeFunction(ea) nfunc = nfunc + 1 ea = ea + 4 idc.AnalyzeArea(segment_start, segment_end) idaapi.autoWait() print("[+] Identified %d new functions" % (nfunc)) print("[+] Looking for interesting functions") find_interesting(segment_start) return 1
def fix_all(): # wait till autoanalysis is done idaapi.autoWait() ea = 0 numInst = 0 numAddRegPc = 0 numFixed = 0 t0 = time.clock() # last MOV/MOVT inst targeting the register, key=register number movVal = dict() movtVal = dict() global refs #old ver compat nextHeadArgCount = len(inspect.getargspec(idc.NextHead).args) cnt = 0 while True: cnt += 1 if nextHeadArgCount == 1: ea = idc.NextHead(ea) else: ea = idc.NextHead(ea, idc.BADADDR) if cnt & 0xfff == 0: print "[progress] ea: %x" % ea if ea == idc.BADADDR: break if not idaapi.isCode(idaapi.getFlags(ea)): continue numInst += 1 # slow, is there any way to avoid it?.. i = idautils.DecodeInstruction(ea) if not i: continue mnem = i.get_canon_mnem() if i[0].type != 1: # only interested in register target operands continue target_reg = i[0].phrase if mnem == 'ADD': if i[1].type == 1 and i[1].phrase == 15: numAddRegPc += 1 (val, mov_ea) = movVal.get(target_reg, (0, 0)) (val_t, movt_ea) = movtVal.get(target_reg, (0, 0)) if not mov_ea: # No preceding MOV, bailing.. continue numFixed += 1 target_addr = 0xffffFFFF & (ea + 4 + val + 0x10000 * val_t) # could be THUMB proc.. if target_addr & 1 and idaapi.isCode( idaapi.getFlags(target_addr - 1)): target_name = idaapi.get_name(target_addr - 1, target_addr - 1) else: target_name = idaapi.get_name(target_addr, target_addr) refs.append((ea, target_addr, target_name)) if i[1].type == 5: if mnem == 'MOV': movVal[target_reg] = (i[1].value, ea) movtVal[target_reg] = (0, 0 ) # since movw clears top bits anyway elif mnem == 'MOVT': movtVal[target_reg] = (i[1].value, ea) else: movVal[target_reg] = (0, 0) movtVal[target_reg] = (0, 0) print "%u instructions scanned in %f seconds" % (numInst, time.clock() - t0) add_refs() # work around an IDA bug for i in range(1, 5): idaapi.autoWait() add_refs() if numAddRegPc == 0: successRate = 100 else: successRate = numFixed * 100.0 / numAddRegPc print "%u 'ADD Reg, PC' found, %u fixed: %u%%" % (numAddRegPc, numFixed, successRate) global g_done g_done = 1
def wait(cls): '''Wait until IDA's autoanalysis queues are empty.''' return idaapi.autoWait() if idaapi.__version__ < 7.0 else idaapi.auto_wait()
def lvar_type_changed(self, vu, v, tif): if (vu.cfunc): func_tif = ida_typeinf.tinfo_t() vu.cfunc.get_func_type(func_tif) funcdata = idaapi.func_type_data_t() got_data = func_tif.get_func_details(funcdata) if (not got_data): # self._log("Didnt get the data") pass lvars = vu.cfunc.get_lvars() for j in range(len(vu.cfunc.argidx)): # for i in vu.cfunc.argidx: i = vu.cfunc.argidx[j] if (lvars[i].name == v.name): #self._log("lvar_type_changed: function argument changed = %s, index = %s, atype = %s" % (lvars[i].name, i, funcdata[j].argloc.atype())) if (funcdata[i].argloc.atype() == 3): # self._log("lvar_type_changed: reg is : %s" %(funcdata[i].argloc.reg1())) pass if (funcdata[i].argloc.atype() != 3 or funcdata[i].argloc.reg1() != RCX_REG): break #self._log("applyName = %s" % (applyName)) firstPtrRemove = ida_typeinf.remove_pointer(tif) #self._log("type name = %s" % (firstPtrRemove._print())) #self._log("remove_pointer.is_ptr = %s" % (firstPtrRemove.is_ptr())) #self._log("remove_pointer.is_struct = %s" % (firstPtrRemove.is_struct())) if (firstPtrRemove.is_struct() and not firstPtrRemove.is_ptr()): currentFuncName = ida_name.get_ea_name( vu.cfunc.entry_ea) # self._log("before demangle current func name = %s" % (currentFuncName)) demangled = idc.Demangle( currentFuncName, idc.GetLongPrm(idc.INF_SHORT_DN)) if (demangled != None): self._log("Overriding mangled name = %s" % (currentFuncName)) currentFuncName = demangled # self._log("after demangle current func name = %s" % (currentFuncName)) tokens = currentFuncName.split("::") if len(tokens) > 1: currentFuncName = tokens[1] currentFuncName = currentFuncName.split("(")[0] # self._log("current func name = %s" % (currentFuncName)) idc.MakeNameEx( vu.cfunc.entry_ea, firstPtrRemove._print() + "::" + currentFuncName, idc.SN_NOWARN) idaapi.autoWait() # self._log("Decomp Res : %s" % idaapi.decompile(vu.cfunc.entry_ea)) idaapi.refresh_idaview_anyway() vu.refresh_ctext() idaapi.refresh_idaview_anyway() vu.refresh_ctext() vu.refresh_view(True) current_widget = idaapi.get_current_widget() vu1 = idaapi.get_widget_vdui(current_widget) if vu1: vu1.refresh_ctext() break #self._log("lvar_type_changed: vu=%s, v=%s, tinfo=%s" % (vu, self._format_lvar(v), tif._print())) return 1
def fix_all(): # wait till autoanalysis is done idaapi.autoWait() ea = 0 numInst = 0 numAddRegPc = 0 numFixed = 0 t0 = time.clock() # last MOV/MOVT inst targeting the register, key=register number movVal = dict() movtVal = dict() global refs cnt = 0 while True: cnt += 1 ea = idc.NextHead(ea) if cnt & 0xfff == 0: print "[progress] ea: %x" % ea if ea == idc.BADADDR: break if not idaapi.isCode(idaapi.getFlags(ea)): continue numInst += 1 # slow, is there any way to avoid it?.. i = idautils.DecodeInstruction(ea) if not i: continue mnem = i.get_canon_mnem() if i[0].type != 1: # only interested in register target operands continue target_reg = i[0].phrase if mnem == 'ADD': if i[1].type == 1 and i[1].phrase == 15: numAddRegPc += 1 (val, mov_ea) = movVal.get(target_reg, (0, 0)) (val_t, movt_ea) = movtVal.get(target_reg, (0, 0)) if not mov_ea: # No preceding MOV, bailing.. continue numFixed += 1 target_addr = 0xffffFFFF & (ea + 4 + val + 0x10000 * val_t) # could be THUMB proc.. if target_addr & 1 and idaapi.isCode(idaapi.getFlags(target_addr - 1)): target_name = idaapi.get_name(target_addr - 1, target_addr - 1) else: target_name = idaapi.get_name(target_addr,target_addr) refs.append((ea, target_addr, target_name)) if i[1].type == 5: if mnem == 'MOV': movVal[target_reg] = (i[1].value, ea) movtVal[target_reg] = (0, 0) # since movw clears top bits anyway elif mnem == 'MOVT': movtVal[target_reg] = (i[1].value, ea) else: movVal[target_reg] = (0, 0) movtVal[target_reg] = (0, 0) print "%u instructions scanned in %f seconds" % (numInst, time.clock() - t0) add_refs() # work around an IDA bug for i in range (1, 5): idaapi.autoWait() add_refs() if numAddRegPc == 0: successRate = 100 else: successRate = numFixed * 100.0 / numAddRegPc print "%u 'ADD Reg, PC' found, %u fixed: %u%%" % (numAddRegPc, numFixed, successRate) global g_done g_done = 1
def parse_pclntable(module_data): pPcHeader = module_data.pPcHeader pc_header = parse_pc_header(pMem=pPcHeader) ptrSize = pc_header.ptrSize numberOfFuncs = pc_header.nFunc log._info("Number of Functions : %d" % numberOfFuncs) pclntable_start = module_data.pPclnTable cur_addr = pclntable_start for idx in range(numberOfFuncs): cur_addr = pclntable_start + (2 * ptrSize) * idx func_rva = common.mem_read_integer(addr=cur_addr, read_size=ptrSize) _func_structure_offset = common.mem_read_integer(addr=cur_addr + ptrSize, read_size=ptrSize) _func_addr = pclntable_start + _func_structure_offset if not idc.GetFunctionName(func_rva): log._info("Unk Func @0x%x" % func_rva) idc.MakeUnkn(func_rva, idc.DOUNK_EXPAND) idaapi.autoWait() idc.MakeCode(func_rva) idaapi.autoWait() if idc.MakeFunction(func_rva): idaapi.autoWait() log._info("Create Func @0x%x" % func_rva) _func = parse__func(pMem=_func_addr) #args=_func.args #func_id=_func.args func_name_addr = module_data.pFuncNameTable + _func.nameoff func_name = idc.GetString(func_name_addr) if func_name: clean_func_name = utils.clean_function_name(func_name) log._info("@0x%x Name : [%s]" % (func_rva, func_name)) idc.MakeComm(func_rva, "@0x" + str(hex(func_rva)) + " entry") idaapi.autoWait() if idc.MakeStr(func_name_addr, func_name_addr + len(func_name) + 1): idaapi.autoWait() else: log._error("@0x%x Name : [%s] Failed..." % (func_rva, func_name)) _func_addr = idaapi.get_func(func_rva) if _func_addr is not None: if idc.MakeNameEx(_func_addr.startEA, func_name, flags=idaapi.SN_FORCE): idaapi.autoWait() log._info("@0x%x Name : [%s]" % (func_rva, func_name)) else: log._error("@0x%x Name : [%s] Failed..." % (func_rva, func_name))
import idaapi import idautils def get_all_strings(): #Get a list of strings stored in that segment list_of_strings = idautils.Strings() for string in list_of_strings: f.write(str(string) + '\n') #Wait for analysis to complete idaapi.autoWait() #Write results to output file output_dir = "C:\data\IDBstore\Strings_output\\" output_filename = 'strings_' + str(GetInputFile()) + '.txt' f = open(output_dir + output_filename, 'a') get_all_strings() #Close and exit f.close() idc.Exit(0)
def PLUGIN_ENTRY(): """ IDAPython plugin wrapper """ idaapi.autoWait() return SkelenoxPlugin()
def mark_as_code(address): if not idc.isCode(idc.GetFlags(address)): idc.MakeCode(address) idaapi.autoWait()
#coding=utf-8 import idc import idaapi import idautils idaapi.autoWait() #等待IDA的分析完成 # 统计idb文件中所有指令的总数 # "D:\software\IDA 7.0\idat64.exe" -A -Scountrecord.py rundll32.idb count = 0 for func in idautils.Functions(): #忽略库函数 flags = idc.GetFunctionFlags(func) if flags & FUNC_LIB: continue for instru in idautils.FuncItems(func): count += 1 f = open("instru_count.txt", "w") print_me = "Instruction Count is %d" % (count) f.write(print_me) f.close() idc.Exit(0) #停止执行脚本 并关闭idb数据库文件
def reanalyze(segm): AnalyzeArea(segm.start_ea, segm.end_ea) idaapi.autoWait()
def parse_funcs(self): ''' Parse function struct and rename function ''' self.func_num = common.read_mem(self.start_addr + 8, forced_addr_sz=self.ptr_sz) common._info("Total functions number: %d\n" % self.func_num) self.func_tbl_sz = self.func_num * 2 * self.ptr_sz funcs_entry = self.start_addr + 8 self.func_tbl_addr = funcs_entry + self.ptr_sz idc.MakeComm(funcs_entry, "Functions number") idc.MakeNameEx(funcs_entry, "funcs_entry", flags=idaapi.SN_FORCE) idaapi.autoWait() idc.MakeNameEx(self.func_tbl_addr, "pc0", flags=idaapi.SN_FORCE) idaapi.autoWait() for func_idx in xrange(self.func_num): curr_addr = self.func_tbl_addr + func_idx * 2 * self.ptr_sz func_addr = common.read_mem(curr_addr, forced_addr_sz=self.ptr_sz) if not idc.GetFunctionName(func_addr): common._debug("Creating function @ %x" % func_addr) idc.MakeUnkn(func_addr, idc.DOUNK_EXPAND) idaapi.autoWait() idc.MakeCode(func_addr) idaapi.autoWait() if idc.MakeFunction(func_addr): idaapi.autoWait() common._info("Create function @ 0x%x" % func_addr) name_off = common.read_mem(curr_addr + self.ptr_sz, forced_addr_sz=self.ptr_sz) name_addr = self.start_addr + self.ptr_sz + name_off func_st_addr = name_addr - self.ptr_sz func_st = FuncStruct(func_st_addr, self) func_st.parse() # Make comment for name offset idc.MakeComm(curr_addr + self.ptr_sz, "Func Struct @ 0x%x" % func_st_addr) idaapi.autoWait()
def parse(self, is_test=False): func_addr = common.read_mem(self.addr, forced_addr_sz=self.pclntbl.ptr_sz, read_only=is_test) name_addr = common.read_mem(self.addr + self.pclntbl.ptr_sz, forced_addr_sz=4, read_only=is_test) \ + self.pclntbl.start_addr raw_name_str = idc.GetString(name_addr) if raw_name_str and len(raw_name_str) > 0: self.name = common.clean_function_name(raw_name_str) if not is_test: idc.MakeComm(self.addr, "Func Entry") idaapi.autoWait() # make comment for func name offset idc.MakeComm( self.addr + self.pclntbl.ptr_sz, "Func name offset(Addr @ 0x%x), name string: %s" % (name_addr, raw_name_str)) idaapi.autoWait() # Make name string if len(self.name) > 0: if idc.MakeStr(name_addr, name_addr + len(raw_name_str) + 1): idaapi.autoWait() common._debug("Match func_name: %s" % self.name) else: common._error("Make func_name_str [%s] failed @0x%x" % (self.name, name_addr)) # Rename function real_func = idaapi.get_func(func_addr) if real_func is not None: orig_func_name = idc.get_func_name(real_func.startEA) if len(self.name) > 0 and orig_func_name.startswith("sub_"): if idc.MakeNameEx(real_func.startEA, self.name, flags=idaapi.SN_FORCE): idaapi.autoWait() common._debug("Rename function 0x%x: %s" % (real_func.startEA, self.name)) else: common._error('Failed to rename function @ 0x%x' % real_func.startEA) self.args = common.read_mem(self.addr + self.pclntbl.ptr_sz + 4, forced_addr_sz=4, read_only=is_test) self.frame = common.read_mem(self.addr + self.pclntbl.ptr_sz + 2 * 4, forced_addr_sz=4, read_only=is_test) self.pcsp = common.read_mem(self.addr + self.pclntbl.ptr_sz + 3 * 4, forced_addr_sz=4, read_only=is_test) self.pcfile = common.read_mem(self.addr + self.pclntbl.ptr_sz + 4 * 4, forced_addr_sz=4, read_only=is_test) self.pcln = common.read_mem(self.addr + self.pclntbl.ptr_sz + 5 * 4, forced_addr_sz=4, read_only=is_test) self.nfuncdata = common.read_mem(self.addr + self.pclntbl.ptr_sz + 6 * 4, forced_addr_sz=4, read_only=is_test) self.npcdata = common.read_mem(self.addr + self.pclntbl.ptr_sz + 7 * 4, forced_addr_sz=4, read_only=is_test) if not is_test: idc.MakeComm(self.addr + self.pclntbl.ptr_sz + 4, "args") idc.MakeComm(self.addr + self.pclntbl.ptr_sz + 2 * 4, "frame") idc.MakeComm(self.addr + self.pclntbl.ptr_sz + 3 * 4, "pcsp") idc.MakeComm(self.addr + self.pclntbl.ptr_sz + 4 * 4, "pcfile") idc.MakeComm(self.addr + self.pclntbl.ptr_sz + 5 * 4, "pcln") idc.MakeComm(self.addr + self.pclntbl.ptr_sz + 6 * 4, "nfuncdata") idc.MakeComm(self.addr + self.pclntbl.ptr_sz + 7 * 4, "npcdata") idaapi.autoWait()
def get_goroot(): goroot_path_str = "" ''' Get GOROOT path string ''' func_goroot = find_func_by_name("runtime_GOROOT") if func_goroot is None: _error("Failed to find func contains goroot") return goroot_path_str goroot_flowchart = idaapi.FlowChart(f=func_goroot) ret_cbs = find_ret_cb(goroot_flowchart) ''' runtime.GOROOT() normally has 2 return code blocks: 1. False return mov [rsp+28h+arg_0], rax mov [rsp+28h+arg_8], rcx mov rbp, [rsp+28h+var_8] add rsp, 28h retn 2. True return(Which we needed): (1). goroot string length as ptr mov rax, cs:runtime_internal_sys_DefaultGoroot mov rcx, cs:qword_D9AB58 mov [rsp+28h+arg_0], rax mov [rsp+28h+arg_8], rcx mov rbp, [rsp+28h+var_8] add rsp, 28h retn (2). goroot string length as instant number lea rax, unk_7220B5 mov [rsp+28h+arg_0], rax mov [rsp+28h+arg_8], 0Dh mov rbp, [rsp+28h+var_8] add rsp, 28h retn ''' for cb_idx in ret_cbs: if idc.GetOpType(goroot_flowchart[cb_idx].startEA, 0) == 1: # e.g.: mov rax, cs:runtime_internal_sys_DefaultGoroot ''' Op Types refer: https://www.hex-rays.com/products/ida/support/sdkdoc/ua_8hpp.html#aaf9da6ae7e8b201108fc225adf13b4d9 o_void = 0 # No Operand o_reg = 1 # General Register (al,ax,es,ds...) reg o_mem = 2 # Direct Memory Reference (DATA) addr o_phrase = 3 # Memory Ref [Base Reg + Index Reg] phrase o_displ = 4 # Memory Reg [Base Reg + Index Reg + Displacement] phrase+addr o_imm = 5 # Immediate Value value o_far = 6 # Immediate Far Address (CODE) addr o_near = 7 # Immediate Near Address (CODE) addr ...... ''' goroot_path_len = 0 goroot_path_addr = 0 curr_addr = goroot_flowchart[cb_idx].startEA goroot_path_addr_val = idc.GetOperandValue(curr_addr, 1) end_addr = goroot_flowchart[cb_idx].endEA curr_addr = idc.FindCode(curr_addr, idaapi.SEARCH_DOWN) # find goroot path length and OpType of length(instant len number or addr of len) while curr_addr <= end_addr: len_optype = idc.GetOpType(curr_addr, 1) if len_optype == 2: # addr of len # mov rcx, cs:qword_D9AB58 goroot_path_addr = read_mem(goroot_path_addr_val) goroot_path_len = read_mem(goroot_path_addr_val + ADDR_SZ) break elif len_optype == 5: # instant number as len # mov [rsp+28h+arg_8], 0Dh goroot_path_addr = goroot_path_addr_val goroot_path_len = idc.GetOperandValue(curr_addr, 1) break curr_addr = idc.FindCode(curr_addr, idaapi.SEARCH_DOWN) if goroot_path_len == 0 or goroot_path_addr == 0: raise Exception("Invalid GOROOT Address ang Length") goroot_path_str = str( idc.GetManyBytes(goroot_path_addr, goroot_path_len)) if goroot_path_str is None or len(goroot_path_str) == 0: raise Exception("Invalid GOROOT") idc.MakeStr(goroot_path_addr, goroot_path_addr + goroot_path_len) idaapi.autoWait() break if len(goroot_path_str) > 0: _info("Go ROOT Path: %s\n" % goroot_path_str) return goroot_path_str.replace("\\", "/")
for name in funcs: each_function_disassembly = list(idautils.FuncItems(name)) for e in each_function_disassembly: for vulnfunc in vuln_function_list: pattern=vulnfunc+r'$' m=re.search(pattern,idc.GetDisasm(e)) if m: f.write(idc.GetFuncOffset(e)+' --> '+idc.GetDisasm(e)+'\n\n') else: f.write('Failed to get function names and hence cannot parse stuff\n') vuln_function_list = [] pattern = [] conf = {} #List of vulnerable functions that are searched for inside the IDB. Add more functions here. vuln_function_list=['strcpy','strcat','gets','sprintf','vsprintf','scanf','memcpy','printf'] #Wait for analysis to complete idaapi.autoWait() #Write results to output file output_dir="C:\data\IDBstore\\" output_filename=str(GetInputFile())+'.txt' f=open(output_dir+output_filename,'a') search_for_vuln_api() #Close and exit f.close() idc.Exit(0)