def XCHG(cpu_context, ip, mnem, opvalues): """ Exchange two values """ opvalue1 = opvalues[0].value opvalue2 = opvalues[1].value cpu_logger.debug("XCHG 0x{:X} :: exchange {} and {}".format(ip, opvalue1, opvalue2)) set_operand_value(cpu_context, ip, opvalue1, idc.GetOpnd(ip, 1), idc.GetOpType(ip, 1)) set_operand_value(cpu_context, ip, opvalue2, idc.GetOpnd(ip, 0), idc.GetOpType(ip, 0))
def parse_STR(self, addr, regs): src = idc.GetOpnd(addr, 0) des = idc.GetOpnd(addr, 1)[1:-1] if src in regs: regs[des] = regs[src] else: regs[des] = 'Unknown'
def function(ea, taintSet): Opnd = idc.GetOpnd(ea, 0) #print format(ea, '04x'), Opnd, taintSet if Opnd in source and Opnd not in sink: #print 'source function %s is called, tainting operand %d' %(Opnd, source[Opnd]), taintSet.add('R' + str(source[Opnd])) #print taintSet #return True elif Opnd in source and 'R' + str(sink[Opnd]) in taintSet: sourceOpnd = 'R' + str(source[Opnd]) while (idc.GetOpnd(ea, 0) != sourceOpnd): ea -= 2 taintTarget = idc.GetOpnd(ea, 1) taintSet.add(taintTarget) #print 'Target %s of sink function %s tainted by operand %d' %(taintTarget, Opnd, sink[Opnd]+1), taintSet #return True elif Opnd in sink and 'R' + str(sink[Opnd]) in taintSet: sinkOpnd = 'R' + str(sink[Opnd]) while (idc.GetOpnd(ea, 0) != sinkOpnd): ea -= 2 taintSource = idc.GetOpnd(ea, 1) #print 'operand %d of sink function %s tainted by source %s' %(sink[Opnd], Opnd, taintSource) #return True else: #pass func_ea = getFunctionWithName(Opnd) f = get_func(func_ea) taintFunction(Opnd, f.startEA, 0, taintSet)
def one2two(ea, taintSet): if idc.GetOpnd(ea, 0) in taintSet: taintSet.add(idc.GetOpnd(ea, 1)) #return True if idc.GetOpnd(ea, 1) in taintSet and idc.GetOpnd(ea, 0) not in taintSet: taintSet.remove(idc.GetOpnd(ea, 1))
def IMUL(cpu_context, ip, mnem, opvalues): """ Signed Multiplication ; Single operand form imul ecx ; Signed multiply the value in ecx with the value in eax (et.al) ; IDA will identify 2 operands, but only operand 1 will contain a value so 0 and 2 will be None ; Two operand form imul edi, edx ; Signed multiply the destination operand (op 0) with the source operand (op 1) ; IDA will identify 3 operands, but operand 2 will be None ; Three operand form imul eax, edi, 5 ; Signed multiple source operand (op 1) with the immediate value (op 2) and store in ; the destination operand (op 0) """ # IDA is awesome in the fact that it isn't consistent as to what operands are assigned values. One instance it # may be operand 0 and 1, another might be 0 and 2, etc...However, since we are assigning a None to operands where # idc.GetOpnd returns "" (an empty string), then we can just remove all the opvalue list items which have a value # of None and this will give us our number of operands. RAX_REG_SIZE_MAP = {8: "RAX", 4: "EAX", 2: "AX", 1: "AL"} width = get_max_operand_size(opvalues) opvalues = [opvalue for opvalue in opvalues if opvalue.value is not None] op_count = len(opvalues) if op_count == 1: # if opvalues[0].value is None and opvalues[2].value is None: # Single operand form _mul(cpu_context, ip, mnem, opvalues) return # else: # if opvalues[0].value and opvalues[1].value and opvalues[2].value is None: # Two operand form elif op_count == 2: destination = idc.GetOpnd(ip, 0) multiplier1 = opvalues[0].value multiplier2 = opvalues[1].value # elif opvalues[0].value and opvalues[1].value and opvalues[2].value: # Three operand form elif op_count == 3: destination = idc.GetOpnd(ip, 0) multiplier1 = opvalues[1].value multiplier2 = opvalues[2].value else: raise Exception("0x{:X}: Invalid sequence for IMUL instruction".format(ip)) mask = utils.get_mask(width) result = multiplier1 * multiplier2 cpu_context.registers.cf = int(not ( (not utils.sign_bit(multiplier1, width) and multiplier2 & mask == 0) or (utils.sign_bit(multiplier1, width) and multiplier2 & mask == mask) )) cpu_context.registers.of = cpu_context.registers.cf cpu_context.registers.zf = int(multiplier1 & mask == 0) cpu_context.registers.sf = utils.sign_bit(multiplier1, width) cpu_context.registers.pf = get_parity(multiplier1) cpu_logger.debug("IMUL 0x{:X} :: {} * {} = {}".format(ip, multiplier1, multiplier2, result)) # Notably, IDA knows that EAX is the destination for the single operand form, and properly returns # idc.o_reg for idc.GetOpType (though for IMUL the destination MUST be a register, so it could technically # be hard coded here... set_operand_value(cpu_context, ip, result, destination, idc.GetOpType(ip, 0))
def find_unusual_xors(functions): # TODO find xors in tight loops candidate_functions = [] for fva in functions: cva = fva while cva != idaapi.BADADDR and cva < idc.FindFuncEnd(fva): if idc.GetMnem(cva) == "xor": if idc.GetOpnd(cva, 0) != idc.GetOpnd(cva, 1): g_logger.debug( "suspicious XOR instruction at 0x%08X in function 0x%08X: %s", cva, fva, idc.GetDisasm(cva)) ph = idc.PrevHead(cva) nh = idc.NextHead(cva) ip = idc.GetDisasm(ph) ia = idc.GetDisasm(nh) if ip and ia: g_logger.debug("Instructions: %s; %s; %s", ip, idc.GetDisasm(cva), ia) if ph or nh: if is_security_cookie(cva, ph, nh): g_logger.debug( "XOR related to security cookie: %s", idc.GetDisasm(cva)) else: g_logger.debug("unusual XOR: %s", idc.GetDisasm(cva)) candidate_functions.append(fva) break cva = idc.NextHead(cva) return candidate_functions
def get_args(addr): """ Retreives the passed arguments to the decryption function. We are only interested in the key and offset to the encrypted string. addr: (int) Address at which the decryption function was called. Returns: key: (int) The key used to decrypt the string. enc_str: (list) Byte array of encrypted string. ins_addr: (int) Address at which the encrypted byte array is referenced. """ found = False foundstr = False foundkey = False while not found: addr = idc.PrevHead(addr) if idc.GetMnem(addr) == "mov" and "r8d" in idc.GetOpnd(addr,0): #print "[+] Found key: 0x%08x at 0x%016x" % (idc.GetOperandValue(addr,1)& 0xffffffff, addr) key = idc.GetOperandValue(addr,1) & 0xffffffff foundkey = True if idc.GetMnem(addr) == "lea" and "rdx" in idc.GetOpnd(addr,0): #print "[+] Found str: 0x%016x at 0x%016x" % (idc.GetOperandValue(addr,1), addr) enc_str_addr = idc.GetOperandValue(addr,1) enc_str = get_encoded_string(enc_str_addr) ins_addr = addr foundstr = True if foundkey and foundstr: found = True return key, enc_str, ins_addr
def check_second_instruction(inst): mnem = idc.GetMnem(inst) if mnem != 'mov': return False if idc.GetOpnd(inst, 0) == 'r10' or idc.GetOpnd(inst, 1) == 'rcx': return True return False
def search_function(): curr_addr = MinEA() end = MaxEA() current_func_name = "" while curr_addr < end: if curr_addr == idc.BADADDR: break elif idc.GetMnem(curr_addr) == 'call': if idc.GetOpnd(curr_addr, 0) in FUNCTIONS_REGISTERS.keys(): func_name_addr = get_string_for_function( curr_addr, FUNCTIONS_REGISTERS[idc.GetOpnd(curr_addr, 0)].lower()) if func_name_addr: try: function_start = idc.GetFunctionAttr( curr_addr, idc.FUNCATTR_START) new_filename = get_fixed_source_filename( func_name_addr) current_func_name = idc.GetFunctionName(function_start) if is_function_name(current_func_name): idaapi.set_name(function_start, new_filename, idaapi.SN_FORCE) else: print "Function:", current_func_name, "was not changed" except: print "failed at address " + hex(curr_addr), \ "function:", current_func_name, "call:", idc.GetOpnd(curr_addr, 0) curr_addr = idc.NextHead(curr_addr)
def GetBranchList(self, start=None, end=None): branch_list = list() current = start if self.arc == ARCHITECTURE['MIPS']: branch_obj = self.asm.mips_asm_class['branch'] jump_obj = self.asm.mips_asm_class['jump'] while current <= end: method = 'do_' + idc.GetMnem(current) if hasattr(branch_obj, method) or hasattr(jump_obj, method): if idc.GetOpType(current, 0) == ASM_TYPE['Imm_Near_Addr']: opr = idc.LocByName(idc.GetOpnd(current, 0)) if opr in self.func_ref_list: branch_list.append(hex(opr)) elif idc.GetOpType(current, 1) == ASM_TYPE['Imm_Near_Addr']: opr = idc.LocByName(idc.GetOpnd(current, 1)) if opr in self.func_ref_list: branch_list.append(hex(opr)) elif idc.GetOpType(current, 2) == ASM_TYPE['Imm_Near_Addr']: opr = idc.LocByName(idc.GetOpnd(current, 2)) if opr in self.func_ref_list: branch_list.append(hex(opr)) current = idc.NextHead(current, end) branch_list = list(set(branch_list)) branch_list.sort() return branch_list
def GetBranchList(self, start=None, end=None): self.branch_list = list() current = start if self.arc == ARCHITECTURE['MIPS']: o_iasm = mips_iasm.MIPS_IAsm() branch_obj = o_iasm.mips_asm_class['branch'] jump_obj = o_iasm.mips_asm_class['jump'] while current <= end: method = 'do_' + idc.GetMnem(current) if hasattr(branch_obj, method) or hasattr(jump_obj, method): if self.isNearAddr(idc.GetOpType(current, 0)): opr = idc.LocByName(idc.GetOpnd(current, 0)) if opr in self.func_ref_list: self.branch_list.append(hex(opr)) elif self.isNearAddr(idc.GetOpType(current, 1)): opr = idc.LocByName(idc.GetOpnd(current, 1)) if opr in self.func_ref_list: self.branch_list.append(hex(opr)) elif self.isNearAddr(idc.GetOpType(current, 2)): opr = idc.LocByName(idc.GetOpnd(current, 2)) if opr in self.func_ref_list: self.branch_list.append(hex(opr)) current = idc.NextHead(current, end) self.branch_list = list(set(self.branch_list)) self.branch_list.sort() return self.branch_list
def jumps_to(f, t): f_ea = idc.LocByName(f) t_ea = idc.LocByName(t) for start, end in idautils.Chunks(f_ea): ea = start while (ea < end): i = idautils.DecodeInstruction(ea) #Functions have data chunks in them, these are offsets and dwords. skipping 4 ahead seems like a safe choice. if type(i) == type(None): ea += 4 continue #detect if instruction is a jump to t_ea m = idc.GetMnem(ea) if idc.GetMnem(ea) == "LDR" and idc.GetOpnd( ea, 0) == "PC" and t in idc.GetOpnd(ea, 1): return True elif idc.GetMnem(ea) == "BX" and idc.GetOpnd(ea, 0) == t: return True try: ea += i.size except: print "0x%08x" % ea print "DecodeInstruction failed!" print i.size return False
def find_interesting_xors(self): next_xor = idc.FindText(idc.MinEA(), idc.SEARCH_DOWN | idc.SEARCH_NEXT, 0, 0, "xor") while next_xor != idc.BADADDR: if idc.GetOpnd(next_xor, 0) != idc.GetOpnd(next_xor, 1): entry = { "func": "", "addr": next_xor, "loop": False, "disasm": idc.GetDisasm(next_xor) } func = idaapi.get_func(next_xor) if func: entry["func"] = idaapi.get_name(idc.BADADDR, func.startEA) heads = idautils.Heads(next_xor, func.endEA) lxors = [] for head in heads: if idc.GetMnem(head).startswith('j'): jmp_addr = idc.GetOperandValue(head, 0) if jmp_addr < next_xor and jmp_addr > func.startEA: entry["loop"] = True break self._interesting_xors.append(entry) next_xor = idc.FindText(idc.NextHead(next_xor), idc.SEARCH_DOWN | idc.SEARCH_NEXT, 0, 0, "xor")
def iter_fn(self, startAddr): """ Generator function designed to walk all instructions within a function, parse and yield them. """ endAddr = idc.GetFunctionAttr(startAddr, idc.FUNCATTR_END) for head in idautils.Heads(startAddr, endAddr): yield head, idc.GetDisasm(head).split()[0], idc.GetOpnd(head, 0), idc.GetOpnd(head, 1)
def disasm(self): l = [] for n in self.body: di = "0x%08x %s %s %s" % (n, idc.GetMnem(n), idc.GetOpnd( n, 0), idc.GetOpnd(n, 1)) l.append(di) return "\n".join(l)
def check_operand(opnd, call_arguments, heads): if is_argument(opnd, call_arguments): return True for head in heads: if is_jump(head): return False if is_return_value(opnd) and idc.GetMnem( head) == 'call' and ida_funcs.func_does_return(head): return check_eax(head, call_arguments) if idc.GetMnem(head) == 'call' and is_used(head, opnd): return False if opnd != idc.GetOpnd(head, 0): continue if should_check_second_opnd(head): if is_number(idc.GetOpnd(head, 1)): return is_argument(idc.GetOpnd(head, 1), call_arguments) opnd = idc.GetOpnd(head, 1) elif (not is_number(idc.GetOpnd(head, 1))) and check_next_opnd( head, call_arguments): return True if is_argument(opnd, call_arguments): return True return False
def revise_syscall(rename=False): if not rename: print( 'Change the function name with `CGCHeler.revise_syscall(True)`.' ) # visit all instructions start_ea, end_ea = utils.get_seg_range('.text') eax = -1 ip = start_ea while ip < end_ea and ip != idaapi.BADADDR: if 'int' in idc.GetMnem(ip) and '80h' == idc.GetOpnd(ip, 0): if eax != -1: # fix comment and function name print('{}: {}'.format(hex(ip), syscall_table[eax])) idc.MakeComm(ip, 'CGC syscall: {}'.format(syscall_table[eax])) if rename: print('Change {} to {}'.format(idc.GetFunctionName(ip), syscall_table[eax])) idc.MakeName( idc.GetFunctionAttr(ip, idc.FUNCATTR_START), syscall_table[eax]) elif 'mov' in idc.GetMnem(ip) and 'eax' == idc.GetOpnd( ip, 0) and 5 == idc.GetOpType(ip, 1): value = idc.GetOpnd(ip, 1) if re.search('^[0-9]+$', value) != None: eax = int(value) if eax > 7 or eax < 1: eax = -1 ip = idc.NextHead(ip)
def parse_register_value(register, start_addr, end_addr): print "start find register: %s from 0x%x to 0x%x" % (register, start_addr, end_addr) _addr = start_addr while _addr > end_addr: _addr = idc.PrevHead(_addr) _opnd_first = idc.GetOpnd(_addr, 0) if _opnd_first == register: _op_code = idc.GetMnem(_addr) second_opnd_type = idc.GetOpType(_addr, 1) print 'find register( 0x%x ) -> %s, type1: %d, type2: %d' % ( _addr, idc.GetDisasm(_addr), second_opnd_type, idc.GetOpType(_addr, 2)) if _op_code.startswith('LDR'): return parse_opnd_value(_addr, end_addr, 1) elif _op_code.startswith('ADD'): if (idc.GetOpType(_addr, 2) == 0): if idc.GetOpnd(_addr, 1) == 'PC': # todo: check last _op => LDR R6, =(_GLOBAL_OFFSET_TABLE_ - 0xAEB6) return 0x00021DB4 else: return parse_register_value( register, _addr, end_addr) + parse_opnd_value( _addr, end_addr, 1) else: return parse_opnd_value(_addr, end_addr, 1) + parse_opnd_value( _addr, end_addr, 2) elif _op_code.startswith('MOV'): return parse_register_value(idc.GetOpnd(_addr, 1), _addr, end_addr)
def build_gcc(): for item in class_list: attribute = idc.Dword(class_list[item]["addr"] + 0x10) num = idc.Dword(class_list[item]["addr"] + 0x14) if (0 <= attribute <= 4) and (0 < num < 100): i = 0 while i < num: symbol = idc.GetOpnd( class_list[item]["addr"] + 0x18 + i * 0x10, 0) symbol = re.sub(r'^offset ', '', symbol) class_list[item]["base"].append(symbol) virtual_attri = idc.Qword(class_list[item]["addr"] + 0x18 + i * 0x10 + 8) if struct.unpack('q', struct.pack('Q', virtual_attri))[0] < 0: if "virtual_inherit" in class_list[item]: class_list[item]["virtual_inherit"].append(symbol) else: class_list[item]["virtual_inherit"] = list() class_list[item]["virtual_inherit"].append(symbol) i += 1 else: symbol = idc.GetOpnd(class_list[item]["addr"] + 0x10, 0) symbol = re.sub(r'^offset ', '', symbol) addr = idc.Qword(class_list[item]["addr"] + 0x10) # 排除类定义到其他文件的 extern if (symbol[:4] == "_ZTI") and ((addr < extern_start) or (addr > extern_end)): class_list[item]["base"].append(symbol)
def __init__(self): print "Naming saved register locations...", for ea in idautils.Functions(): mea = ea named_regs = [] last_iteration = False while mea < (ea + (self.INSIZE * self.SEARCH_DEPTH)): mnem = idc.GetMnem(mea) if mnem in ['sw', 'sd']: reg = idc.GetOpnd(mea, 0) dst = idc.GetOpnd(mea, 1) if reg in self.ARCH['savedregs'] and reg not in named_regs and dst.endswith('($sp)') and 'var_' in dst: offset = int(dst.split('var_')[1].split('(')[0], 16) idc.MakeLocal(ea, idc.FindFuncEnd(ea), "[sp-%d]" % offset, "saved_%s" % reg[1:]) named_regs.append(reg) if last_iteration: break elif mnem.startswith('j') or mnem.startswith('b'): last_iteration = True mea += self.INSIZE print "done."
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 __init__(self, *args): if len(args) == 1: idc.op_hex(args[0], 0) idc.op_hex(args[0], 1) op1 = idc.GetOpnd(args[0], 0) op2 = idc.GetOpnd(args[0], 1) if op1 == '': op1 = False if op2 == '': op2 = False self.ea = args[0] self.mnem = idc.GetMnem(args[0]) self.op1 = op1 self.op2 = op2 self.extend = 0 elif len(args) == 4: self.ea = args[0] self.mnem = args[1] self.op1 = args[2] self.op2 = args[3] self.extend = 0 elif len(args) == 5: self.ea = args[0] self.mnem = args[1] self.op1 = args[2] self.op2 = args[3] self.extend = args[4]
def function(ea, taintSet): Opnd = idc.GetOpnd(ea, 0) #print format(ea, '04x'), Opnd if Opnd in source and Opnd not in sink: print 'source function %s is called, tainting operand %d' % ( Opnd, source[Opnd]) taintSet.add('R' + str(source[Opnd])) return True elif Opnd in source and 'R' + str(sink[Opnd]) in taintSet: sourceOpnd = 'R' + str(source[Opnd]) while (idc.GetOpnd(ea, 0) != sourceOpnd): ea -= 2 taintTarget = idc.GetOpnd(ea, 1) taintSet.add(taintTarget) print 'Target %s of sink function %s tainted by operand %d' % ( taintTarget, Opnd, sink[Opnd] + 1) return True elif Opnd in sink and 'R' + str(sink[Opnd]) in taintSet: sinkOpnd = 'R' + str(sink[Opnd]) while (idc.GetOpnd(ea, 0) != sinkOpnd): ea -= 2 taintSource = idc.GetOpnd(ea, 1) print 'operand %d of sink function %s tainted by source %s' % ( sink[Opnd], Opnd, taintSource) return True else: pass return False
def ext_instruction(file_name, addr_start, addr_end): name_fun = GetFunctionName(addr_start) row = '' for addr in Heads(addr_start, addr_end): ins = '' thisOperand = idc.GetMnem(addr) oPtype1 = idc.GetOpType(addr, 0) oPtype2 = idc.GetOpType(addr, 1) # assemblydata = parametertype(oPtype1)+' '+parametertype(oPtype2) if (oPtype1 == 1 or oPtype1 == 4): oPtype1 = idc.GetOpnd(addr, 0) if (oPtype2 == 1 or oPtype2 == 4): oPtype2 = idc.GetOpnd(addr, 1) if thisOperand == "call": call_fun_name = GetOpnd(addr, 0) keyInstr = LocByName(call_fun_name) fflags = idc.get_func_flags(keyInstr) if (fflags & idc.FUNC_LIB) or (fflags & idc.FUNC_THUNK): ins = thisOperand + '_' + idc.GetOpnd(addr, 0) + '_0' row = row + ' ' + ins continue ins = str(thisOperand)+'_'+tran(str(oPtype1)) + \ '_'+tran(str(oPtype2)) row = row + ' ' + ins return row
def get_opnd(address): opnd = idc.GetOpnd(address, 1) if opnd == '': opnd = idc.GetOpnd(address, 0) return opnd
def is_used(call, opnd): addresses = get_args_addresses(call) for address in addresses: if idc.GetOpnd(address, 0) == opnd or idc.GetOpnd(address, 1) == opnd: return True return False
def two2one(ea, taintSet): if idc.GetOpnd(ea, 1) in taintSet: taintSet.add(idc.GetOpnd(ea, 0)) return True if idc.GetOpnd(ea, 0) in taintSet and idc.GetOpnd(ea, 1) not in taintSet: taintSet.remove(idc.GetOpnd(ea, 0)) return False
def MOVAPD(cpu_context, ip, mnem, opvalues): """ Move Aligned Packed Double-Precision Floating-Point Values """ opvalues = [opvalue for opvalue in opvalues if opvalue.value is not None] opvalue2 = opvalues[1].value cpu_logger.debug("{} 0x{:X} :: Copy {} into {}".format(mnem, ip, opvalue2, idc.GetOpnd(ip, 0))) set_operand_value(cpu_context, ip, opvalue2, idc.GetOpnd(ip, 0), idc.GetOpType(ip, 0), width=opvalues[1].width)
def find_WdfDriverCreate(): function_offset = OFFSET_WdfDriverCreate # If the XREF to wdfFunctions + function_offset exists.. then we're in case 1! try: call_pfnWdfDriverCreate = idautils.XrefsTo(g_vars["_WDFFUNCTIONS"]+function_offset).next().frm except StopIteration: # this is case 2! call_pfnWdfDriverCreate = find_wdf_callback_through_immediate("mov", 1,function_offset) if call_pfnWdfDriverCreate != None: idc.OpStroffEx(call_pfnWdfDriverCreate,1,(idaapi.get_struc_id("_WDFFUNCTIONS")),0) else: call_pfnWdfDriverCreate = find_wdf_callback_through_immediate("call", 0, function_offset) idc.OpStroffEx(call_pfnWdfDriverCreate,0,(idaapi.get_struc_id("_WDFFUNCTIONS")),0) if call_pfnWdfDriverCreate != None: # First identify the RealDriverEntry :) current_func = idaapi.get_func(call_pfnWdfDriverCreate) idc.MakeName(current_func.startEA, "_DriverEntry_") argument_DriverConfig_addr = find_function_arg_with_operand_value(call_pfnWdfDriverCreate, "mov", "rsp", 0x20, 0) register_DriverConfig = idc.GetOpnd(argument_DriverConfig_addr, 1) lea_DriverConfig_addr = find_function_arg(argument_DriverConfig_addr, "lea", register_DriverConfig, 0) # Get stack and the stack operand offset current_func = idaapi.get_func(lea_DriverConfig_addr) stack_id = idc.GetFrame(current_func) opnd = idc.GetOpnd(lea_DriverConfig_addr, 1) if "rsp" in opnd: stack_member_offset = idc.GetOperandValue(lea_DriverConfig_addr, 1) elif "rbp" in opnd: var_x = opnd.split("+")[-1][:-1] # [rbp+57h+var_80] -> var_80 members, _ = retrieve_stack_members(current_func) inverted_members = {v:k for k, v in members.items()} try: stack_member_offset = inverted_members[var_x] except KeyError as msg: print msg return else: print("+] WdfDriverCreate() Unidentified register stack layout") return #idc.SetMemberName(stack_id, stack_member_offset, "_DriverConfig") struct_id = idaapi.get_struc_id("_WDF_DRIVER_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 # pass #else: delete_all_function_stack_members(current_func, force=True) idc.AddStrucMember(stack_id, "driver_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)
def _mov_lea(cpu_context, ip, mnem, opvalues): """ Handle the MOV, MOVZX, and LEA instructions in the same manner. MOVZX is a zero extend, but this logic makes no real sense in python. """ opvalue2 = opvalues[1].value width = opvalues[0].width cpu_logger.debug("{} 0x{:X} :: Copy {} into {}".format(mnem, ip, opvalue2, idc.GetOpnd(ip, 0))) set_operand_value(cpu_context, ip, opvalue2, idc.GetOpnd(ip, 0), idc.GetOpType(ip, 0), width=width)