def copy_bytes(): """ Copy selected bytes to clipboard """ if using_ida7api: start = idc.read_selection_start() end = idc.read_selection_end() if idaapi.BADADDR in (start, end): ea = idc.here() start = idaapi.get_item_head(ea) end = idaapi.get_item_end(ea) # # reference https://stackoverflow.com/questions/6624453/whats-the-correct-way-to-convert-bytes-to-a-hex-string-in-python-3 data = idc.get_bytes(start, end - start).hex() print("Bytes copied: %s" % data) copy_to_clip(data) else: start = idc.SelStart() end = idc.SelEnd() if idaapi.BADADDR in (start, end): ea = idc.here() start = idaapi.get_item_head(ea) end = idaapi.get_item_end(ea) # reference https://stackoverflow.com/questions/6624453/whats-the-correct-way-to-convert-bytes-to-a-hex-string-in-python-3 # not work in ida7.5 python3.7.7 # data = idc.GetManyBytes(start, end-start).encode('hex') data = idc.GetManyBytes(start, end - start).hex() print("Bytes copied: %s" % data) copy_to_clip(data) return
def show_current_function_meaningful(): try: function = sark.Function(idc.here()) show_meaningful_in_function(function) except sark.exceptions.SarkNoFunction: idaapi.msg("[FunctionStrings] No function at 0x{:08X}.\n".format(idc.here()))
def actionP(): """ Profiling Action. Time Profiling and other analyses go here. """ # tp.runTimeTests() n = 10 x = lambda ea: Data.Data(ea).__str__() t, output = tp.avgTime_us(n, x, here()) print('[%03d us] %s' % (t, Data.Data(here()).getDisasm()))
def compare_s(*args): """ wrapper sur idc.here() """ print "" print "<!------- SUB HASH COMPARE -------!>" print "[+] Searching for " + GetFunctionName(idc.here()) print compare_sub(idc.here()) print "<!--------------------------------!>" return
def runTimeTests(n=10): """ Performs time profiling tests for optimization purposes :param n: number of times to sample the time. Result is the average of all samples """ x = lambda: Data.Data(idc.here())._lowerCode(idc.GetDisasm(idc.here())) y = lambda: Data.Data(idc.here())._lowerCodeOLD(idc.GetDisasm(idc.here())) print(x()) runTimeTest(n, 'new _lowerCode', x) print(y()) runTimeTest(n, 'old _lowerCode', y)
def promptForRange(self): #check if a range has already been selected - if so skip prompt start = idc.SelStart() if start != idc.BADADDR: self.logger.info('Processing range 0x%08x - 0x%08x', self.params.startAddr, self.params.endAddr) self.params.startAddr = start self.params.endAddr = idc.SelEnd() else: self.logger.info('Processing current segment only') self.params.startAddr = idc.SegStart(idc.here()) self.params.endAddr = idc.SegEnd(idc.here())
def processCode(self): if (self.params.startAddr==idc.BADADDR) and (self.params.endAddr==idc.BADADDR): self.logger.info('Processing current segment only') #self.processAllSegments() self.params.startAddr = idc.SegStart(idc.here()) self.params.endAddr = idc.SegEnd(idc.here()) else: self.logger.info('Processing range 0x%08x - 0x%08x', self.params.startAddr, self.params.endAddr) if self.params.searchDwordArray: self.lookForDwordArray(self.params.startAddr, self.params.endAddr) if self.params.searchPushArgs: self.lookForOpArgs(self.params.startAddr, self.params.endAddr)
def run(self): try: self.logger.debug('Starting up') dlg = StructTyperWidget() dlg.setStructs(loadStructs()) oldTo = idaapi.set_script_timeout(0) res = dlg.exec_() idaapi.set_script_timeout(oldTo) if res == QtGui.QDialog.DialogCode.Accepted: regPrefix = dlg.getRegPrefix() sid = None struc = None if dlg.ui.rb_useStackFrame.isChecked(): ea = idc.here() sid = idc.GetFrame(ea) struc = idaapi.get_frame(ea) self.logger.debug('Dialog result: accepted stack frame') if (sid is None) or (sid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError('Failed to get sid for stack frame at 0x%x' % ea) if (struc is None) or (struc == 0) or (struc == idc.BADADDR): raise RuntimeError('Failed to get struc_t for stack frame at 0x%x' % ea) #need the actual pointer value, not the swig wrapped struc_t struc= long(struc.this) else: structName = dlg.getActiveStruct() self.logger.debug('Dialog result: accepted %s "%s"', type(structName), structName) sid = idc.GetStrucIdByName(structName) if (sid is None) or (sid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError('Failed to get sid for %s' % structName) tid = idaapi.get_struc_id(structName) if (tid is None) or (tid == 0) or (tid == idc.BADADDR): #i should really figure out which is the correct error case raise RuntimeError('Failed to get tid_t for %s' % structName) struc = g_dll.get_struc(tid) if (struc is None) or (struc == 0) or (struc == idc.BADADDR): raise RuntimeError('Failed to get struc_t for %s' % structName) foundMembers = self.processStruct(regPrefix, struc, sid) if dlg.ui.rb_useStackFrame.isChecked() and (foundMembers != 0): #reanalyze current function if we're analyzing a stack frame & found some func pointers funcstart = idc.GetFunctionAttr(idc.here(), idc.FUNCATTR_START) funcend = idc.GetFunctionAttr(idc.here(), idc.FUNCATTR_END) if (funcstart != idc.BADADDR) and (funcend != idc.BADADDR): idc.AnalyzeArea(funcstart, funcend) elif res == QtGui.QDialog.DialogCode.Rejected: self.logger.info('Dialog result: canceled by user') else: self.logger.debug('Unknown result') raise RuntimeError('Dialog unknown result') except Exception, err: self.logger.exception("Exception caught: %s", str(err))
def actionF(): """ Shift+F - Display current file """ gfs = env['gameFiles'] gf = mt.ea2gf(here()) fileAddr = here() - gfs[gf][0] size = gfs[gf][1] - gfs[gf][0] # get last name found ea = here() while not idc.Name(ea): ea -= 1 relAddr = here() - ea print('%s+0x%X::<%s>+0x%X (%d%%)' % (gf, fileAddr, idc.Name(ea), relAddr, float(fileAddr) / size * 100))
def type_one_function(self, tinfo_map): fn_name = GetFunctionName(here()) if not fn_name: print "you're not in a function lol" return if fn_name not in tinfo_map: print "I don't know of this %s" % fn_name return tinfo, fields = tinfo_map[fn_name] fn_loc = LocByName(fn_name) current_tinfo_ = GetTinfo(fn_loc) packed = self.unparse_tinfo(tinfo) if current_tinfo_ is not None: current_tinfo, current_fields = current_tinfo_ if packed == current_tinfo and fields == current_fields: print "already the same" return ret = ApplyType(fn_loc, (packed, fields)) if ret: print "success: %#x %s" % (fn_loc, fn_name) open_pseudocode(fn_loc, False) else: print "failed :(" print fn_name print packed.encode("string_escape") print fields.encode("string_escape")
def ArrayItems(*args): """ Enumerate array items @param ea: address of the array you want the items enumerated, defaults to here() @return: list of each item in the array. Example:: for ea in ArrayItems(): pname= GetString(Dword(ea)) MakeName(Dword(ea+4)&~1, "task_%s" % pname) MakeName(Dword(ea+8), "taskinfo_%s" % pame) MakeName(Dword(ea+12), "stack_%s" % pame) Assuming the cursor is on an array of structs, in which the first struct item points to a name, this will name the other items in the struct. """ ea = args[0] if len(args) > 0 else idc.here() s = idc.ItemSize(ea) ss = idaapi.get_data_elsize(ea, idaapi.get_full_flags(ea)) n = s / ss for i in xrange(n): yield ea + i * ss
def ArrayItems(*args): """ Enumerate array items @param ea: address of the array you want the items enumerated, defaults to here() @return: list of each item in the array. Example:: for ea in ArrayItems(): pname= GetString(Dword(ea)) MakeName(Dword(ea+4)&~1, "task_%s" % pname) MakeName(Dword(ea+8), "taskinfo_%s" % pame) MakeName(Dword(ea+12), "stack_%s" % pame) Assuming the cursor is on an array of structs, in which the first struct item points to a name, this will name the other items in the struct. """ ea = args[0] if len(args)>0 else idc.here() s= idc.ItemSize(ea) ss= idaapi.get_data_elsize(ea, idaapi.getFlags(ea)) n= s/ss for i in range(n): yield ea+i*ss
def map_pe_from_cursor(self): """Map PE file from current cursor position""" # Is the cursor on an MZ file? current = idc.here() if ida_bytes.get_word(current) == 0x5a4d: self.form.map_pe(image_base=current, priority=1)
def __init__(self, ea=UseCurrentAddress, name=None): if name is not None and ea != self.UseCurrentAddress: raise ValueError( ("Either supply a name or an address (ea). " "Not both. (ea={!r}, name={!r})").format(ea, name)) elif name is not None: ea = idc.get_name_ea_simple(name) if ea == idc.BADADDR: raise exceptions.SarkNoFunction( "The supplied name does not belong to an existing function. " "(name = {!r})".format(name)) elif ea == self.UseCurrentAddress: ea = idc.here() elif ea is None: raise ValueError( "`None` is not a valid address. To use the current screen ea, " "use `Function(ea=Function.UseCurrentAddress)` or supply no `ea`." ) elif isinstance(ea, Line): ea = ea.ea self._func = get_func(ea) self._comments = Comments(self)
def __init__(self, ea=UseCurrentAddress, name=None, index=None): """Wrapper around IDA segments. There are 3 ways to get a segment - by name, ea or index. Only use one. Args: ea - address in the segment name - name of the segment index - index of the segment """ if sum((ea not in (self.UseCurrentAddress, None), name is not None, index is not None,)) > 1: raise ValueError( "Expected only one (ea, name or index). Got (ea={!r}, name={!r}, index={!r})".format(ea, name, index)) elif name is not None: seg = idaapi.get_segm_by_name(name) elif index is not None: seg = idaapi.getnseg(index) elif ea == self.UseCurrentAddress: seg = idaapi.getseg(idc.here()) elif ea is None: raise ValueError("`None` is not a valid address. To use the current screen ea, " "use `Function(ea=Function.UseCurrentAddress)` or supply no `ea`.") else: seg = idaapi.getseg(ea) self._segment = seg
def stringify(): ea = idc.here() size_data = get_bitness_bytes(ea) f = idaapi.get_func(ea) frsize = idc.GetFrameLvarSize(ea) position = f.startEA size = 0 while position < f.endEA: instr = idautils.DecodeInstruction(position) if instr is None: print("%x: Not and instruction found" % position) break mnem = instr.get_canon_mnem() if mnem == "mov": if instr.Op2.type == idaapi.o_imm and instr.Op1.type == idaapi.o_reg: #this may be string load is_string, size_s = is_this_a_real_string( position + instr.size, instr, size_data) if is_string is True: make_string(instr.Op2.value, size_s) elif mnem == "lea": if instr.Op2.type == idaapi.o_mem and instr.Op1.type == idaapi.o_reg: is_string, size_s = is_this_a_real_string( position + instr.size, instr, size_data) if is_string is True: make_string(instr.Op2.addr, size_s) position += instr.size
def __init__(self): QtCore.QObject.__init__(self) self.target = ida_kernwin.PluginForm.FormToPyQtWidget( ida_kernwin.open_navband_window(idc.here(), 1)) self.target.installEventFilter(self) self.items = [] self.painting = False
def show_decompiler(): import idc import host import host.ui import traceback import sys import decompiler_form reload(decompiler_form) try: ea = idc.here() func = idaapi.get_func(ea) ea = func.startEA print 'Decompiling %x' % (ea, ) form = decompiler_form.DecompilerForm(ea) form.Show() except: traceback.print_exc() return
def __init__(self): self.storage = {} #TODO: maybe here() not best option self.bt_obj = Utils.get_bitness(idc.here()) self.structCreator = Utils.StructCreator(self.bt_obj) self.processor = None self.typer = None
def get_local_var_value_64(loc_var_name): frame = ida_frame.get_frame(idc.here()) loc_var = ida_struct.get_member_by_name(frame, loc_var_name) loc_var_start = loc_var.soff loc_var_ea = loc_var_start + idc.get_reg_value("RSP") loc_var_value = idc.read_dbg_qword(loc_var_ea) # in case the variable is 32bit, just use get_wide_dword() instead return loc_var_value
def ida_main(): import idc import capa.features.extractors.ida.extractor function = idc.get_func_attr(idc.here(), idc.FUNCATTR_START) print("getting features for current function 0x%X" % function) extractor = capa.features.extractors.ida.extractor.IdaFeatureExtractor() if not function: for feature, va in extractor.extract_file_features(): if va: print("file: 0x%08x: %s" % (va, feature)) else: print("file: 0x00000000: %s" % (feature)) return functions = extractor.get_functions() if function: functions = tuple(filter(lambda f: f.start_ea == function, functions)) if len(functions) == 0: print("0x%X not a function" % function) return -1 print_features(functions, extractor) return 0
def run(self): self.logger.info('Starting up') try: here = idc.here() self.logger.info('Using ea: 0x%08x', here) if not idc.GetMnem(here).startswith('call'): self.logger.info( 'Not running at a call instruction. Bailing out now') return if idc.GetOpType(here, 0) == idc.o_near: self.logger.info( "Cannot (or shouldn't) run when call optype is o_near") return dlg = ApplyCalleeTypeWidget() oldTo = idaapi.set_script_timeout(0) res = dlg.exec_() idaapi.set_script_timeout(oldTo) if res == QtWidgets.QDialog.Accepted: self.logger.debug('Dialog accepted. Input type: %d', dlg.inputType) else: self.logger.debug('Dialog rejected') return tinfo = None #check user input type if dlg.inputType == dlg.USER_TYPE: decl = self.convertUserType(str(dlg.getUserText())) tinfo = self.getUserDeclType(decl) elif dlg.inputType == dlg.STANDARD_TYPE: tinfo = self.getBuiltinGlobalType() elif dlg.inputType == dlg.LOCAL_TYPE: tinfo = self.getLocalType() else: self.logger.info('Bad user input type') return if tinfo is None: self.logger.debug('Bailing due to null tinfo') return #self.logger.info('Deserialize result: %r', ret) #not 100% sure if i need to explicitly convert from func to funcptr - seemed # to pretty much work without this, but doing it just to be sure if not tinfo.is_funcptr(): self.logger.debug('Converting to func pointer') tinfo.create_ptr(tinfo) typename = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, tinfo, '', '') self.logger.info('Applying tinfo: "%s"', str(typename)) #both applying callee type & setting op type -> not sure if both are needed? # set op type causes change in hexrays decompilation # apply callee type updates ida's stack analysis ret = idaapi.apply_callee_tinfo(here, tinfo) ret = idaapi.set_op_tinfo2(here, 0, tinfo) self.logger.debug('set_op_tinfo2 result: %r', ret) except Exception, err: self.logger.exception("Exception caught: %s", str(err))
def taintStart(self): Print("Taint Start pressed!") #Remove the starting breakpoint if self.taintStart is not None: idc.DelBpt(self.taintStart) #Add a new starting breakpoint self.taintStart = idc.here() instruction = idc.GetDisasm(self.taintStart) Print(instruction) idc.AddBpt(self.taintStart) idc.SetBptAttr(self.taintStart, idc.BPT_BRK, 0) callbackAddr = "interactivemodeCallback.startTrace()" customCallbackFuncs = ['ReadFile', 'recv'] for callbackFunc in customCallbackFuncs: if callbackFunc in instruction: callbackAddr = "interactivemodeCallback." + callbackFunc + "()" Print("Found callback function %s for interactive mode" % callbackAddr) break idc.SetBptCnd(self.taintStart, callbackAddr)
def modify_function_lvars(name_prefix="patched_", cmt_prefix="(patched) ", new_types={}): ea = idc.here() my_mod = my_modifier_t( name_prefix=name_prefix, cmt_prefix=cmt_prefix, new_types=new_types) ida_hexrays.modify_user_lvars(ea, my_mod)
def get_selection(): start = idc.SelStart() end = idc.SelEnd() if idaapi.BADADDR in (start, end): ea = idc.here() start = idaapi.get_item_head(ea) end = idaapi.get_item_end(ea) return start, end
def actionZ(): # return next.ret(here(), end_ea=env['gameFiles'][mt.ea2gf(here())][1]) # return next.byDataElement(here(), lambda ea: ('POP' in idc.GetDisasm(ea) and 'PC' in idc.GetDisasm(ea)) # or 'PC, LR' in idc.GetDisasm(ea), # end_ea=env['gameFiles'][mt.ea2gf(here())][1]) # fix.fixThumbPushPopFuncRanges(Function.Function(here()-4).func_ea, here()) # return next.unkptr(here()) # return ops.tillName(here(), ops.delShiftedContent) # currFile = env['gameFiles'][MiscTools.miscTools.ea2gf(here())] unit = source_unit_computations.find_unit_containing(int(idc.here())) unit = source_unit.to_physical_unit(unit) unit_size = source_unit.compute_unit_size(address_space, unit['ea']) print('dumping unit [{:07X}:{:07X}] <{}>'.format(unit['ea'], unit['ea'] + unit_size, unit['name'])) ida_dumper.dump_unit_at(source_unit_computations, int(idc.here())) # if not ops.delShiftedContentRange(*currFile): print(False) pass
def decode_here_clicked(self): inst = idc.here() if not idc.isCode(idc.GetFlags(inst)): print "Not code instruction" else: raw = idc.GetManyBytes(inst, idc.NextHead(inst) - inst) s = to_hex(raw) self.decode_ir(s)
def target_addr_button_clicked(self): ea = idc.here() self.target_addr_field.setText(hex(ea)) cmt = idc.RptCmt(ea) if cmt is not None: if cmt.startswith("//@assert:"): expr = cmt.split(":")[1].lstrip() self.dba_expr_field.setText(expr)
def find_pe(self, cursor=False): """Search IDB for possible MZ/PE headers""" info = idaapi.get_inf_structure() mz_headers = [] # Check current cursor for MZ/PE? if cursor: # Get IDA cursor address addr = idc.here() # Get segment and end address s = idaapi.getseg(addr) e = idc.get_segm_end(addr) # Check for MZ magic if ida_bytes.get_word(addr) == 0x5a4d: # Ensure the PE header is in the segment e_lfanew = ida_bytes.get_dword(addr + 0x3c) if addr + e_lfanew + 1 < e: # Check for PE magic if ida_bytes.get_word(addr + e_lfanew) == 0x4550: # Found possible MZ/PE header mz_headers.append([addr, idc.get_segm_name(addr), info.is_64bit()]) self.ret = mz_headers return self.ret # Search all segments for seg in idautils.Segments(): s = idc.get_segm_start(seg) e = idc.get_segm_end(seg) addr = s while True: # Find first byte of MZ header addr = ida_bytes.find_byte(addr, e-addr, 0x4d, 0) if addr == ida_idaapi.BADADDR or addr >= e: break # Check for MZ magic if ida_bytes.get_word(addr) == 0x5a4d: # Ensure the PE header is in the segment e_lfanew = ida_bytes.get_dword(addr + 0x3c) if addr + e_lfanew + 1 < e: # Check for PE magic if ida_bytes.get_word(addr + e_lfanew) == 0x4550: # Found possible MZ/PE header mz_headers.append([addr, idc.get_segm_name(s), info.is_64bit()]) # Resume search from next address addr += 1 self.ret = mz_headers return self.ret
def init_func_from_ida(self): # get current address # and get the function address from current address current_addr = idc.here() self.func_name = idc.GetFunctionName(current_addr) for chunk in idautils.Chunks(idc.LocByName(self.func_name)): self.func_addr = chunk return self.func_name, self.func_addr
def actionS(ea=None, pointerRange=None): # Mainly for search-type actions or analysis if not ea: ea = here() # if not pointerRange: # global ptrRange # try: # print('@input ptrRange=(%07X, %07X)' % (ptrRange[0], ptrRange[1])) # except Exception: # print('[input ptrRange]') # pointerRange = ptrRange def nextOneWordArr(): d = Data.Data(ea) while (d.ea < pointerRange[1]): content = d.getContent() # case: byte array that's 4 elements. Likely a word if type(content) == list and len(content) == 4 and (d.getSize() / len(content) == 1): break d = Data.Data(d.ea + d.getSize()) if d.ea >= pointerRange[1]: print(False) else: print('%07X' % d.ea) idc.jumpto(d.ea) # output = next.unkptr(here(), end_ea=env['gameFiles'][mt.ea2gf(here())][1], pointerRange=pointerRange, showLabel=False) # output = next.red(here(), end_ea=env['gameFiles'][mt.ea2gf(here())][1]) # output = next.ascii(here()) # if output == idaapi.BADADDR: # print(False) # global v, cur # idaapi.jumpto(v[cur]) # print('%07X [%d/%d]' % (v[cur], cur, len(v))) # cur += 1 # ops.tillName(here(), lambda ea: idc.SetRegEx(ea, "T", 0, idc.SR_user)) # pt.misc.getLZ77CompressedSize(pointerOf(here()) - (1<<31)) def nextCompressedData(ea, end_ea=None): if not end_ea: end_ea = idc.SegEnd(ea) while ea < end_ea: if mt.getLZ77CompressedSize(ea) >= 0: return ea ea += 1 return -1 out = nextCompressedData(ea+1) print('%07X' % (out)) idaapi.jumpto(out)
def getFuncRanges(ea, doAllFuncs): if doAllFuncs: funcs = [] funcGen = idautils.Functions(idc.SegStart(ea), idc.SegEnd(ea)) for i in funcGen: funcs.append(i) funcRanges = [] for i in range(len(funcs) - 1): funcRanges.append((funcs[i], funcs[i + 1])) funcRanges.append((funcs[-1], idc.SegEnd(ea))) return funcRanges else: #just get the range of the current function fakeRanges = [ (idc.GetFunctionAttr(idc.here(), idc.FUNCATTR_START), idc.GetFunctionAttr(idc.here(), idc.FUNCATTR_END)), ] return fakeRanges
def run(self): self.logger.info('Starting up') try: here = idc.here() self.logger.info('Using ea: 0x%08x', here) if not idc.GetMnem(here).startswith('call'): self.logger.info('Not running at a call instruction. Bailing out now') return if idc.GetOpType(here, 0) == idc.o_near: self.logger.info("Cannot (or shouldn't) run when call optype is o_near") return dlg = ApplyCalleeTypeWidget() oldTo = idaapi.set_script_timeout(0) res = dlg.exec_() idaapi.set_script_timeout(oldTo) if res == QtGui.QDialog.DialogCode.Accepted: self.logger.debug('Dialog accepted. Input type: %d', dlg.inputType) else: self.logger.debug('Dialog rejected') return tinfo = None #check user input type if dlg.inputType == dlg.USER_TYPE: decl = self.convertUserType(str(dlg.getUserText())) tinfo = self.getUserDeclType(decl) elif dlg.inputType == dlg.STANDARD_TYPE: tinfo = self.getBuiltinGlobalType() elif dlg.inputType == dlg.LOCAL_TYPE: tinfo = self.getLocalType() else: self.logger.info('Bad user input type') return if tinfo is None: self.logger.debug('Bailing due to null tinfo') return #self.logger.info('Deserialize result: %r', ret) #not 100% sure if i need to explicitly convert from func to funcptr - seemed # to pretty much work without this, but doing it just to be sure if not tinfo.is_funcptr(): self.logger.debug('Converting to func pointer') tinfo.create_ptr(tinfo) typename = idaapi.print_tinfo('', 0, 0, idaapi.PRTYPE_1LINE, tinfo, '', '') self.logger.info('Applying tinfo: "%s"', str(typename)) #both applying callee type & setting op type -> not sure if both are needed? # set op type causes change in hexrays decompilation # apply callee type updates ida's stack analysis ret = idaapi.apply_callee_tinfo(here, tinfo) ret = idaapi.set_op_tinfo2(here, 0, tinfo) self.logger.debug('set_op_tinfo2 result: %r', ret) except Exception, err: self.logger.exception("Exception caught: %s", str(err))
def getrange(args): """ Determines a address range. @param args: the argument list passed to the caller @return: a pair of addresses args can contain one of the following: 1) a tuple containing (first, last) 2) an area_t, containing (start_ea, end_ea) 3) nothing * if the user made a selection ( using Alt-L ), that selection is returned * otherwise from the cursor line until endoffile 4) one address: from address until the end of file 5) two addresses: the range between those addresses The range is specified as (first,last) meaning all addresses satisfying first <= addr < last """ selection, selfirst, sellast = idaapi.read_selection() if isinstance(args, idaapi.area_t): return (args.start_ea, args.end_ea) if len(args) and type(args[0]) == types.TupleType: return args[0] if len(args) and isinstance(args[0], idaapi.area_t): return (args[0].start_ea, args[0].end_ea) argfirst = args[0] if len(args) > 0 and type( args[0]) == types.IntType else None arglast = args[1] if len(args) > 1 and type( args[1]) == types.IntType else None """ afirst alast sel None None 0 -> here, BADADDR None None 1 -> selection None + 0 -> here, BADADDR None + 1 -> selection + None 0 -> afirst, BADADDR + None 1 -> afirst, BADADDR + + 0 -> afirst, alast + + 1 -> afirst, alast """ if argfirst is None: if selection: return (selfirst, sellast) else: return (idc.here(), BADADDR) if arglast is None: return (argfirst, BADADDR) else: return (argfirst, arglast)
def eFunc(self, address=None, *args): if address == None: address = here() func = get_func(address) refs = [ref.frm for ref in XrefsTo(func.startEA, 0)] if len(refs) == 0: RA = self.RA else: RA = refs[0] + ItemSize(refs[0]) self._emulate(func.startEA, RA, *args) print("Euclation done. Below is the Result:") res = self.curUC.reg_read(self.RES_REG) print(">>> function result = %d" % res)
def taintStop(self): Print("Taint Stop pressed!") #Remove the stopping breakpoint if self.taintStop is not None: idc.DelBpt(self.taintStop) #Add a new stopping breakpoint self.taintStop = idc.here() Print( idc.GetDisasm(self.taintStop) ) idc.AddBpt(self.taintStop) idc.SetBptAttr(self.taintStop, idc.BPT_BRK, 0) idc.SetBptCnd(self.taintStop, "interactivemodeCallback.stopTrace()")
def promptForRange(self): # Only run if QT not available, so not bothering with ida7 check #check if a range has already been selected - if so skip prompt if using_ida7api: selstart = idc.read_selection_start() selend = idc.read_selection_end() segstart = idc.get_segm_start(idc.here()) segend = idc.get_segm_end(idc.here()) else: selstart = idc.SelStart() selend = idc.SelEnd() seg = idc.SegStart(idc.here()) self.params.endAddr = idc.SegEnd(idc.here()) if selstart != idc.BADADDR: self.params.startAddr = selstart self.params.endAddr = selend logger.info('Processing range 0x%08x - 0x%08x', self.params.startAddr, self.params.endAddr) else: self.params.startAddr = segstart self.params.endAddr = segend logger.info('Processing current segment only')
def eFunc(self, address=None, retAddr=None, args=[]): if address == None: address = here() func = get_func(address) if retAddr == None: refs = [ref.frm for ref in XrefsTo(func.startEA, 0)] if len(refs) != 0: retAddr = refs[0] + ItemSize(refs[0]) else: print("Please offer the return address.") return self._emulate(func.startEA, retAddr, args) res = self.curUC.reg_read(self.REG_RES) return res
def get_selection(always=True): start = idc.SelStart() end = idc.SelEnd() if idaapi.BADADDR in (start, end): if not always: raise exceptions.SarkNoSelection() ea = idc.here() start = idaapi.get_item_head(ea) end = idaapi.get_item_end(ea) return Selection(start, end)
def getrange(args): """ Determines a address range. @param args: the argument list passed to the caller @return: a pair of addresses args can contain one of the following: 1) a tuple containing (first, last) 2) an area_t, containing (startEA, endEA) 3) nothing * if the user made a selection ( using Alt-L ), that selection is returned * otherwise from the cursor line until endoffile 4) one address: from address until the end of file 5) two addresses: the range between those addresses The range is specified as (first,last) meaning all addresses satisfying first <= addr < last """ selection, selfirst, sellast = idaapi.read_selection() if len(args) and type(args[0])==types.TupleType: return args[0] if len(args) and isinstance(args[0], idaapi.area_t): return (args[0].startEA, args[0].endEA) argfirst = args[0] if len(args)>0 and type(args[0])==types.IntType else None arglast = args[1] if len(args)>1 and type(args[1])==types.IntType else None """ afirst alast sel None None 0 -> here, BADADDR None None 1 -> selection None + 0 -> here, BADADDR None + 1 -> selection + None 0 -> afirst, BADADDR + None 1 -> afirst, BADADDR + + 0 -> afirst, alast + + 1 -> afirst, alast """ if argfirst is None: if selection: return (selfirst, sellast) else: return (idc.here(), BADADDR) if arglast is None: return (argfirst, BADADDR) else: return (argfirst, arglast)
def get_bb(ea=None): # from https://gist.github.com/w4kfu/4252f4c19be573eaaecceb76e1dc0c1c """ Return the basic block if a desired effective address or the current one """ if ea == None: ea = idc.here() f = idaapi.get_func(ea) if not f: return None fc = idaapi.FlowChart(f) for block in fc: if block.startEA <= ea and block.endEA > ea: return block return None
def get_string_ref(ea=None): # from https://gist.github.com/w4kfu/4252f4c19be573eaaecceb76e1dc0c1c """ Get the string references in the given function from current effective address or desired one """ if ea == None: ea = idc.here() func_ea = idc.GetFunctionAttr(ea, FUNCATTR_START) for item_ea in idautils.FuncItems(func_ea): for ref in idautils.DataRefsFrom(item_ea): type = idc.GetStringType(ref) if type not in range(0, 7) and type != 0x2000001: continue yield (item_ea, str(idc.GetString(ref, -1, type)))
def getFuncRanges_ida7(ea, doAllFuncs): if doAllFuncs: funcs = [] funcGen = idautils.Functions(idc.get_segm_start(ea), idc.get_segm_end(ea)) for i in funcGen: funcs.append(i) funcRanges = [] for i in range(len(funcs) - 1): funcRanges.append( (funcs[i], funcs[i+1]) ) funcRanges.append( (funcs[-1], idc.get_segm_end(ea)) ) return funcRanges else: #just get the range of the current function fakeRanges = [( idc.get_func_attr(idc.here(), idc.FUNCATTR_START), idc.get_func_attr(idc.here(), idc.FUNCATTR_END)), ] return fakeRanges
def eFunc(self, address=None, retAddr=None, args=[], force=False): if address == None: address = idc.here() func = idaapi.get_func(address) if retAddr == None: refs = [ref.frm for ref in idautils.XrefsTo(func.start_ea, 0)] if len(refs) != 0: retAddr = refs[0] + idc.ItemSize(refs[0]) else: print("Please offer the return address.") return if not force: address = func.start_ea address = address | 1 if self._is_thumb_ea(address) else address self._emulate(address, retAddr, args) res = self.curUC.reg_read(self.REG_RES) return res
def __init__(self, ea=UseCurrentAddress, name=None): if name is not None and ea != self.UseCurrentAddress: raise ValueError(("Either supply a name or an address (ea). " "Not both. (ea={!r}, name={!r})").format(ea, name)) elif name is not None: ea = idc.LocByName(name) elif ea == self.UseCurrentAddress: ea = idc.here() elif ea is None: raise ValueError("`None` is not a valid address. To use the current screen ea, " "use `Line(ea=Line.UseCurrentAddress)` or supply no `ea`.") self._ea = idaapi.get_item_head(ea) self._comments = Comments(ea)
def __init__(self, ea=UseCurrentAddress, name=None): if name is not None and ea != self.UseCurrentAddress: raise ValueError(("Either supply a name or an address (ea). " "Not both. (ea={!r}, name={!r})").format(ea, name)) elif name is not None: ea = idc.LocByName(name) if ea == idc.BADADDR: raise exceptions.SarkNoFunction( "The supplied name does not belong to an existing function. " "(name = {!r})".format(name)) elif ea == self.UseCurrentAddress: ea = idc.here() elif ea is None: raise ValueError("`None` is not a valid address. To use the current screen ea, " "use `Function(ea=Function.UseCurrentAddress)` or supply no `ea`.") self._func = get_func(ea) self._comments = Comments(self)
def custom_out(self): global last_saved, backup_file, skel_settings if last_saved < (time.time() - skel_settings.save_timeout): print "[+] Saving IDB" SaveBase(backup_file, idaapi.DBFL_TEMP) print "[+] Updating database" update_poli_db() last_saved = time.time() addr = idc.here() if addr < self.curfuncstart or addr > self.curfuncend: ea = ScreenEA() if idaapi.get_func(ea) is not None: cfs = idaapi.get_func(ea).startEA cfe = idaapi.get_func(ea).endEA if cfe == BADADDR: cfe = idaapi.get_func(self.curfuncS).endEA if cfe != BADADDR and cfs != BADADDR: self.curfuncstart = cfs self.curfuncend = cfe print analyzeFunction(addr)[0] return idaapi.IDP_Hooks.custom_out(self)
def main(doAllFuncs=True): #doAllFuncs=False #jayutils.configLogger(__name__, logging.DEBUG) jayutils.configLogger(__name__, logging.INFO) logger = jayutils.getLogger('stackstrings') logger.debug('Starting up now') filePath = jayutils.getInputFilepath() if filePath is None: self.logger.info('No input file provided. Stopping') return vw = jayutils.loadWorkspace(filePath) ea = idc.here() res = -1 if using_ida7api: res = idc.ask_yn(0, 'Use basic-block local aggregator') else: res = idc.AskYN(0, 'Use basic-block local aggregator') if res == idaapi.ASKBTN_CANCEL: print 'User canceled' return uselocalagg = (res == 1) ranges = getFuncRanges(ea, doAllFuncs) for funcStart, funcEnd in ranges: try: logger.debug('Starting on function: 0x%x', funcStart) stringList = runStrings(vw, funcStart, uselocalagg) for node, string in stringList: if isLikelyFalsePositiveString(string): #if it's very likely a FP, skip annotating continue print '0x%08x: %s' % (node[0], string) #print '0x%08x: 0x%08x: %s %s' % (node[0], node[1], binascii.hexlify(string), string) if using_ida7api: idc.set_cmt(node[0], string.strip(), 0) else: idc.MakeComm(node[0], string.strip()) except Exception, err: logger.exception('Error during parse: %s', str(err))
def taintStart(self): Print("Taint Start pressed!") #Remove the starting breakpoint if self.taintStart is not None: idc.DelBpt(self.taintStart) #Add a new starting breakpoint self.taintStart = idc.here() instruction = idc.GetDisasm(self.taintStart) Print( instruction ) idc.AddBpt(self.taintStart) idc.SetBptAttr(self.taintStart, idc.BPT_BRK, 0) callbackAddr = "interactivemodeCallback.startTrace()" customCallbackFuncs = ['ReadFile','recv'] for callbackFunc in customCallbackFuncs: if callbackFunc in instruction: callbackAddr = "interactivemodeCallback." + callbackFunc + "()" Print("Found callback function %s for interactive mode" % callbackAddr) break idc.SetBptCnd(self.taintStart, callbackAddr)
def preprocess(self, name): #checkupdates() # XXX : enable it after correct timestamp management self.cmdname = name self.addr = idc.here() return 0
def show_xrefs_to(*args): distance = idaapi.asklong(4, 'Distance To Source') show_xref_graph(idc.here(), to=True, distance=distance)
def show_xrefs_from(*args): distance = idaapi.asklong(4, 'Distance From Source') show_xref_graph(idc.here(), to=False, distance=distance)
# re-propagate after gluing pre/post increments s = simplifier(f, COLLECT_ALL) s.propagate_all(PROPAGATE_REGISTERS | PROPAGATE_FLAGS) #~ print '5' s = simplifier(f, COLLECT_ALL) s.propagate_all(PROPAGATE_ANY | PROPAGATE_SINGLE_USES) #~ print '6' # eliminate restored registers. during this pass, the simplifier also collects # stack variables because registers may be preserved on the stack. s = simplifier(f, COLLECT_REGISTERS | COLLECT_VARIABLES) s.process_restores() # ONLY after processing restores can we do this; any variable which is assigned # and never used again is removed as dead code. s = simplifier(f, COLLECT_REGISTERS) s.remove_unused_definitions() #~ print '7' # rename registers to pretty names. r = renamer(f, RENAME_REGISTERS) r.fct_arguments = t.fct_arguments r.wrap_variables() return f print 'decompile:', idc.here() func = idaapi.get_func(idc.here()) g = GraphViewer(func)
def preprocess(self, name): # checkupdates() self.cmdname = name self.addr = idc.here() return 0
def main(): print 'here:', idc.here() func = idaapi.get_func(idc.here()) arch = arch_intel() f = flow_t(func.startEA, arch) f.prepare_blocks() print '----1----' print str(f) print '----1----' check_stack_alignment(f) # tag all registers so that each instance of a register can be uniquely identified. # during this process we also take care of matching registers to their respective # function calls. #~ conv = callconv.stdcall() conv = callconv.systemv_x64_abi() t = tagger(f, conv) t.tag_all() print '1' # remove special flags (eflags) definitions that are not used, just for clarity s = simplifier(f, COLLECT_FLAGS) s.remove_unused_definitions() print '2' # After registers are tagged, we can replace their uses by their definitions. this # takes care of eliminating any instances of 'esp' which clears the way for # determining stack variables correctly. s = simplifier(f, COLLECT_ALL) s.propagate_all(PROPAGATE_STACK_LOCATIONS) s = simplifier(f, COLLECT_REGISTERS) s.remove_unused_definitions() print '3' # rename stack variables to differenciate them from other dereferences. r = renamer(f, RENAME_STACK_LOCATIONS) r.wrap_variables() # collect function arguments that are passed on the stack s = simplifier(f, COLLECT_ALL) s.collect_argument_calls(conv) print '3.1' # This propagates special flags. s = simplifier(f, COLLECT_ALL) s.propagate_all(PROPAGATE_REGISTERS | PROPAGATE_FLAGS) print '4' # At this point we must take care of removing increments and decrements # that are in their own statements and "glue" them to an adjacent use of # that location. s = simplifier(f, COLLECT_ALL) s.glue_increments() # re-propagate after gluing pre/post increments s = simplifier(f, COLLECT_ALL) s.propagate_all(PROPAGATE_REGISTERS | PROPAGATE_FLAGS) print '5' s = simplifier(f, COLLECT_ALL) s.propagate_all(PROPAGATE_ANY | PROPAGATE_SINGLE_USES) print '6' # eliminate restored registers. during this pass, the simplifier also collects # stack variables because registers may be preserved on the stack. s = simplifier(f, COLLECT_REGISTERS | COLLECT_VARIABLES) s.process_restores() # ONLY after processing restores can we do this; any variable which is assigned # and never used again is removed as dead code. s = simplifier(f, COLLECT_REGISTERS) s.remove_unused_definitions() print '7' # rename registers to pretty names. r = renamer(f, RENAME_REGISTERS) r.fct_arguments = t.fct_arguments r.wrap_variables() # after everything is propagated, we can combine blocks! f.combine_blocks() print '----2----' print str(f) print '----2----'