def search_sub_esp_instr(ea): func = idaapi.get_func(ea) name = idc.GetFunctionName(ea) end = func.endEA start = func.startEA #print('%s - %s: %s()' %(hex(start), hex(end), name)) #patten = '81 EC' #addr = idc.FindBinary(x, SEARCH_DOWN | SEARCH_NEXT, patten) bfind_sub_esp = False sub_esp_addr = None add_esp_addr = None x = start while x < end: asm = idc.GetDisasm(x) y = x + idc.ItemSize(x) if bfind_sub_esp == False: if asm.startswith('sub esp,') or asm.startswith( 'sub rsp,'): #print('%s(): %s => %s' %(name, hex(x), asm)) #sub esp, 540h t = idc.GetOpType(x, 1) if t != idc.o_imm: continue bfind_sub_esp = True sub_esp_addr = x add_esp_asm = asm.replace('sub', 'add') else: #搜索后续指令应该有leave指令 或 #add esp, 540h if asm.startswith(add_esp_asm): add_esp_addr = x x = y break elif asm == 'leave': break x = y if add_esp_addr is not None: #搜索后续指令不再对esp操作 while x < end: asm = idc.GetDisasm(x) y = x + idc.ItemSize(x) if re.search('esp', asm): print('why to here') pass x = y return [sub_esp_addr, add_esp_addr]
def parseArgs(self, ref): i = self.trackBackLimit argsToParse = self.func.nargs argv = [] ref_p = ref while (i and argsToParse): insSize, dataSize = self.func.getInstrDataPair(self.func.nargs-argsToParse) if (insSize > self.func.ESCAPE_CODE_BEGIN): argsToParse -= 1 else: if (dataSize > insSize): self.log(3, "[!!] invalid argument size pair (%d, %d) for arg no: %d" % (insSize, dataSize, self.func.nargs-argsToParse)) raise ref_p = idc.PrevHead(ref_p, 0) if ref_p == BADADDR: break disstr = idc.GetDisasm(ref_p) if disstr.startswith(self.func.argPassMech) and (idc.ItemSize(ref_p) == insSize): arVal = self.getDataValue(ref_p + insSize - dataSize, dataSize) argv.append(arVal) self.log(4, "Arg found: (0x%x)" % arVal) argsToParse -= 1 if not argsToParse: break if len(self.getXrefs(ref_p)) == 1: nref = self.getXrefs(ref_p)[0] refins = idc.GetDisasm(nref) if refins.startswith(self.interConnectInstr): ref_p = nref i -= 1 if len(argv) > 0: self.log(4, "[-] Adding args for call at 0x%x->%s" % (ref,repr(argv))) self.params[ref] = argv
def patch_32_esp(addr, sub_value, is_sub_esp): count = idc.ItemSize(addr) #get value v = idc.GetOperandValue(addr, 1) #print(hex(v)) if v == -1: print('get value error') return if count == 3: #.text:0804867C 83 EC 18 sub esp, 18h off = 0xff - v if sub_value < off: idc.PatchByte(addr + 2, v + sub_value) else: idc.PatchByte(addr + 2, 0xff) idc.MakeCode(addr) else: #.text:0804875B 81 EC 30 02 00 00 sub esp, 230h idc.PatchDword(addr + 2, v + sub_value) idc.MakeCode(addr) if is_sub_esp != 0: print('patch [sub esp, %s] ok, addr: %s' % (hex(v), hex(addr))) else: print('patch [add esp, %s] ok, addr: %s' % (hex(v), hex(addr))) return
def insertRelocatedSymbol(M, D, reloc_dest, offset, seg_offset, new_eas, itemsize=-1): pf = idc.GetFlags(reloc_dest) DS = D.symbols.add() DS.base_address = offset+seg_offset itemsize = int(itemsize) if itemsize == -1: itemsize = int(idc.ItemSize(offset)) DEBUG("Offset: {0:x}, seg_offset: {1:x}\n".format(offset, seg_offset)) DEBUG("Reloc Base Address: {0:x}\n".format(DS.base_address)) DEBUG("Reloc offset: {0:x}\n".format(offset)) DEBUG("Reloc size: {0:x}\n".format(itemsize)) if idc.isCode(pf): DS.symbol_name = "sub_"+hex(reloc_dest) DS.symbol_size = itemsize DEBUG("Code Ref: {0:x}!\n".format(reloc_dest)) if reloc_dest not in RECOVERED_EAS: new_eas.add(reloc_dest) elif idc.isData(pf): reloc_dest = handleDataRelocation(M, reloc_dest, new_eas) DS.symbol_name = "dta_"+hex(reloc_dest) DS.symbol_size = itemsize DEBUG("Data Ref!\n") else: reloc_dest = handleDataRelocation(M, reloc_dest, new_eas) DS.symbol_name = "dta_"+hex(reloc_dest) DS.symbol_size = itemsize DEBUG("UNKNOWN Ref, assuming data\n")
def findCodeCavez(self, segment=".text"): start = idc.SegByBase(idc.SegByName(segment)) if start == idc.BADADDR: print "Can't find segment %s" % (segment) return end = idc.SegEnd(start) curr_addr = start curr_size = 0 biggest_addr = idc.BADADDR biggest_size = 0 results = [] while start < end: new_addr = idc.FindText(start + curr_size, idc.SEARCH_DOWN, 0, 0, "align") if start == new_addr: break curr_size = idc.ItemSize(new_addr) if curr_size > biggest_size: biggest_addr = new_addr biggest_size = curr_size start = new_addr results.append((new_addr, curr_size)) return results return biggest_addr, biggest_size
def create_state(endEA, startEA=None): ''' Quick and dirty representation of stack and regs from start of function to this ea. :param endEA: The EA of which you want to compute the stack up until :param startEA: Optional param of the beginning of the function - sometimes necessary if ida can't compute and you can :return A newly created TraceState ''' if not startEA: startEA = idaapi.get_func(endEA).startEA state = TraceState() ea = startEA while ea < endEA: mnemonic = idc.GetMnem(ea) if 'mov' in mnemonic: handle_mov(ea, state) elif ('xor' in mnemonic and unsafe_get_reg_fam(get_opnd_replacement(ea, POS_FIRST)) == unsafe_get_reg_fam(get_opnd_replacement(ea, POS_SECOND))) or \ ('lea' in mnemonic and idc.GetOpnd(ea, POS_SECOND) == '[0]') or \ ('sub' in mnemonic and get_opnd_replacement(ea, POS_FIRST) == get_opnd_replacement(ea, POS_SECOND)): reg = unsafe_get_reg_fam(get_opnd_replacement(ea, POS_FIRST)) if reg: state.regs[reg[0]] = (0, ea) elif 'lea' in mnemonic: handle_lea(ea, state) elif 'push' in mnemonic: handle_push(ea, state) elif 'pop' in mnemonic: handle_pop(ea, state) ea += idc.ItemSize(ea) return state
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 addDataReference(M, I, inst, dref, new_eas): if inValidSegment(dref): if isExternalReference(dref): fn = getFunctionName(dref) fn = handleExternalRef(fn) if isExternalData(fn): I.ext_data_name = fn sys.stdout.write( "EXTERNAL DATA REF FROM {0:x} to {1}\n".format(inst, fn)) else: I.ext_call_name = fn sys.stdout.write( "EXTERNAL CODE REF FROM {0:x} to {1}\n".format(inst, fn)) elif isInternalCode(dref): I.call_target = dref if dref not in RECOVERED_EAS: new_eas.add(dref) else: dref_size = idc.ItemSize(dref) DEBUG("\t\tData Ref: {0:x}, size: {1}\n".format(dref, dref_size)) I.data_offset = handleDataRelocation(M, dref, new_eas) else: DEBUG("WARNING: Data not in valid segment {0:x}\n".format(dref))
def patch_to_call_puts(addr): #.text:0000114D E8 DE FE FF FF call _printf count = idc.ItemSize(addr) #get value v = idc.GetOperandValue(addr, 0) #要CALL的地址 - 下一条指令地址 = E8 后面的硬编码 plt_names = idautils.Names() for address, name in plt_names: if name == '.puts': puts_addr = address elif name == '.printf': printf_addr = address op = puts_addr - (addr + count) op = op & 0xffffffff #print('op: %s' %hex(op)) idc.PatchDword(addr + 1, op) idc.MakeCode(addr) print('patch [call _printf] ok, addr: %s' % hex(addr)) return
def ExecuteSymbolicSingleStep(addr, state=INIT_REG): size = idc.ItemSize(addr) code = idc.GetManyBytes(addr, size) loc_db = LocationDB() base = addr try: ins = mn_x86.dis(bin_stream_str(code, base_address=base), 64, base) except: return state.copy() ira = machine.ira(loc_db) ircfg = ira.new_ircfg() try: ira.add_instr_to_ircfg(ins, ircfg) sb = SymbolicExecutionEngine(ira, state) symbolic_pc = sb.run_at(ircfg, base) except: return state.copy() ret = state.copy() for key, value in sb.modified(): if isinstance(value, ExprOp) and value.op == "call_func_ret": value = ExprInt(0, 64) ret[key] = value return ret
def patch_64_rsp(addr, sub_value, is_sub_rsp): count = idc.ItemSize(addr) #get value v = idc.GetOperandValue(addr, 1) #print(hex(v)) if v == -1: print('get value error') return if count == 4: #.text:000055BBF4127FD9 48 83 EC 10 sub rsp, 10h off = 0xff - v if sub_value < off: idc.PatchByte(addr + 3, v + sub_value) else: idc.PatchByte(addr + 3, 0xff) idc.MakeCode(addr) else: #.text:00007EFEA44A5310 48 81 EC 20 01 00 00 sub rsp, 120h idc.PatchDword(addr + 3, v + sub_value) idc.MakeCode(addr) if is_sub_rsp != 0: print('patch [sub rsp, %s] ok, addr: %s' % (hex(v), hex(addr))) else: print('patch [add rsp, %s] ok, addr: %s' % (hex(v), hex(addr))) return
def _execution_tree_onClickItem(self, item): address = int(item.text(1), 16) is_api = int(item.text(5), 16) tid = int(item.text(6), 16) target = int(item.text(3), 16) callee_id = int(item.text(7), 16) if is_api > 0: for thread in self._maze['process']['threads']: if tid == thread['tid']: for i in range(len(thread['api_parameters'])): if thread['api_parameters'][i][ 'target'] == target and thread[ 'api_parameters'][i]['id'] == callee_id: if thread['api_parameters'][i]['xref'] == ( address + idc.ItemSize(address)): if 'parameters' in thread['api_parameters'][i]: cmt = item.text(0).encode('ascii') + "\n" for param in thread['api_parameters'][i][ 'parameters']: cmt += (param['name'] + " : " + str(param['data']) + "\n").encode('ascii') idc.MakeComm(address, cmt) break idc.Jump(address)
def createBasicBlockXRefsTo(startAddress, endAddress, minSegAddress, maxSegAddress, func=None): function_xrefs = {} data_xrefs = {} comments = {} strucs = {} stackframe = {} operand_view = {} hidden_areas = {} references = {} enums = {} ea = startAddress while ea < endAddress: get_function_xrefs_at_ea(startAddress, ea, function_xrefs, minSegAddress, maxSegAddress) get_data_xrefs_at_ea(startAddress, ea, data_xrefs, function_xrefs, minSegAddress, maxSegAddress) add_comments_at_ea(startAddress, ea, comments) get_hidden_area_at_ea(startAddress, ea, hidden_areas) get_struc_enum_xrefs_at_ea(startAddress, ea, strucs, enums, stackframe, func) get_reference_xrefs_at_ea(startAddress, ea, references) # # OPERAND VIEW # operand_view[ea - startAddress] = getOperandView(ea) # next instruction # (a, size) = getInvariantsBytes(ea, ida_function_bytes_cache[ea - startAddress:]) ea += idc.ItemSize(ea) return (function_xrefs, data_xrefs, comments, strucs, enums, operand_view, hidden_areas, stackframe, references)
def GetItemContaining(ea): previous_item = idc.PrevHead(ea) if previous_item is not idc.BADADDR: previous_item_size = idc.ItemSize(previous_item) if previous_item_size > 0 and ea < previous_item + previous_item_size: return previous_item return ea
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 handle_call(self, state): '''Updates the state of the stack string finding based on a call instruction''' stack_pointer = idc.GetSpd(state.ea) next_ea = state.ea + idc.ItemSize(state.ea) stack_pointer_delta = idc.GetSpDiff(next_ea) if stack_pointer is not None and stack_pointer_delta is not None: next_reg = tracingutils.get_reg_fam(idc.GetOpnd( next_ea, POS_FIRST)) # Caller cleanup handling, vulnerable to instruction reordering though. if next_reg and 'esp' in next_reg and "add" in idc.GetMnem( next_ea).lower(): stack_pointer_delta += idc.GetSpDiff(next_ea + idc.ItemSize(next_ea)) for index in xrange(stack_pointer, stack_pointer + stack_pointer_delta): if index in state.stack: del state.stack[index]
def is_end_of_flow(self, instruction): """Return whether the last instruction processed end the flow.""" next_addr = instruction.ip + idc.ItemSize(instruction.ip) next_addr_flags = idc.GetFlags(next_addr) if idc.isCode(next_addr_flags) and idc.isFlow(next_addr_flags): return False return True
def data(self): h = self.keleven for ea in idautils.FuncItems(self.offset): h = self._cycle(h, idc.Byte(ea)) # skip additional bytes of any instruction that contains an offset in it if idautils.CodeRefsFrom(ea, False) or idautils.DataRefsFrom(ea): continue for i in range(ea + 1, ea + idc.ItemSize(ea)): h = self._cycle(h, idc.Byte(i)) return h
def _scan_block(self, block, fname): current_bb_start = block.startEA instructions = idautils.Heads(block.startEA, block.endEA) last_instruction = None last_instruction_size = None call_instructions = [] next_instruction = None for i in instructions: last_instruction = i last_instruction_size = idc.ItemSize(i) mnem = idc.GetMnem(i) is_call = mnem == "call" is_int = mnem == "int" if (is_call or is_int) and i != block.endEA: if not ida_graph: next_instruction = i + last_instruction_size bb_size = next_instruction - current_bb_start ct = [] if is_call: call_instructions = [(i, next_instruction)] ct = self._get_call_target(call_instructions) self._invoke_cbs(current_bb_start, i, bb_size, ct, [next_instruction], fname) # start a new translation block current_bb_start = idc.NextHead(i, block.endEA + 1) else: next_instruction = i + last_instruction_size call_instructions.append((i, next_instruction)) if current_bb_start == idc.BADADDR: current_inst = last_instruction + last_instruction_size self._invoke_cbs(current_inst, idc.BADADDR, 0, [], [], fname) # the call instruction probably doesn't return. return if current_bb_start < block.endEA: bb_size = block.endEA - current_bb_start ct = [] succs = [] for succ_block in block.succs(): succs.append(succ_block.startEA) if not ida_graph and mnem == "call": call_instructions = [(last_instruction, succs[0])] ct = self._get_call_target(call_instructions) if not ida_graph: self._invoke_cbs(current_bb_start, last_instruction, bb_size, ct, succs, fname) else: self._invoke_cbs(current_bb_start, i, bb_size, ct, succs, fname)