From e7d9bb894f35b4f80d4f626d0f8348a800f3fe51 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Fri, 5 Nov 2021 13:18:09 -0400 Subject: Fix vars_written/vars_read/vars_address_taken --- python/highlevelil.py | 379 ++++++++++-------------------------------------- python/lowlevelil.py | 25 +--- python/mediumlevelil.py | 16 ++ 3 files changed, 101 insertions(+), 319 deletions(-) (limited to 'python') diff --git a/python/highlevelil.py b/python/highlevelil.py index c8751c8f..8c8b1958 100644 --- a/python/highlevelil.py +++ b/python/highlevelil.py @@ -37,6 +37,7 @@ from . import types from . import highlight from . import flowgraph from . import variable +from .log import log_info from .interaction import show_graph_report from .commonil import (ILInstruction, Call, Tailcall, Syscall, Comparison, Signed, UnaryOperation, BinaryOperation, SSA, Phi, Loop, ControlFlow, Memory, Constant, Arithmetic, DoublePrecision, Terminal, @@ -416,30 +417,67 @@ class HighLevelILInstruction(ILInstruction): def core_operands(self) -> OperandsType: return self.core_instr.operands + @property + def instruction_operands(self) -> List['HighLevelILInstruction']: + result = [] + for i in self.operands: + if isinstance(i, list): + result.extend([j for j in i if isinstance(j, HighLevelILInstruction)]) + elif isinstance(i, HighLevelILInstruction): + result.append(i) + return result + @property def vars_written(self) -> VariablesList: - """List of variables written by instruction""" - return [] + """List of variables value is written by this instruction""" + result = [] + for i in self.operands: + if isinstance(i, HighLevelILInstruction): + result.extend(i.vars_written) + return result @property def vars_read(self) -> VariablesList: - """List of variables read by instruction""" - return [] + """Non-unique list of variables whose value is read by this instruction""" + non_read = [*self.vars_written, *self.vars_address_taken] + result = [] + for v in self.vars: + if v in non_read: + non_read.remove(v) + continue + result.append(v) + return result @property def vars_address_taken(self) -> VariablesList: - """Non-unique list of variables whose address is taken by instruction""" - return [] + """ + Non-unique list of variables whose address is taken by instruction - @property - def vars_used_in_address(self) -> VariablesList: - """Non-unique list of variables used to calculate an address""" - return [] + .. note:: This property has some nuance to it, so use carefully. This property will return only those variable which \ + directly have their address taken such as `&var_4` or `&var_8.d` but not those which are involved in an address \ + calculation such as `&(var_4 + 0)` or `&var_4[0]` even though they may be functionally equivalent. + """ + result = [] + for operand in self.instruction_operands: + result.extend(operand.vars_address_taken) + return result @property def vars(self) -> VariablesList: """Non-unique list of variables read by instruction""" - return [] + result = [] + for operand in self.operands: + if isinstance(operand, HighLevelILInstruction): + result.extend(operand.vars) + elif isinstance(operand, (variable.Variable, mediumlevelil.SSAVariable)): + result.append(operand) + elif isinstance(operand, list): + for sub_operand in operand: + if isinstance(sub_operand, (variable.Variable, mediumlevelil.SSAVariable)): + result.append(sub_operand) + elif isinstance(sub_operand, HighLevelILInstruction): + result.extend(sub_operand.vars) + return result @property def parent(self) -> Optional['HighLevelILInstruction']: @@ -666,14 +704,6 @@ class HighLevelILUnaryBase(HighLevelILInstruction, UnaryOperation): def src(self) -> HighLevelILInstruction: return self.get_expr(0) - @property - def vars(self) -> VariablesList: - return self.src.vars - - @property - def vars_read(self) -> VariablesList: - return self.vars - @property def operands(self) -> List[HighLevelILOperandType]: return [self.src] @@ -690,14 +720,6 @@ class HighLevelILBinaryBase(HighLevelILInstruction, BinaryOperation): def right(self) -> HighLevelILInstruction: return self.get_expr(1) - @property - def vars(self) -> VariablesList: - return [*self.left.vars, *self.right.vars] - - @property - def vars_read(self) -> VariablesList: - return self.vars - @property def operands(self) -> List[HighLevelILOperandType]: return [self.left, self.right] @@ -723,14 +745,6 @@ class HighLevelILCarryBase(HighLevelILInstruction, Arithmetic): def carry(self) -> HighLevelILInstruction: return self.get_expr(2) - @property - def vars(self) -> VariablesList: - return [*self.left.vars, *self.right.vars, *self.carry.vars] - - @property - def vars_read(self) -> VariablesList: - return self.vars - @property def operands(self) -> List[HighLevelILOperandType]: return [self.left, self.right, self.carry] @@ -752,14 +766,6 @@ class HighLevelILBlock(HighLevelILInstruction): for expr in self.body: yield expr - @property - def vars(self) -> VariablesList: - return [v for i in self for v in i.vars] - - @property - def operands(self) -> List[HighLevelILInstruction]: - return self.body - @dataclass(frozen=True, repr=False) class HighLevelILIf(HighLevelILInstruction, ControlFlow): @@ -776,13 +782,9 @@ class HighLevelILIf(HighLevelILInstruction, ControlFlow): def false(self) -> HighLevelILInstruction: return self.get_expr(2) - @property - def vars(self) -> VariablesList: - return [*self.condition.vars, *self.true.vars, *self.false.vars] - @property def operands(self) -> List[HighLevelILOperandType]: - return [self.condition, self.true, self.false] + return [self.condition] @dataclass(frozen=True, repr=False) @@ -796,13 +798,9 @@ class HighLevelILWhile(HighLevelILInstruction, Loop): def body(self) -> HighLevelILInstruction: return self.get_expr(1) - @property - def vars(self) -> VariablesList: - return [*self.condition.vars, *self.body.vars] - @property def operands(self) -> List[HighLevelILOperandType]: - return [self.condition, self.body] + return [self.condition] @dataclass(frozen=True, repr=False) @@ -820,13 +818,9 @@ class HighLevelILWhile_ssa(HighLevelILInstruction, Loop, SSA): def body(self) -> HighLevelILInstruction: return self.get_expr(2) - @property - def vars(self) -> VariablesList: - return [*self.condition_phi.vars, *self.condition.vars, *self.body.vars] - @property def operands(self) -> List[HighLevelILOperandType]: - return [self.condition_phi, self.condition, self.body] + return [self.condition_phi, self.condition] @dataclass(frozen=True, repr=False) @@ -840,13 +834,9 @@ class HighLevelILDo_while(HighLevelILInstruction, Loop): def condition(self) -> HighLevelILInstruction: return self.get_expr(1) - @property - def vars(self) -> VariablesList: - return [*self.condition.vars, *self.body.vars] - @property def operands(self) -> List[HighLevelILOperandType]: - return [self.body, self.condition] + return [self.condition] @dataclass(frozen=True, repr=False) @@ -864,17 +854,9 @@ class HighLevelILDo_while_ssa(HighLevelILInstruction, Loop, SSA): def condition(self) -> HighLevelILInstruction: return self.get_expr(2) - @property - def vars(self) -> VariablesList: - return [*self.condition_phi.vars, *self.condition.vars, *self.body.vars] - - @property - def vars_read(self) -> VariablesList: - return self.condition.vars - @property def operands(self) -> List[HighLevelILOperandType]: - return [self.body, self.condition_phi, self.condition] + return [self.condition_phi, self.condition] @dataclass(frozen=True, repr=False) @@ -896,21 +878,9 @@ class HighLevelILFor(HighLevelILInstruction, Loop): def body(self) -> HighLevelILInstruction: return self.get_expr(3) - @property - def vars(self) -> VariablesList: - return [*self.init.vars, *self.condition.vars, *self.update.vars, *self.body.vars] - - @property - def vars_read(self) -> VariablesList: - return [*self.condition.vars, *self.update.vars_read, *self.init.vars_read, *self.body.vars_read] - - @property - def vars_written(self) -> VariablesList: - return [*self.update.vars_written, *self.init.vars_written] - @property def operands(self) -> List[HighLevelILOperandType]: - return [self.init, self.condition, self.update, self.body] + return [self.init, self.condition, self.update] @dataclass(frozen=True, repr=False) @@ -936,21 +906,9 @@ class HighLevelILFor_ssa(HighLevelILInstruction, Loop, SSA): def body(self) -> HighLevelILInstruction: return self.get_expr(3) - @property - def vars(self) -> VariablesList: - return [*self.init.vars, *self.condition_phi.vars, *self.condition.vars, *self.update.vars, *self.body.vars] - - @property - def vars_read(self) -> VariablesList: - return [*self.condition.vars, *self.update.vars_read, *self.init.vars_read, *self.body.vars_read] - - @property - def vars_written(self) -> VariablesList: - return [*self.update.vars_written, *self.init.vars_written] - @property def operands(self) -> List[HighLevelILOperandType]: - return [self.init, self.condition_phi, self.condition, self.update, self.body] + return [self.init, self.condition_phi, self.condition, self.update] @dataclass(frozen=True, repr=False) @@ -968,17 +926,9 @@ class HighLevelILSwitch(HighLevelILInstruction, ControlFlow): def cases(self) -> List[HighLevelILInstruction]: return self.get_expr_list(2, 3) - @property - def vars(self) -> VariablesList: - return [*self.condition.vars, *self.default.vars, *[v for i in self.cases for v in i.vars]] - - @property - def vars_read(self) -> VariablesList: - return [*self.condition.vars] - @property def operands(self) -> List[HighLevelILOperandType]: - return [self.condition, self.default, self.cases] + return [self.condition] @dataclass(frozen=True, repr=False) @@ -992,13 +942,9 @@ class HighLevelILCase(HighLevelILInstruction): def body(self) -> HighLevelILInstruction: return self.get_expr(2) - @property - def vars(self) -> VariablesList: - return [*[v for i in self.values for v in i.vars], *self.body.vars] - @property def operands(self) -> List[HighLevelILOperandType]: - return [self.values, self.body] + return [self.values] @dataclass(frozen=True, repr=False) @@ -1017,10 +963,6 @@ class HighLevelILJump(HighLevelILInstruction, Terminal): def dest(self) -> HighLevelILInstruction: return self.get_expr(0) - @property - def vars(self) -> VariablesList: - return self.dest.vars - @property def operands(self) -> List[HighLevelILOperandType]: return [self.dest] @@ -1033,10 +975,6 @@ class HighLevelILRet(HighLevelILInstruction, ControlFlow): def src(self) -> List[HighLevelILInstruction]: return self.get_expr_list(0, 1) - @property - def vars(self) -> VariablesList: - return [v for i in self.src for v in i.vars] - @property def operands(self) -> List[HighLevelILInstruction]: return self.src @@ -1078,10 +1016,6 @@ class HighLevelILVar_declare(HighLevelILInstruction): def var(self) -> 'variable.Variable': return self.get_var(0) - @property - def vars(self) -> VariablesList: - return [self.var] - @property def operands(self) -> List[HighLevelILOperandType]: return [self.var] @@ -1098,14 +1032,6 @@ class HighLevelILVar_init(HighLevelILInstruction): def src(self) -> HighLevelILInstruction: return self.get_expr(1) - @property - def vars(self) -> VariablesList: - return [self.dest, *self.src.vars] - - @property - def vars_read(self) -> VariablesList: - return self.src.vars - @property def vars_written(self) -> VariablesList: return [self.dest] @@ -1126,14 +1052,6 @@ class HighLevelILVar_init_ssa(HighLevelILInstruction, SSA): def src(self) -> HighLevelILInstruction: return self.get_expr(2) - @property - def vars(self) -> VariablesList: - return [self.dest, *self.src.vars] - - @property - def vars_read(self) -> VariablesList: - return self.src.vars - @property def vars_written(self) -> VariablesList: return [self.dest] @@ -1154,17 +1072,14 @@ class HighLevelILAssign(HighLevelILInstruction): def src(self) -> HighLevelILInstruction: return self.get_expr(1) - # @property - # def vars_written(self) -> VariablesList: - # return self.dest.vars - - # @property - # def vars_read(self) -> VariablesList: - # return self.src.vars - @property - def vars(self) -> VariablesList: - return [*self.src.vars, *self.dest.vars] + def vars_written(self) -> VariablesList: + if isinstance(self.dest, (HighLevelILSplit, HighLevelILVar)): + return [*self.dest.vars, *self.src.vars_written] + elif isinstance(self.dest, HighLevelILStruct_field): + return [*self.dest.vars, *self.src.vars_written] + else: + return [*self.dest.vars_written, *self.src.vars_written] @property def operands(self) -> List[HighLevelILOperandType]: @@ -1184,15 +1099,13 @@ class HighLevelILAssign_unpack(HighLevelILInstruction): @property def vars_written(self) -> VariablesList: - return [j for i in self.dest for j in i.vars_written] - - # @property - # def vars_read(self) -> VariablesList: - # return self.src.vars - - @property - def vars(self) -> VariablesList: - return [*self.vars_read, *self.vars_written] + result = [] + for i in self.dest: + if isinstance(i, HighLevelILVar): + result.append(i.var) + else: + result.extend(i.vars_written) + return result @property def operands(self) -> List[HighLevelILOperandType]: @@ -1242,14 +1155,6 @@ class HighLevelILAssign_unpack_mem_ssa(HighLevelILInstruction, SSA, Memory): def src_memory(self) -> int: return self.get_int(4) - @property - def vars_written(self) -> VariablesList: - return [v for i in self.dest for v in i.vars] - - @property - def vars_read(self) -> VariablesList: - return self.src.vars - @property def operands(self) -> List[HighLevelILOperandType]: return [self.dest, self.dest_memory, self.src, self.src_memory] @@ -1262,10 +1167,6 @@ class HighLevelILVar(HighLevelILInstruction): def var(self) -> 'variable.Variable': return self.get_var(0) - @property - def vars(self) -> VariablesList: - return [self.var] - @property def operands(self) -> List[HighLevelILOperandType]: return [self.var] @@ -1278,10 +1179,6 @@ class HighLevelILVar_ssa(HighLevelILInstruction, SSA): def var(self) -> 'mediumlevelil.SSAVariable': return self.get_var_ssa(0, 1) - @property - def vars(self) -> VariablesList: - return [self.var] - @property def operands(self) -> List[HighLevelILOperandType]: return [self.var] @@ -1302,14 +1199,6 @@ class HighLevelILVar_phi(HighLevelILInstruction, Phi): def vars_written(self) -> VariablesList: return [self.dest] - @property - def vars_read(self) -> VariablesList: - return self.src # type: ignore - - @property - def vars(self) -> VariablesList: - return [self.dest, *self.src] - @property def operands(self) -> List[HighLevelILOperandType]: return [self.dest, self.src] @@ -1346,15 +1235,10 @@ class HighLevelILStruct_field(HighLevelILInstruction): def member_index(self) -> Optional[int]: return self.get_member_index(2) - @property - def vars(self) -> VariablesList: - return self.src.vars - @property def operands(self) -> List[HighLevelILOperandType]: return [self.src, self.offset, self.member_index] - @dataclass(frozen=True, repr=False) class HighLevelILArray_index(HighLevelILInstruction): @@ -1366,18 +1250,10 @@ class HighLevelILArray_index(HighLevelILInstruction): def index(self) -> HighLevelILInstruction: return self.get_expr(1) - @property - def vars(self) -> VariablesList: - return [*self.src.vars, *self.index.vars] - @property def operands(self) -> List[HighLevelILOperandType]: return [self.src, self.index] - @property - def vars_used_in_address(self) -> VariablesList: - return self.src.vars - @dataclass(frozen=True, repr=False) class HighLevelILArray_index_ssa(HighLevelILInstruction, SSA): @@ -1394,14 +1270,6 @@ class HighLevelILArray_index_ssa(HighLevelILInstruction, SSA): def index(self) -> HighLevelILInstruction: return self.get_expr(2) - @property - def vars(self) -> VariablesList: - return [*self.src.vars, *self.index.vars] - - @property - def vars_used_in_address(self) -> VariablesList: - return self.src.vars - @property def operands(self) -> List[HighLevelILOperandType]: return [self.src, self.src_memory, self.index] @@ -1418,10 +1286,6 @@ class HighLevelILSplit(HighLevelILInstruction): def low(self) -> HighLevelILInstruction: return self.get_expr(1) - @property - def vars(self) -> VariablesList: - return [*self.high.vars, *self.low.vars] - @property def operands(self) -> List[HighLevelILOperandType]: return [self.high, self.low] @@ -1429,10 +1293,7 @@ class HighLevelILSplit(HighLevelILInstruction): @dataclass(frozen=True, repr=False) class HighLevelILDeref(HighLevelILUnaryBase): - - @property - def vars_used_in_address(self) -> VariablesList: - return self.vars + pass @dataclass(frozen=True, repr=False) @@ -1450,14 +1311,6 @@ class HighLevelILDeref_field(HighLevelILInstruction): def member_index(self) -> Optional[int]: return self.get_member_index(2) - @property - def vars(self) -> VariablesList: - return self.src.vars - - @property - def vars_used_in_address(self) -> VariablesList: - return self.vars - @property def operands(self) -> List[HighLevelILOperandType]: return [self.src, self.offset, self.member_index] @@ -1474,14 +1327,6 @@ class HighLevelILDeref_ssa(HighLevelILInstruction, SSA): def src_memory(self) -> int: return self.get_int(1) - @property - def vars(self) -> VariablesList: - return self.src.vars - - @property - def vars_used_in_address(self) -> VariablesList: - return self.vars - @property def operands(self) -> List[HighLevelILOperandType]: return [self.src, self.src_memory] @@ -1506,14 +1351,6 @@ class HighLevelILDeref_field_ssa(HighLevelILInstruction, SSA): def member_index(self) -> Optional[int]: return self.get_member_index(3) - @property - def vars(self) -> VariablesList: - return self.src.vars - - @property - def vars_used_in_address(self) -> VariablesList: - return self.vars - @property def operands(self) -> List[HighLevelILOperandType]: return [self.src, self.src_memory, self.offset, self.member_index] @@ -1522,17 +1359,13 @@ class HighLevelILDeref_field_ssa(HighLevelILInstruction, SSA): @dataclass(frozen=True, repr=False) class HighLevelILAddress_of(HighLevelILUnaryBase): - @property - def vars(self) -> VariablesList: - return self.src.vars - - @property - def vars_read(self) -> VariablesList: - return [] - @property def vars_address_taken(self) -> VariablesList: - return self.src.vars + if isinstance(self.src, HighLevelILVar): + return [self.src.var] + elif isinstance(self.src, HighLevelILStruct_field) and isinstance(self.src.src, HighLevelILVar): + return [self.src.src.var] + return [*self.src.vars_address_taken] @dataclass(frozen=True, repr=False) @@ -1760,14 +1593,6 @@ class HighLevelILCall(HighLevelILInstruction, Call): def params(self) -> List[HighLevelILInstruction]: return self.get_expr_list(1, 2) - @property - def vars_read(self) -> VariablesList: - return [*self.dest.vars, *[v for i in self.params for v in i.vars]] - - @property - def vars(self) -> VariablesList: - return self.vars_read - @property def operands(self) -> List[HighLevelILOperandType]: return [self.dest, self.params] @@ -1792,14 +1617,6 @@ class HighLevelILCall_ssa(HighLevelILInstruction, Call, SSA): def src_memory(self) -> int: return self.get_int(4) - @property - def vars_read(self) -> VariablesList: - return [*self.dest.vars, *[v for i in self.params for v in i.vars]] - - @property - def vars(self) -> VariablesList: - return self.vars_read - @property def operands(self) -> List[HighLevelILOperandType]: return [self.dest, self.params, self.dest_memory, self.src_memory] @@ -1877,14 +1694,6 @@ class HighLevelILSyscall(HighLevelILInstruction, Syscall): def params(self) -> List[HighLevelILInstruction]: return self.get_expr_list(0, 1) - @property - def vars_read(self) -> VariablesList: - return [v for i in self.params for v in i.vars] - - @property - def vars(self) -> VariablesList: - return self.vars_read - @property def operands(self) -> List[HighLevelILInstruction]: return self.params @@ -1905,14 +1714,6 @@ class HighLevelILSyscall_ssa(HighLevelILInstruction, Syscall, SSA): def src_memory(self) -> int: return self.get_int(3) - @property - def vars_read(self) -> VariablesList: - return [v for i in self.params for v in i.vars] - - @property - def vars(self) -> VariablesList: - return self.vars_read - @property def operands(self) -> List[HighLevelILOperandType]: return [self.params, self.dest_memory, self.src_memory] @@ -1929,14 +1730,6 @@ class HighLevelILTailcall(HighLevelILInstruction, Tailcall): def params(self) -> List[HighLevelILInstruction]: return self.get_expr_list(1, 2) - @property - def vars_read(self) -> VariablesList: - return [*self.dest.vars, *[v for i in self.params for v in i.vars]] - - @property - def vars(self) -> VariablesList: - return self.vars_read - @property def operands(self) -> List[HighLevelILOperandType]: return [self.dest, self.params] @@ -1970,14 +1763,6 @@ class HighLevelILIntrinsic(HighLevelILInstruction): def params(self) -> List[HighLevelILInstruction]: return self.get_expr_list(1, 2) - @property - def vars_read(self) -> VariablesList: - return [v for i in self.params for v in i.vars] - - @property - def vars(self) -> VariablesList: - return self.vars_read - @property def operands(self) -> List[HighLevelILOperandType]: return [self.intrinsic, self.params] @@ -2002,14 +1787,6 @@ class HighLevelILIntrinsic_ssa(HighLevelILInstruction, SSA): def src_memory(self) -> int: return self.get_int(3) - @property - def vars_read(self) -> VariablesList: - return [v for i in self.params for v in i.vars] - - @property - def vars(self) -> VariablesList: - return self.vars_read - @property def operands(self) -> List[HighLevelILOperandType]: return [self.intrinsic, self.params, self.dest_memory, self.src_memory] diff --git a/python/lowlevelil.py b/python/lowlevelil.py index a301dc2a..313feec4 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -1936,18 +1936,7 @@ class LowLevelILFlag_cond(LowLevelILInstruction): @dataclass(frozen=True, repr=False) class LowLevelILAdd_overflow(LowLevelILBinaryBase, Arithmetic): - - @property - def left(self) -> LowLevelILInstruction: - return self.get_expr(0) - - @property - def right(self) -> LowLevelILInstruction: - return self.get_expr(1) - - @property - def operands(self) -> List[LowLevelILOperandType]: - return [self.left, self.right] + pass @dataclass(frozen=True, repr=False) @@ -4686,13 +4675,13 @@ class LowLevelILBasicBlock(basicblock.BasicBlock): return self._il_function -def LLIL_TEMP(n:int) -> int: - return n | 0x80000000 +def LLIL_TEMP(n:Union[ILRegister, int]) -> int: + return int(n) | 0x80000000 -def LLIL_REG_IS_TEMP(n:int) -> bool: - return (n & 0x80000000) != 0 +def LLIL_REG_IS_TEMP(n:Union[ILRegister, int]) -> bool: + return (int(n) & 0x80000000) != 0 -def LLIL_GET_TEMP_REG_INDEX(n:int) -> int: - return n & 0x7fffffff +def LLIL_GET_TEMP_REG_INDEX(n:Union[ILRegister, int]) -> int: + return int(n) & 0x7fffffff diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 3ee5fc99..86927b0a 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -449,6 +449,10 @@ class MediumLevelILInstruction(ILInstruction): result.append(MediumLevelILOperationAndSize(self.operation, self.size)) return result + @property + def instruction_operands(self) -> List['MediumLevelILInstruction']: + return [i for i in self.operands if isinstance(i, MediumLevelILInstruction)] + @property def operands(self) -> List[MediumLevelILOperandType]: """Operands for the instruction""" @@ -470,6 +474,14 @@ class MediumLevelILInstruction(ILInstruction): result += operand.vars_read return result + @property + def vars_address_taken(self) -> List[Union[variable.Variable, SSAVariable]]: + """Non-unique list of variables whose address is taken by instruction""" + result = [] + for operand in self.instruction_operands: + result.extend(operand.vars_address_taken) + return result + @property def expr_type(self) -> Optional['types.Type']: """Type of expression""" @@ -909,6 +921,10 @@ class MediumLevelILAddress_of(MediumLevelILInstruction): def operands(self) -> List[variable.Variable]: return [self.src] + @property + def vars_address_taken(self) -> List[variable.Variable]: + return [self.src] + @dataclass(frozen=True, repr=False) class MediumLevelILConst(MediumLevelILConstBase): -- cgit v1.3.1