def set_jit_info(self, method_id, start): end = self.get_func_end(start) if (end < start or end - start > self.jit_max_size): return method = next((x for x in self.as3dump if x["id"] == method_id), None) if (method is None): return stackvars = self.get_stack_vars(start, end) save_eip = self.get_save_eip(method, stackvars) ea = start while (ea < end): if ("ebp" in idc.print_operand(ea, 0) and idc.get_operand_type(ea, 1) == idc.o_imm): op0 = idc.get_operand_value(ea, 0) op1 = idc.get_operand_value(ea, 1) if (op0 == save_eip): idc.set_cmt(ea, method["instructions"][op1], 0) ea += idc.get_item_size(ea)
def find_main_x86(self): start = ida_ida.inf_get_start_ea() fn = idaapi.get_func(start) f_start, f_end = fn.start_ea, fn.end_ea eas = list(idautils.Heads(f_start, f_end)) mnem = idc.print_insn_mnem(eas[-1]) if mnem == 'jmp': return idc.get_operand_value(eas[-1], 0) elif mnem == 'call': for i in range(len(list(eas)) - 2, -1, -1): mnem = idc.print_insn_mnem(eas[i]) if mnem == 'push': return idc.get_operand_value(eas[i], 0) else: print(idc.GetDisasm(eas[-1])) return 0
def getMinorDispatchTableAddress(ea): """find address of last lea in function""" start = idc.get_func_attr(ea, idc.FUNCATTR_START) end = idc.prev_head(idc.get_func_attr(ea, idc.FUNCATTR_END), start) res = prevMnemonic(end, 'lea', start) assert res != idc.BADADDR return idc.get_operand_value(res, 1)
def find_lua_function_array(start, end): for head in idautils.Heads(start, end): disasm = idc.generate_disasm_line(head, 2) if disasm.startswith('lea '): result = idc.get_operand_value(head, 1) return result raise RuntimeError('Unable to find Lua function array near 0x%08x' % start)
def disassemble_func(address): func_dis = {} symbolic_calls = {} inst_num = 0 flags = get_func_flags(address) last_addr = address asm = '' for addr in FuncItems(address): ins = DecodeInstruction(addr) # print('decoded') byte_instr = get_bytes(addr, ins.size) asm = asm + str(binascii.hexlify(byte_instr)) inst_num = inst_num + 1 last_addr = addr if idc.print_insn_mnem(addr) in ["call"]: # print('Call:'+str(ins)) call_address = idc.get_operand_value(addr, 0) # print(call_address) start_addr = first_func_chunk(call_address) symbolic_calls[start_addr] = idc.get_func_name(call_address) func_dis['bytecode'] = asm func_dis['symbolic_calls'] = symbolic_calls func_dis['start_address'] = first_fusnc_chunk(address) func_dis['end_address'] = last_addr func_dis['segment_address'] = get_segm_start(address) func_dis['segment_name'] = SegName(address) func_dis['name'] = idc.get_func_name(address) func_dis['inst_numbers'] = inst_num # attenzione sta cosa ci da la roba riconosciuta con flirt. func_dis['library_flag'] = flags & FUNC_LIB return func_dis
def handle_mov(self, state): """Updates the state of the stack string finding based on a mov instruction""" op1 = tracing.get_opnd_replacement(state.ea, POS_FIRST) if '[' in op1: offset = tracing.get_operand_value_replacement(state.ea, POS_FIRST, state) self.set_stack(offset, state.ea, POS_SECOND, state) else: reg = tracing.get_reg_fam(op1) type_ = idc.get_operand_type(state.ea, POS_SECOND) if reg: if type_ != idc.o_phrase and type_ != idc.o_displ: if type_ == idc.o_reg: reg2 = tracing.get_reg_fam(tracing.get_opnd_replacement(state.ea, POS_SECOND)) if reg2 and reg2[0] in state.regs: val = state.regs[reg2[0]][0] else: val = None else: val = idc.get_operand_value(state.ea, POS_SECOND) if val is not None: state.regs[reg[0]] = (val, state.ea) else: offset = tracing.get_operand_value_replacement(state.ea, POS_SECOND, state) value = state.stack.get(offset, None) if value is not None: state.regs[reg[0]] = value else: self.clear_reg_if_needed(reg, state.regs)
def lookForOpArgs(self, start, end): for head in idautils.Heads(start, end): try: for i in range(2): if using_ida7api: t = idc.get_operand_type(head, i) else: t = idc.GetOpType(head, i) if t == idc.o_imm: if using_ida7api: opval = idc.get_operand_value(head, i) else: opval = idc.GetOperandValue(head, i) if self.params.useXORSeed: opval = opval ^ self.params.XORSeed for h in self.params.hashTypes: hits = self.dbstore.getSymbolByTypeHash( h.hashType, opval) for sym in hits: logger.info("0x%08x: %s", head, str(sym)) self.addHit(head, sym) self.markupLine(head, sym, self.params.useDecompiler) except Exception as err: logger.exception("Exception: %s", str(err))
def find_WdfControlDeviceInitAllocate(): function_offset = OFFSET_WdfControlDeviceInitAllocate call_pfn = None try: for xref in idautils.XrefsTo(g_vars["_WDFFUNCTIONS"] + function_offset): call_pfn = xref.frm except StopIteration: # this is case 2 or 3 pass if call_pfn is None: call_pfn = find_wdf_callback_through_immediate("call", 0, function_offset) if call_pfn: idc.OpStroffEx(call_pfn, 0, (idaapi.get_struc_id("_WDFFUNCTIONS")), 0) if call_pfn is None: call_pfn = find_wdf_callback_through_immediate("mov", 1, function_offset) if call_pfn: idc.OpStroffEx(call_pfn, 1, (idaapi.get_struc_id("_WDFFUNCTIONS")), 0) lea_sddl = find_function_arg(call_pfn, "lea", "r8", 0) unicode_sddl = idc.get_operand_value(lea_sddl, 1) idc.set_name(unicode_sddl, 'control_device_sddl') assign_struct_to_address(unicode_sddl, "_UNICODE_STRING") print(("Control Device SDDL at: ", hex(unicode_sddl)))
def value(self): """ Retrieve the value of the operand as it is currently in the cpu_context. NOTE: We can't cache this value because the value may change based on the cpu context. :return int: An integer of the operand value. """ if self.is_hidden: return None if self.is_immediate: value = idc.get_operand_value(self.ip, self.idx) # Create variable/reference if global. if idc.is_loaded(value): self._cpu_context.variables.add(value, reference=self.ip) return value if self.is_register: value = self._cpu_context.registers[self.text] # Record reference if register is a variable address. if value in self._cpu_context.variables: self._cpu_context.variables[value].add_reference(self.ip) return value # TODO: Determine if this is still necessary. # FS, GS (at least) registers are identified as memory addresses. We need to identify them as registers # and handle them as such if self.type == idc.o_mem: if "fs" in self.text: return self._cpu_context.registers.fs elif "gs" in self.text: return self._cpu_context.registers.gs # If a memory reference, return read in memory. if self.is_memory_reference: addr = self.addr # Record referenc if address is a variable address. if addr in self._cpu_context.variables: self._cpu_context.variables[addr].add_reference(self.ip) # If a function pointer, we want to return the address. # This is because a function may be seen as a memory reference, but we don't # want to dereference it in case it in a non-call instruction. # (e.g. "mov esi, ds:LoadLibraryA") # NOTE: Must use internal function to avoid recursive loop. if utils.is_func_ptr(addr): return addr # Return empty if not self.width: logger.debug("Width is zero for {}, returning empty string.".format(self.text)) return b"" # Otherwise, dereference the address. value = self._cpu_context.mem_read(addr, self.width) return utils.struct_unpack(value) raise FunctionTracingError("Invalid operand type: {}".format(self.type), ip=self.ip)
def get_opnd_replacement(ea, pos): """ A replacement for IDA's idc.print_operand that can de-alias register names""" # TODO: Support renames in other operand types if idc.get_operand_type(ea, pos) == idc.o_reg: return idaapi.get_reg_name(idc.get_operand_value(ea, pos), get_byte_size_of_operand(ea, pos)) else: return idc.print_operand(ea, pos)
def getDispatchCode(ea): # get dispatch code out of an instruction first, second = (idc.print_operand(ea, 0), idc.get_operand_value(ea, 1)) if first == 'eax': return second raise ValueError( "Search resulted in address %08x, but instruction '%s' does fulfill requested constraints" % (ea, idc.print_insn_mnem(ea)))
def is_libc_syscall(self, mnemonic, instr_addr): """ Is it a libc _syscall()? """ if mnemonic in self.call_mnemonics: target = idc.get_operand_value(instr_addr, 0) target_name = idc.GetFunctionName(target) return target_name in self.syscall_functions
def set_types(self): """ handle (EFI_BOOT_SERVICES *) type """ RAX = 0 O_REG = 1 O_MEM = 2 EFI_BOOT_SERVICES = "EFI_BOOT_SERVICES *" empty = True for service in self.gBServices: for address in self.gBServices[service]: ea = address num_of_attempts = 10 for _ in range(num_of_attempts): ea = idc.prev_head(ea) if (idc.GetMnem(ea) == "mov" and idc.get_operand_type(ea, 1) == O_MEM): if (idc.get_operand_type(ea, 0) == O_REG and idc.get_operand_value(ea, 0) == RAX): gBs_var = idc.get_operand_value(ea, 1) gBs_var_type = idc.get_type(gBs_var) if (gBs_var_type == "EFI_BOOT_SERVICES *"): empty = False print("[{0}] EFI_BOOT_SERVICES->{1}".format( hex(address).replace("L", ""), service)) print("\t [address] {0}".format( hex(gBs_var).replace("L", ""))) print("\t [message] type already applied") break if idc.SetType(gBs_var, EFI_BOOT_SERVICES): empty = False old_name = idc.Name(gBs_var) idc.MakeName(gBs_var, "gBs_" + old_name) print("[{0}] EFI_BOOT_SERVICES->{1}".format( hex(address).replace("L", ""), service)) print("\t [address] {0}".format( hex(gBs_var).replace("L", ""))) print("\t [message] type successfully applied") else: empty = False print("[{0}] EFI_BOOT_SERVICES->{1}".format( hex(address).replace("L", ""), service)) print("\t [address] {0}".format( hex(gBs_var).replace("L", ""))) print("\t [message] type not applied") break if empty: print(" * list is empty")
def _get_decompiled_function(offset: int) -> "ida_hexrays.cfuncptr_t": """ Attempt to decompile the function containing offset and return the obtained cfuncptr_t object. Additionaly sets the type for all decompiled functions. :param offset: offset of interest :return: a cfuncptr_t object or None """ # This requires Hexrays decompiler, load it and make sure it's available before continuing. if not ida_hexrays.init_hexrays_plugin(): if is_x86_64(): idc.load_and_run_plugin("hexrays", 0) or idc.load_and_run_plugin( "hexx64", 0) else: idc.load_and_run_plugin("hexarm", 0) or idc.load_and_run_plugin( "hexarm64", 0) if not ida_hexrays.init_hexrays_plugin(): raise RuntimeError("Unable to load Hexrays decompiler.") decompiled = None offsets_to_decompile = [offset] # LIFO list of offsets to try to decompile offsets_attempted = set( ) # Offsets already attempted to decompile, whether successful or not offsets_decompiled = set() # Set of offsets that successfully decompiled # Continue trying to decompile until the list of offsets to decompile is empty or we get an error we can't handle # TODO: Determine what errors we can actually handle while offsets_to_decompile: _offset = offsets_to_decompile.pop() # This check means we have probably hit a snag preventing us from decompiling all together, and should prevent # an endless loop of continuously trying to decompile if _offset in offsets_decompiled: # already decompiled, but still causing a problem? raise RuntimeError( "Unable to decompile function 0x{:X}".format(offset)) offsets_attempted.add(_offset) decompiled, hf = _decompile(_offset) if decompiled and not hf.code: # successful decompilation, add to set of decompiled, and remove from attempted # set the type _set_decompiled_func_type(_offset, decompiled) offsets_decompiled.add(_offset) offsets_attempted.remove(_offset) else: # unsuccessful... if not hf.code in DECOMPILE_ERRORS: # cannot possibly recover raise RuntimeError( "Unable to decompile function at 0x{:X}".format(offset)) # Can possibly recover by decompiling called functions # add the current offset back to the LIFO list to try decompiling a second time offsets_to_decompile.append(_offset) # get the address where the analysis failed, pull its operand, and add to the stack call_ea = idc.get_operand_value(hf.errea, 0) # can't continue if this address was already attempted if call_ea in offsets_attempted: raise RuntimeError( "Unable to decompile function at 0x{:X}".format(offset)) offsets_to_decompile.append(call_ea) return decompiled
def set_types(self): """ handle (EFI_BOOT_SERVICES *) type and (EFI_SYSTEM_TABLE *) for x64 images """ RAX = 0 O_REG = 1 O_MEM = 2 EFI_BOOT_SERVICES = 'EFI_BOOT_SERVICES *' EFI_SYSTEM_TABLE = 'EFI_SYSTEM_TABLE *' empty = True for service in self.gBServices: for address in self.gBServices[service]: ea = address num_of_attempts = 10 for _ in range(num_of_attempts): ea = idc.prev_head(ea) if (idc.print_insn_mnem(ea) == 'mov' and idc.get_operand_type(ea, 1) == O_MEM): if (idc.get_operand_type(ea, 0) == O_REG and idc.get_operand_value(ea, 0) == RAX): gvar = idc.get_operand_value(ea, 1) gvar_type = idc.get_type(gvar) # if (EFI_SYSTEM_TABLE *) if ((gvar_type != 'EFI_SYSTEM_TABLE *') and (idc.print_operand( address, 0).find('rax') == 1)): if self._find_est(gvar, ea, address): print( f'[ {gvar:016X} ] Type ({EFI_SYSTEM_TABLE}) successfully applied' ) empty = False break # otherwise it (EFI_BOOT_SERVICES *) if (gvar_type != 'EFI_BOOT_SERVICES *' and gvar_type != 'EFI_SYSTEM_TABLE *'): if idc.SetType(gvar, EFI_BOOT_SERVICES): empty = False idc.set_name(gvar, f'gBS_{gvar:X}') print( f'[ {gvar:016X} ] Type ({EFI_BOOT_SERVICES}) successfully applied' ) break if empty: print(' * list is empty')
def find_iat_ptrs(self, pe, image_base, size, get_word): """Find all likely IAT pointers""" iat_ptrs = [] next_offset = image_base while next_offset < image_base + size: offset = next_offset next_offset = ida_bytes.next_addr(offset) # Attempt to read the current instruction's effective memory address operand (if present) mnem = idc.print_insn_mnem(offset).lower() ptr = 0 if mnem in ["call", "push", "jmp"]: if idc.get_operand_type(offset, 0) == idc.o_mem: # Get memory offset for branch instructions ptr = idc.get_operand_value(offset, 0) elif mnem in ["mov", "lea"]: if idc.get_operand_type(offset, 0) == idc.o_reg and idc.get_operand_type(offset, 1) == idc.o_mem: # Get memory offset for mov/lea instructions ptr = idc.get_operand_value(offset, 1) # Does the instruction's memory address operand seem somewhat valid?! if ptr < 0x1000: continue # Resolve pointer from memory operand iat_offset = get_word(ptr) # Ignore offset if it is in our image if image_base <= iat_offset <= image_base + size: continue # Get module and API name for offset module, api = self.resolve_address(iat_offset) # Ignore the offset if it is in a debug segment or stack etc if api and module and module.endswith(".dll"): if not iat_offset in iat_ptrs: # Add IAT offset, address to patch, module name and API name to list iat_ptrs.append((iat_offset, offset + idc.get_item_size(offset) - 4, module, api)) self.ret = iat_ptrs return self.ret
def _find_est(self, gvar, start, end): REG_RAX = 0 BS_OFFSET = 0x60 EFI_SYSTEM_TABLE = "EFI_SYSTEM_TABLE *" if self.arch == "x86": BS_OFFSET = 0x3C ea = start while ea < end: if ( (idc.print_insn_mnem(ea) == "mov") and (idc.get_operand_value(ea, 0) == REG_RAX) and (idc.get_operand_value(ea, 1) == BS_OFFSET) ): if idc.SetType(gvar, EFI_SYSTEM_TABLE): idc.set_name(gvar, f"gST_{gvar:X}") return True ea = idc.next_head(ea) return False
def get_boot_services(self): for ea_start in idautils.Functions(): for ea in idautils.FuncItems(ea_start): for service_name in OFFSET: if (idc.GetMnem(ea) == "call" and \ idc.get_operand_value(ea, 0) == OFFSET[service_name] ): if self.gBServices[service_name].count(ea) == 0: self.gBServices[service_name].append(ea)
def getLastImmediateRegisterValue(address, regIndex): while True: if (idc.get_operand_value(address, 0) == regIndex): mnem = idc.print_insn_mnem(address) if (mnem == "li"): return idc.get_operand_value(address, 1) elif (mnem == "move"): regIndex = idc.get_operand_value(address, 1) if (regIndex == 0): return 0 return getLastImmediateRegisterValue(address - 4, regIndex) else: return getLastImmediateRegisterValue(address - 4, regIndex) address -= 4
def extract_insn_obfs_call_plus_5_characteristic_features(f, bb, insn): """ parse call $+5 instruction from the given instruction. """ if not idaapi.is_call_insn(insn): return if insn.ea + 5 == idc.get_operand_value(insn.ea, 0): yield Characteristic("call $+5"), insn.ea
def can_be_ignored(instr_addr): """ Checks whether or not an instruction can be ignored. An instruction can be ignored if it does not actually an arithmetic or bitwise computation, although it has a mnemonic that falls into that category. Example: xor eax, eax """ # ignore instructions that are "abused" for non-arithmetic purposes if idc.GetMnem(instr_addr) in ['xor', 'sub']: same_op_type = idc.get_operand_type(instr_addr, 0) == idc.get_operand_type( instr_addr, 1) same_op_value = idc.get_operand_value(instr_addr, 0) == idc.get_operand_value( instr_addr, 1) if same_op_type and same_op_value: return True return False
def get_stack_vars(self, start, end): stackvars = {} ea = start while (ea < end): if ("ebp" in idc.print_operand(ea, 0) and idc.get_operand_type(ea, 1) == idc.o_imm): op0 = idc.get_operand_value(ea, 0) op1 = idc.get_operand_value(ea, 1) if (op0 in stackvars): stackvars[op0]["values"].append(op1) else: stackvars[op0] = {"values": [], "hits": 0} ea += idc.get_item_size(ea) return stackvars
def apply_iat(self, iat): min_ea = ida_ida.inf_get_min_ea() max_ea = ida_ida.inf_get_max_ea() image_base = ida_nalt.get_imagebase() idaapi.msg(f"{hex(min_ea)} - {hex(max_ea)} - {hex(image_base)} \n") for i in range(min_ea, max_ea): mnemonic = idc.print_insn_mnem(i) if mnemonic == "call" and str(idc.print_operand( i, 0)).startswith("dword"): try: idc.set_name( idc.get_operand_value(i, 0), iat[hex(idc.get_operand_value(i, 0))] + str(random.randint(0, 1000)) ) # I added random.randint() because some functions already in the IAT are dynamically resolved again, so renaming them causes a conflict, if you want remove it. (Sample causing the problem: https://bazaar.abuse.ch/sample/49fd52a3f3d1d46dc065217e588d1d29fba4d978cd8fdb2887fd603320540f71/) open("resolved_iat.txt", "a").write(f"{hex(idc.get_operand_value(i, 0))}\n") except: open("unresolved_iat.txt", "a").write(f"{hex(idc.get_operand_value(i, 0))}\n")
def get_position_and_translate(): """ Gets the current selected address and decodes the second parameter to the instruction if it exists/is an immediate then adds the C define for the code as a comment and prints a summary table of all decoded IOCTL codes. """ pos = idc.get_screen_ea() if idc.get_operand_type(pos, 1) != 5: # Check the second operand to the instruction is an immediate return value = idc.get_operand_value(pos) ioctl_tracker.add_ioctl(pos, value) define = ioctl_decoder.get_define(value) make_comment(pos, define) # Print summary table each time a new IOCTL code is decoded ioctls = [] for inst in ioctl_tracker.ioctl_locs: value = idc.get_operand_value(inst) ioctls.append((inst, value)) ioctl_tracker.print_table(ioctls)
def find_main(rom_addr, rom_end): # '00 00 00 00 ? ? ? ? 00 00 00 00 4D 00 00 00' addr, _ = masked_search(rom_addr, rom_end, b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4D\x00\x00\x00', b'\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF') if addr != idaapi.BADADDR: addr += 4 addr = idc.get_operand_value(addr, 0) return addr
def value(self): # operand is an immediate value => immediate value # operand has a displacement => displacement # operand is a direct memory ref => memory address # operand is a register => register number # operand is a register phrase => phrase number # otherwise => -1 value = get_operand_value(self.__ea, self.__n) if value == -1: raise Exception("get_operand_value() for %s has failed" % self) return value
def findRspRbpDifference(curr_ea): difference = 0 for i in range(0, 256): mnem = idc.print_insn_mnem(curr_ea) debug(mnem) idaapi.decode_insn(insn, curr_ea) if mnem == 'push': push_offset = 8 difference += push_offset elif mnem == 'sub': if idc.get_operand_value( curr_ea, 0 ) == OperandValueRegister.RSP and idc.get_operand_type( curr_ea, 1) == OperandType.IMMEDIATE_VALUE: rsp_substraction = idc.get_operand_value(curr_ea, 1) difference += rsp_substraction elif mnem == 'mov' or mnem == 'lea': #debug('type: ', idc.get_operand_type(curr_ea, 0), ' val: ', idc.get_operand_value(curr_ea, 0)) debug(idc.generate_disasm_line(curr_ea, 0)) if idc.get_operand_value(curr_ea, 0) == OperandValueRegister.RBP: debug( mnem, ' type: ', idc.get_operand_type(curr_ea, 1), ' val: ', 'bp: 0x{:X}'.format(idc.get_operand_value(curr_ea, 1))) #case 1: mov if mnem == 'mov': if idc.get_operand_type( curr_ea, 1 ) == OperandType.GENERAL_REG and idc.get_operand_value( curr_ea, 1) == OperandValueRegister.RSP: displacement = 0 #case 2: lea if mnem == 'lea': if idc.get_operand_type(curr_ea, 1) == OperandType.MEMORY_REG: if idc.get_operand_value(curr_ea, 1) > 0xF000000000000000: displacement = 0x10000000000000000 - idc.get_operand_value( curr_ea, 1) difference += displacement else: displacement = idc.get_operand_value( curr_ea, 1) difference -= displacement break curr_ea += insn.size return difference
def get_cursor_func_ref(): """ Get the function reference under the user cursor. Returns BADADDR or a valid function address. """ current_widget = idaapi.get_current_widget() form_type = idaapi.get_widget_type(current_widget) vu = idaapi.get_widget_vdui(current_widget) # # hexrays view is active # if vu: cursor_addr = vu.item.get_ea() # # disassembly view is active # elif form_type == idaapi.BWN_DISASM: cursor_addr = idaapi.get_screen_ea() opnum = idaapi.get_opnum() if opnum != -1: # # if the cursor is over an operand value that has a function ref, # use that as a valid rename target # op_addr = idc.get_operand_value(cursor_addr, opnum) op_func = idaapi.get_func(op_addr) if op_func and op_func.start_ea == op_addr: return op_addr # unsupported/unknown view is active else: return idaapi.BADADDR # # if the cursor is over a function definition or other reference, use that # as a valid rename target # cursor_func = idaapi.get_func(cursor_addr) if cursor_func and cursor_func.start_ea == cursor_addr: return cursor_addr # fail return idaapi.BADADDR
def find_WdfIoQueueCreate(): function_offset = OFFSET_WdfIoQueueCreate calls_to_pfn_list = [] try: for xref in idautils.XrefsTo(g_vars["_WDFFUNCTIONS"] + function_offset): call_pfnWdfIoQueueCreate = xref.frm calls_to_pfn_list.append(call_pfnWdfIoQueueCreate) except StopIteration: # this is case 2 or 3 pass if len(calls_to_pfn_list) == 0: call_pfnWdfIoQueueCreate = find_wdf_callback_through_immediate( "call", 0, function_offset) if call_pfnWdfIoQueueCreate: calls_to_pfn_list.append(call_pfnWdfIoQueueCreate) idc.OpStroffEx(call_pfnWdfIoQueueCreate, 0, (idaapi.get_struc_id("_WDFFUNCTIONS")), 0) if len(calls_to_pfn_list) == 0: call_pfnWdfIoQueueCreate = find_wdf_callback_through_immediate( "mov", 1, function_offset) if call_pfnWdfIoQueueCreate: calls_to_pfn_list.append(call_pfnWdfIoQueueCreate) idc.OpStroffEx(call_pfnWdfIoQueueCreate, 1, (idaapi.get_struc_id("_WDFFUNCTIONS")), 0) for pfn_call in calls_to_pfn_list: lea_argument_addr = find_function_arg(pfn_call, "lea", "r8", 0) # Get stack and the stack operand offset current_func = idaapi.get_func(lea_argument_addr) stack_id = idc.GetFrame(current_func) stack_member_offset = idc.get_operand_value(lea_argument_addr, 1) struct_id = idaapi.get_struc_id("_WDF_IO_QUEUE_CONFIG") struct_size = idc.GetStrucSize(struct_id) # First check if we have already touch this function stack before if function_stack_erased(current_func): # need to take care of the already defined structs # If the arguments collide then this will fail pass else: delete_all_function_stack_members(current_func) print("Erased the stack members") idc.AddStrucMember(stack_id, "queue_config", stack_member_offset, idc.FF_BYTE | idc.FF_DATA, -1, struct_size) idc.SetMemberType(stack_id, stack_member_offset, idc.FF_STRU | idc.FF_DATA, struct_id, 1) print("IOQueue Creation at: " + hex(pfn_call))
def addr(self): """ Retrieves the referenced memory address of the operand. :return int: Memory address or None if operand is not a memory reference. """ addr = None if self.has_phrase: # These need to be handled in the same way even if they don't contain the same types of data... addr = self._calc_displacement() elif self.type == idc.o_mem: addr = idc.get_operand_value(self.ip, self.idx) return addr
def _isImportStart(self, start: int) -> bool: """Check if the given function is imported or internal. """ if start in self._importsSet: return True if print_insn_mnem(start) == 'call': return False # print(print_insn_mnem(start)) op = get_operand_value(start, 0) if op in self._importsSet: return True return False
def lookForOpArgs(self, start, end): for head in idautils.Heads(start, end): try: for i in range(2): if using_ida7api: t = idc.get_operand_type(head, i) else: t = idc.GetOpType(head, i) if t == idc.o_imm: if using_ida7api: opval = idc.get_operand_value(head, i) else: opval = idc.GetOperandValue(head, i) for h in self.params.hashTypes: hits = self.dbstore.getSymbolByTypeHash(h.hashType, opval) for sym in hits: logger.info("0x%08x: %s", head, str(sym)) self.addHit(head, sym) self.markupLine(head, sym) except Exception, err: logger.exception("Exception: %s", str(err))