mirror of
https://github.com/angr/angr
synced 2026-08-17 12:23:11 -04:00
Preserve indirect store addresses across type casts
This commit is contained in:
parent
503b1be066
commit
83d7c034ba
2 changed files with 64 additions and 8 deletions
|
|
@ -3328,15 +3328,18 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis, Serializab
|
|||
lvalue: bool,
|
||||
renegotiate_type: Callable[[SimType, SimType], SimType] = lambda old, proposed: old,
|
||||
) -> CExpression:
|
||||
def _force_type_cast(src_type_: SimType, dst_type_: SimType, expr_: CExpression) -> CUnaryOp:
|
||||
def _force_type_cast(
|
||||
src_type_: SimType, dst_type_: SimType, expr_: CExpression, take_reference: bool
|
||||
) -> CUnaryOp:
|
||||
src_type_ptr = SimTypePointer(src_type_).with_arch(self.project.arch)
|
||||
dst_type_ptr = SimTypePointer(dst_type_).with_arch(self.project.arch)
|
||||
cast_expr = CUnaryOp("Reference", expr_, codegen=self) if take_reference else expr_
|
||||
return CUnaryOp(
|
||||
"Dereference",
|
||||
CTypeCast(
|
||||
src_type_ptr,
|
||||
dst_type_ptr,
|
||||
CUnaryOp("Reference", expr_, codegen=self),
|
||||
cast_expr,
|
||||
codegen=self,
|
||||
),
|
||||
codegen=self,
|
||||
|
|
@ -3369,11 +3372,11 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis, Serializab
|
|||
# case 2: we're done because we can never find it and we might as well stop early
|
||||
if base_expr:
|
||||
if not type_equals(base_type, data_type):
|
||||
return _force_type_cast(base_type, data_type, base_expr)
|
||||
return _force_type_cast(base_type, data_type, base_expr, True)
|
||||
return base_expr
|
||||
|
||||
if not type_equals(base_type, data_type):
|
||||
return _force_type_cast(base_type, data_type, expr)
|
||||
return _force_type_cast(base_type, data_type, expr, False)
|
||||
return CUnaryOp("Dereference", expr, codegen=self)
|
||||
|
||||
stride = 1 if base_type.size is None else base_type.size // self.project.arch.byte_width or 1
|
||||
|
|
|
|||
|
|
@ -7,7 +7,20 @@ __package__ = __package__ or "tests.analyses.decompiler" # pylint:disable=redef
|
|||
import unittest
|
||||
|
||||
import angr
|
||||
from angr.ailment import Expr
|
||||
from angr.ailment import Expr, Manager, Stmt
|
||||
from angr.ailment.expression import VirtualVariableCategory
|
||||
from angr.analyses.decompiler import CStructuredCodeGenerator
|
||||
from angr.analyses.decompiler.variable_map import VariableMap
|
||||
from angr.sim_type import SimTypeChar, SimTypePointer
|
||||
from angr.sim_variable import SimRegisterVariable, SimStackVariable
|
||||
|
||||
|
||||
def _make_codegen() -> CStructuredCodeGenerator:
|
||||
proj = angr.load_shellcode(b"\x31\xc0\xc3", arch="AMD64")
|
||||
cfg = proj.analyses.CFGFast(normalize=True)
|
||||
codegen = proj.analyses.Decompiler(cfg.functions[0], cfg=cfg).codegen
|
||||
assert isinstance(codegen, CStructuredCodeGenerator)
|
||||
return codegen
|
||||
|
||||
|
||||
class TestConvertRendering(unittest.TestCase):
|
||||
|
|
@ -16,9 +29,7 @@ class TestConvertRendering(unittest.TestCase):
|
|||
@classmethod
|
||||
def setUpClass(cls):
|
||||
# any decompilation will do; all we need is a codegen instance to render expressions with
|
||||
proj = angr.load_shellcode(b"\x31\xc0\xc3", arch="AMD64") # xor eax, eax; ret
|
||||
cfg = proj.analyses.CFGFast(normalize=True)
|
||||
cls.codegen = proj.analyses.Decompiler(cfg.functions[0], cfg=cfg).codegen
|
||||
cls.codegen = _make_codegen()
|
||||
|
||||
def _render(self, from_bits: int, to_bits: int, value: int = 0x1234) -> str:
|
||||
conv = Expr.Convert(0, from_bits, to_bits, False, Expr.Const(0, value, from_bits))
|
||||
|
|
@ -43,5 +54,47 @@ class TestConvertRendering(unittest.TestCase):
|
|||
assert self._render(32, 64, value=3) == "(unsigned long long)3"
|
||||
|
||||
|
||||
class TestStoreRendering(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.codegen = _make_codegen()
|
||||
|
||||
def test_mismatched_store_cast_distinguishes_pointer_from_storage(self):
|
||||
manager = Manager(arch=self.codegen.project.arch)
|
||||
addr = Expr.VirtualVariable(
|
||||
manager.next_atom(), 1, self.codegen.project.arch.bits, VirtualVariableCategory.REGISTER
|
||||
)
|
||||
data = Expr.Const(manager.next_atom(), 0x11223344, 32)
|
||||
pointer_store = Stmt.Store(
|
||||
manager.next_atom(), addr, data, 4, self.codegen.project.arch.memory_endness, ins_addr=0x401000
|
||||
)
|
||||
direct_store = Stmt.Store(
|
||||
manager.next_atom(), addr, data, 4, self.codegen.project.arch.memory_endness, ins_addr=0x401004
|
||||
)
|
||||
addr_variable = SimRegisterVariable(0x28, self.codegen.project.arch.bytes, ident="ir_test", name="iter")
|
||||
storage_variable = SimStackVariable(-0x10, 4, ident="is_test", name="storage")
|
||||
variable_map = VariableMap()
|
||||
variable_map.set_variable(addr, addr_variable)
|
||||
variable_map.set_variable(direct_store, storage_variable)
|
||||
|
||||
variable_manager = self.codegen.kb.dec_variables[self.codegen._func.addr]
|
||||
variable_manager.set_unified_variable(addr_variable, addr_variable)
|
||||
variable_manager.set_unified_variable(storage_variable, storage_variable)
|
||||
variable_manager.set_variable_type(
|
||||
addr_variable, SimTypePointer(SimTypeChar()).with_arch(self.codegen.project.arch)
|
||||
)
|
||||
variable_manager.set_variable_type(storage_variable, SimTypeChar().with_arch(self.codegen.project.arch))
|
||||
old_variable_map = self.codegen._variable_map
|
||||
self.codegen._variable_map = variable_map
|
||||
try:
|
||||
pointer_rendered = self.codegen._handle(pointer_store, is_expr=False).c_repr()
|
||||
direct_rendered = self.codegen._handle(direct_store, is_expr=False).c_repr()
|
||||
finally:
|
||||
self.codegen._variable_map = old_variable_map
|
||||
|
||||
assert direct_rendered == "*((unsigned int *)&storage) = 287454020;\n"
|
||||
assert pointer_rendered == "*((unsigned int *)iter) = 287454020;\n"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue