1
0
mirror of https://github.com/angr/angr synced 2026-06-08 13:09:39 +00:00
Files
angr-angr/tests/sim/test_self_modifying_code.py
T
pre-commit-ci[bot] 563fb5f862 [pre-commit.ci] pre-commit autoupdate (#6025)
* [pre-commit.ci] pre-commit autoupdate

updates:
- [github.com/astral-sh/ruff-pre-commit: v0.14.11 → v0.14.13](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.11...v0.14.13)
- [github.com/psf/black-pre-commit-mirror: 25.12.0 → 26.1.0](https://github.com/psf/black-pre-commit-mirror/compare/25.12.0...26.1.0)

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2026-01-19 13:37:06 -07:00

112 lines
4.2 KiB
Python
Executable File

#!/usr/bin/env python3
# pylint:disable=no-self-use,missing-class-docstring
from __future__ import annotations
__package__ = __package__ or "tests.sim" # pylint:disable=redefined-builtin
import os
from unittest import TestCase, main
import claripy
import angr
from angr import options as o
from tests.common import bin_location
test_location = os.path.join(bin_location, "tests")
class TestSelfModifyingCOde(TestCase):
def test_self_modifying_code(self):
p = angr.Project(os.path.join(test_location, "cgc", "stuff"), auto_load_libs=False, selfmodifying_code=True)
pg = p.factory.simulation_manager(p.factory.entry_state(add_options={o.STRICT_PAGE_ACCESS}))
# small issue: the program is bugged and uses illegal stack allocation patterns, bypassing the red page
# hack around this here
for offs in range(0, 0x6000, 0x1000):
pg.one_active.memory.load(pg.one_active.regs.sp - offs, size=1)
pg.run(until=lambda lpg: len(lpg.active) != 1)
retval = pg.one_deadended.regs.ebx
assert claripy.is_true(retval == 65)
pgu = p.factory.simulation_manager(p.factory.entry_state(add_options={o.STRICT_PAGE_ACCESS} | o.unicorn))
for offs in range(0, 0x6000, 0x1000):
pgu.one_active.memory.load(pgu.one_active.regs.sp - offs, size=1)
pgu.run(until=lambda lpg: len(lpg.active) != 1)
retval = pgu.one_deadended.regs.ebx
assert claripy.is_true(retval == 65)
# the two histories are not the same because angr does not add relifted block addresses (caused by raising
# SimReliftExceptions during execution) to the history. whether this is a good design decision or not is a
# question for another day. for now, we resort to a weaker check.
#
# assert pg.one_deadended.history.bbl_addrs.hardcopy == pgu.one_deadended.history.bbl_addrs.hardcopy
i, j = 0, 0
pg_bbl_addrs = pg.one_deadended.history.bbl_addrs.hardcopy
u_bbl_addrs = pgu.one_deadended.history.bbl_addrs.hardcopy
while i < len(pg_bbl_addrs) and j < len(u_bbl_addrs):
if pg_bbl_addrs[i] == u_bbl_addrs[j]:
i += 1
j += 1
elif pg_bbl_addrs[i] != u_bbl_addrs[j] and pg_bbl_addrs[i - 1] < u_bbl_addrs[j] < pg_bbl_addrs[i]:
# this is the missing relifted block address in angr's history. skip it
j += 1
else:
raise Exception("History mismatch")
assert i == len(pg_bbl_addrs)
assert j == len(u_bbl_addrs)
# also ensure that block.pp() does not raise any exceptions
p.factory.block(0xBAAA7B42, backup_state=pg.one_deadended).pp()
def test_self_modifying_code_overwrite_invalid_instruction(self):
# mov byte ptr [rip+invalid], 0x90
# invalid:
# .byte 0x6
# mov rax, 0x1234
# int3
code = b"\xc6\x05\x00\x00\x00\x00\x90\x06H\xc7\xc04\x12\x00\x00\xcc"
proj = angr.load_shellcode(code, "amd64", selfmodifying_code=True)
state = proj.factory.blank_state(addr=0, add_options={angr.options.SYMBOL_FILL_UNCONSTRAINED_REGISTERS})
simgr = proj.factory.simgr(state)
simgr.step()
assert len(simgr.active) == 1
rax = simgr.active[0].regs.rax
assert rax.concrete
assert rax.concrete_value == 0x1234
def test_self_modifying_code_overwrite_middle_of_invalid_instruction(self):
# xor rax, rax
# ; "ff ff" becomes "ff c0", which is is "inc eax"
# mov byte ptr [rip+invalid1], 0xc0
# .byte 0xff
# invalid1:
# .byte 0xff
# mov rbx, 0x1234
# int3
code = b"H1\xc0\xc6\x05\x01\x00\x00\x00\xc0\xff\xffH\xc7\xc34\x12\x00\x00\xcc"
proj = angr.load_shellcode(code, "amd64", selfmodifying_code=True)
state = proj.factory.blank_state(addr=0, add_options={angr.options.SYMBOL_FILL_UNCONSTRAINED_REGISTERS})
simgr = proj.factory.simgr(state)
simgr.step()
assert len(simgr.active) == 1
rax = simgr.active[0].regs.rax
assert rax.concrete
assert rax.concrete_value == 1
rbx = simgr.active[0].regs.rbx
assert rbx.concrete
assert rbx.concrete_value == 0x1234
if __name__ == "__main__":
main()