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 removeStackVarUsages(self_ea, end_ea): madeChanges = False for func_ea in idautils.Functions(self_ea, end_ea): changedStackVar = False if Function.hasStackVars(func_ea): stackVars = Function.getStackVars(func_ea) # traverse data items of function and op_bin all ea = func_ea while ea < func_ea + Function.Function(func_ea).getSize( withPool=False): d = Data.Data(ea) for name, off in stackVars: if name != ' s' and name in d.getOrigDisasm(): changedStackVar = True if not madeChanges: madeChanges = True idc.op_hex(d.ea, 1) ea += d.getSize() if changedStackVar: print('%07X: stackvars op -> hex' % func_ea) if madeChanges: print("Removed all stack variable usages!") else: print("No stack variable usages to remove!")
def parse_phrase(o, ida_operand_str, addr, op_num): # IDA does not give us an API to get the content of the phrase # => we have to parse the string :/ if isinstance(__builtin__.REGISTERS, RegistersX64): # DEBUG #print("phrase: ida_operand_str: %s" % ida_operand_str) # Example: [rdx+rcx] or [rax+rdx*8] or byte ptr [rsi+rdx] # Remove "[" and "]" start = ida_operand_str.find("[") + 1 end = len(ida_operand_str) - 1 temp_str = ida_operand_str[start:end] memory_elements = temp_str.split("+") # DEBUG #print("phrase: Memory elements: %d" % len(memory_elements)) #print(memory_elements) # Example: [rdx+rcx] => rdx or [rax+rdx*8] => rax base_str = memory_elements[0] try: base_reg = __builtin__.REGISTERS.to_idx(base_str) except: # In cases such as [rsp-50h+arg_48] our # string parsing fails. However, we can normalize this # to [rsp] and retry. if op_hex(addr, op_num): new_str = GetOpnd(addr, op_num) if ida_operand_str != new_str: return parse_phrase(o, new_str, addr, op_num) raise NotImplementedError("Do not know how to " + "handle o_phrase '%s'." % ida_operand_str) index_reg = None index_factor = None if len(memory_elements) == 2: index_split = memory_elements[1].split("*") # DEBUG #print("phrase: Index split: " + str(index_split)) # Example: [rdx+rcx] => rcx or [rax+rdx*8] => rdx # Example: [rsp+0] => rsp index_str = index_split[0] factor_str = None if len(index_split) == 2: # Example [rax+rdx*8] => 8 factor_str = index_split[1] elif len(index_split) > 1: # In cases such as [rsp+0B0h+lbarray+78h] our # string parsing fails. However, we can normalize this # to [rsp] and retry. if op_hex(addr, op_num): new_str = GetOpnd(addr, op_num) if ida_operand_str != new_str: return parse_phrase(o, new_str, addr, op_num) raise NotImplementedError("Do not know how to " + "handle o_phrase '%s'." % ida_operand_str) # Example: [rsp+0] # Example: [rsp+s2] with r2 = 0 try: index_reg = __builtin__.REGISTERS.to_idx(index_str) except: # DEBUG #print("NOTE: phrase index string '%s' ignored." # % index_str) index_reg = None if factor_str: index_factor = int(factor_str) # Example: [rsp+0] if index_reg is None: return operands.Memory(operands.Register(base_reg)) # Example: [rax+rdx*8] elif factor_str: return operands.Memory( operands.Register(base_reg), index=operands.Register(index_reg), index_factor=operands.Constant(index_factor)) # Example: [rdx+rcx] else: return operands.Memory(operands.Register(base_reg), index=operands.Register(index_reg)) # Example: [rsp+40h+var_40] => [rsp] # Example: [rsp+8+var_8] => [rsp] # Example: [rsp+rcx*2+var_s0] => [rsp+rcx*2] elif len(memory_elements) == 3: # IDA defines o_phrase as the following: # Memory Ref [Base Reg + Index Reg] # Therefore, a phrase does not have an offset. # The string construct built by IDA always adds up to 0. possible_number = memory_elements[1] has_hex_ending = possible_number[-1:] == "h" is_hex = bool(re.match(r'^[a-fA-F0-9]+$', possible_number[:-1])) is_number = bool(re.match(r'^[0-9]+$', possible_number)) # Example: [rsp+40h+var_40] => [rsp] if has_hex_ending and is_hex: return operands.Memory(operands.Register(base_reg)) # Example: [rsp+8+var_8] => [rsp] elif is_number: return operands.Memory(operands.Register(base_reg)) # Example: [rsp+rcx*2+var_s0] => [rsp+rcx*2] else: index_split = memory_elements[1].split("*") # Example: [rsp+rcx*2+var_s0] => rcx index_str = index_split[0] factor_str = None if len(index_split) == 2: # Example [rax+rdx*8] => 8 factor_str = index_split[1] elif len(index_split) > 1: # In cases such as [rsp+0B0h+lbarray+78h] our # string parsing fails. However, we can normalize this # to [rsp] and retry. if op_hex(addr, op_num): new_str = GetOpnd(addr, op_num) if ida_operand_str != new_str: return parse_phrase(o, new_str, addr, op_num) raise NotImplementedError("Do not know how to " + "handle o_phrase '%s'." % ida_operand_str) try: index_reg = __builtin__.REGISTERS.to_idx(index_str) except: # In cases such as [rsp+0B0h+lbarray+78h] our # string parsing fails. However, we can normalize this # to [rsp] and retry. if op_hex(addr, op_num): new_str = GetOpnd(addr, op_num) if ida_operand_str != new_str: return parse_phrase(o, new_str, addr, op_num) raise NotImplementedError("Do not know how to " + "handle o_phrase '%s'." % ida_operand_str) if factor_str: index_factor = int(factor_str) # Example: [rsp+rcx*2+var_s0] if factor_str: return operands.Memory( operands.Register(base_reg), index=operands.Register(index_reg), index_factor=operands.Constant(index_factor)) # Example: [rsp+rcx+var_s0] else: return operands.Memory( operands.Register(base_reg), index=operands.Register(index_reg)) # Example: [rsp+rdx*8+98h+var_98] => [rsp+rdx*8] elif len(memory_elements) == 4: # IDA defines o_phrase as the following: # Memory Ref [Base Reg + Index Reg] # Therefore, a phrase does not have an offset. # The string construct built by IDA always adds up to 0. possible_number = memory_elements[2] has_hex_ending = possible_number[-1:] == "h" is_hex = bool(re.match(r'^[a-fA-F0-9]+$', possible_number[:-1])) if has_hex_ending and is_hex: new_op_str = "[" + \ memory_elements[0] + \ "+" + \ memory_elements[1] + \ "]" return parse_phrase(o, new_op_str, addr, op_num) else: # In cases such as [rsp+0B0h+lbarray+78h] our # string parsing fails. However, we can normalize this # to [rsp] and retry. if op_hex(addr, op_num): new_str = GetOpnd(addr, op_num) if ida_operand_str != new_str: return parse_phrase(o, new_str, addr, op_num) raise NotImplementedError("Do not know how to " + "handle o_phrase '%s'." % ida_operand_str) elif len(memory_elements) > 4: # In cases such as [rsp+0B0h+lbarray+78h] our # string parsing fails. However, we can normalize this # to [rsp] and retry. if op_hex(addr, op_num): new_str = GetOpnd(addr, op_num) if ida_operand_str != new_str: return parse_phrase(o, new_str, addr, op_num) raise NotImplementedError("Do not know how to handle " + "o_phrase '%s'." % ida_operand_str) return operands.Memory(operands.Register(base_reg)) else: raise NotImplementedError( "Do not know how to handle o_phrase for architecture.")