Skip to content

Commit f4a75e4

Browse files
committed
Merge branch 'rip/memory'
2 parents b8b5703 + 208e78a commit f4a75e4

104 files changed

Lines changed: 5690 additions & 5350 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

angr/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
from .storage.file import SimFileBase, SimFile, SimPackets, SimFileStream, SimPacketsStream, SimFileDescriptor, SimFileDescriptorDuplex
6262
from .state_plugins.filesystem import SimMount, SimHostFilesystem
6363
from .state_plugins.heap import SimHeapBrk, SimHeapPTMalloc, PTChunk
64+
from . import concretization_strategies
6465
from .distributed import Server
6566

6667
# for compatibility reasons

angr/analyses/cfg/indirect_jump_resolvers/jumptable.py

Lines changed: 76 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,12 @@ def _do_load(self, addr, size):
385385
class StoreHook:
386386
@staticmethod
387387
def hook(state):
388-
state.inspect.mem_write_expr = state.solver.BVS('instrumented_store',
389-
state.solver.eval(state.inspect.mem_write_length) * 8)
388+
write_length = state.inspect.mem_write_length
389+
if write_length is None:
390+
write_length = len(state.inspect.mem_write_expr)
391+
else:
392+
write_length = write_length * state.arch.byte_width
393+
state.inspect.mem_write_expr = state.solver.BVS('instrumented_store', write_length)
390394

391395

392396
class LoadHook:
@@ -421,6 +425,72 @@ def __init__(self, reg_offset, reg_bits, value):
421425
def hook(self, state):
422426
state.registers.store(self.reg_offset, state.solver.BVV(self.value, self.reg_bits))
423427

428+
429+
class BSSHook:
430+
def __init__(self, project, bss_regions):
431+
self.project = project
432+
self._bss_regions = bss_regions
433+
self._written_addrs = set()
434+
435+
def bss_memory_read_hook(self, state):
436+
437+
if not self._bss_regions:
438+
return
439+
440+
read_addr = state.inspect.mem_read_address
441+
read_length = state.inspect.mem_read_length
442+
443+
if not isinstance(read_addr, int) and read_addr.symbolic:
444+
# don't touch it
445+
return
446+
447+
concrete_read_addr = state.solver.eval(read_addr)
448+
concrete_read_length = state.solver.eval(read_length)
449+
450+
for start, size in self._bss_regions:
451+
if start <= concrete_read_addr < start + size:
452+
# this is a read from the .bss section
453+
break
454+
else:
455+
return
456+
457+
if concrete_read_addr not in self._written_addrs:
458+
# it was never written to before. we overwrite it with unconstrained bytes
459+
for i in range(0, concrete_read_length, self.project.arch.bytes):
460+
state.memory.store(concrete_read_addr + i, state.solver.Unconstrained('unconstrained',
461+
self.project.arch.bits))
462+
463+
# job done :-)
464+
465+
def bss_memory_write_hook(self, state):
466+
467+
if not self._bss_regions:
468+
return
469+
470+
write_addr = state.inspect.mem_write_address
471+
472+
if not isinstance(write_addr, int) and write_addr.symbolic:
473+
return
474+
475+
concrete_write_addr = state.solver.eval(write_addr)
476+
concrete_write_length = state.solver.eval(state.inspect.mem_write_length) \
477+
if state.inspect.mem_write_length is not None \
478+
else len(state.inspect.mem_write_expr) // state.arch.byte_width
479+
480+
for start, size in self._bss_regions:
481+
if start <= concrete_write_addr < start + size:
482+
# hit a BSS section
483+
break
484+
else:
485+
return
486+
487+
if concrete_write_length > 1024:
488+
l.warning("Writing more 1024 bytes to the BSS region, only considering the first 1024 bytes.")
489+
concrete_write_length = 1024
490+
491+
for i in range(concrete_write_addr, concrete_write_length):
492+
self._written_addrs.add(i)
493+
424494
#
425495
# Main class
426496
#
@@ -578,7 +648,10 @@ def _resolve(self, cfg, addr, func_addr, b):
578648

579649
# any read from an uninitialized segment should be unconstrained
580650
if self._bss_regions:
581-
bss_memory_read_bp = BP(when=BP_BEFORE, enabled=True, action=self._bss_memory_read_hook)
651+
bss_hook = BSSHook(self.project, self._bss_regions)
652+
bss_memory_write_bp = BP(when=BP_AFTER, enabled=True, action=bss_hook.bss_memory_write_hook)
653+
start_state.inspect.add_breakpoint('mem_write', bss_memory_write_bp)
654+
bss_memory_read_bp = BP(when=BP_BEFORE, enabled=True, action=bss_hook.bss_memory_read_hook)
582655
start_state.inspect.add_breakpoint('mem_read', bss_memory_read_bp)
583656

584657
# instrument specified store/put/load statements
@@ -1338,36 +1411,6 @@ def _find_bss_region(self):
13381411
self._bss_regions.append((section.vaddr, section.memsize))
13391412
break
13401413

1341-
def _bss_memory_read_hook(self, state):
1342-
1343-
if not self._bss_regions:
1344-
return
1345-
1346-
read_addr = state.inspect.mem_read_address
1347-
read_length = state.inspect.mem_read_length
1348-
1349-
if not isinstance(read_addr, int) and read_addr.symbolic:
1350-
# don't touch it
1351-
return
1352-
1353-
concrete_read_addr = state.solver.eval(read_addr)
1354-
concrete_read_length = state.solver.eval(read_length)
1355-
1356-
for start, size in self._bss_regions:
1357-
if start <= concrete_read_addr < start + size:
1358-
# this is a read from the .bss section
1359-
break
1360-
else:
1361-
return
1362-
1363-
if not state.memory.was_written_to(concrete_read_addr):
1364-
# it was never written to before. we overwrite it with unconstrained bytes
1365-
for i in range(0, concrete_read_length, self.project.arch.bytes):
1366-
state.memory.store(concrete_read_addr + i, state.solver.Unconstrained('unconstrained',
1367-
self.project.arch.bits))
1368-
1369-
# job done :-)
1370-
13711414
def _init_registers_on_demand(self, state):
13721415
# for uninitialized read using a register as the source address, we replace them in memory on demand
13731416
read_addr = state.inspect.mem_read_address

angr/analyses/congruency_check.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,15 @@ def _sync_steps(simgr, max_steps=None):
8383
elif simgr.left[0].history.block_count < simgr.right[0].history.block_count:
8484
l.debug("... right is ahead; stepping left %s times",
8585
simgr.right[0].history.block_count - simgr.left[0].history.block_count)
86-
npg = simgr.step(
86+
npg = simgr.run(
8787
stash='left',
8888
until=lambda lpg: lpg.left[0].history.block_count >= simgr.right[0].history.block_count,
8989
n=max_steps
9090
)
9191
elif simgr.right[0].history.block_count < simgr.left[0].history.block_count:
9292
l.debug("... left is ahead; stepping right %s times",
9393
simgr.left[0].history.block_count - simgr.right[0].history.block_count)
94-
npg = simgr.step(
94+
npg = simgr.run(
9595
stash='right',
9696
until=lambda lpg: lpg.right[0].history.block_count >= simgr.left[0].history.block_count,
9797
n=max_steps

angr/analyses/ddg.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ def kill_def(self, variable, location, size_threshold=32):
248248

249249
def lookup_defs(self, variable, size_threshold=32):
250250
"""
251-
Find all definitions of the varaible
251+
Find all definitions of the variable.
252252
253253
:param SimVariable variable: The variable to lookup for.
254254
:param int size_threshold: The maximum bytes to consider for the variable. For example, if the variable is 100

angr/analyses/identifier/runner.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def _get_recv_state(self):
5959
fake_flag_data = entry_state.solver.BVV(FLAG_DATA)
6060
entry_state.memory.store(0x4347c000, fake_flag_data)
6161
# map the place where I put arguments
62-
entry_state.memory.mem.map_region(0x2000, 0x10000, 7)
62+
entry_state.memory.map_region(0x2000, 0x10000, 7)
6363

6464
entry_state.unicorn._register_check_count = 100
6565
entry_state.unicorn._runs_since_symbolic_data = 100

angr/analyses/vfg.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import logging
22
from collections import defaultdict
33

4-
import angr
54
import archinfo
65
from archinfo.arch_arm import is_arm_arch
76
import claripy
@@ -12,7 +11,7 @@
1211
from .cfg.cfg_utils import CFGUtils
1312
from .forward_analysis import ForwardAnalysis
1413
from .. import sim_options
15-
from ..engines.procedure import ProcedureMixin
14+
from ..engines.procedure import ProcedureEngine
1615
from ..engines import SimSuccessors
1716
from ..errors import AngrDelayJobNotice, AngrSkipJobNotice, AngrVFGError, AngrError, AngrVFGRestartAnalysisNotice, \
1817
AngrJobMergingFailureNotice, SimValueError, SimIRSBError, SimError
@@ -1344,22 +1343,22 @@ def _get_simsuccessors(self, state, addr):
13441343
error_occured = True
13451344
inst = SIM_PROCEDURES["stubs"]["PathTerminator"](
13461345
state, self.project.arch)
1347-
sim_successors = SimEngineProcedure().process(state, inst)
1346+
sim_successors = ProcedureEngine().process(state, procedure=inst)
13481347
except claripy.ClaripyError:
13491348
l.error("ClaripyError: ", exc_info=True)
13501349
error_occured = True
13511350
# Generate a PathTerminator to terminate the current path
13521351
inst = SIM_PROCEDURES["stubs"]["PathTerminator"](
13531352
state, self.project.arch)
1354-
sim_successors = SimEngineProcedure().process(state, inst)
1353+
sim_successors = ProcedureEngine().process(state, procedure=inst)
13551354
except SimError:
13561355
l.error("SimError: ", exc_info=True)
13571356

13581357
error_occured = True
13591358
# Generate a PathTerminator to terminate the current path
13601359
inst = SIM_PROCEDURES["stubs"]["PathTerminator"](
13611360
state, self.project.arch)
1362-
sim_successors = SimEngineProcedure().process(state, inst)
1361+
sim_successors = ProcedureEngine().process(state, procedure=inst)
13631362
except AngrError as ex:
13641363
#segment = self.project.loader.main_object.in_which_segment(addr)
13651364
l.error("AngrError %s when generating SimSuccessors at %#x",
@@ -1412,13 +1411,15 @@ def _create_new_jobs(self, job, successor, new_block_id, new_call_stack):
14121411
sp_difference = current_function.sp_delta
14131412
else:
14141413
sp_difference = 0
1415-
reg_sp_offset = successor_state.arch.sp_offset
1416-
reg_sp_expr = successor_state.registers.load(reg_sp_offset) + sp_difference
1417-
successor_state.registers.store(successor_state.arch.sp_offset, reg_sp_expr)
1414+
arch = successor_state.arch
1415+
reg_sp_offset = arch.sp_offset
1416+
reg_sp_expr = successor_state.registers.load(reg_sp_offset, size=arch.bytes,
1417+
endness=arch.register_endness) + sp_difference
1418+
successor_state.registers.store(arch.sp_offset, reg_sp_expr)
14181419

14191420
# Clear the return value with a TOP
1420-
top_si = successor_state.solver.TSI(successor_state.arch.bits)
1421-
successor_state.registers.store(successor_state.arch.ret_offset, top_si)
1421+
top_si = successor_state.solver.TSI(arch.bits)
1422+
successor_state.registers.store(arch.ret_offset, top_si)
14221423

14231424
if job.call_skipped:
14241425

@@ -1601,8 +1602,9 @@ def _is_return_jumpkind(jumpkind):
16011602

16021603
@staticmethod
16031604
def _create_stack_region(successor_state, successor_ip):
1604-
reg_sp_offset = successor_state.arch.sp_offset
1605-
reg_sp_expr = successor_state.registers.load(reg_sp_offset)
1605+
arch = successor_state.arch
1606+
reg_sp_offset = arch.sp_offset
1607+
reg_sp_expr = successor_state.registers.load(reg_sp_offset, size=arch.bytes, endness=arch.register_endness)
16061608

16071609
if type(reg_sp_expr._model_vsa) is claripy.BVV: # pylint:disable=unidiomatic-typecheck
16081610
reg_sp_val = successor_state.solver.eval(reg_sp_expr)
@@ -1619,7 +1621,7 @@ def _create_stack_region(successor_state, successor_ip):
16191621
reg_sp_si = next(iter(reg_sp_expr._model_vsa.items()))[1]
16201622
reg_sp_val = reg_sp_si.min
16211623

1622-
reg_sp_val = reg_sp_val - successor_state.arch.bytes # TODO: Is it OK?
1624+
reg_sp_val = reg_sp_val - arch.bytes # TODO: Is it OK?
16231625
new_stack_region_id = successor_state.memory.stack_id(successor_ip)
16241626
successor_state.memory.set_stack_address_mapping(reg_sp_val,
16251627
new_stack_region_id,

angr/analyses/vsa_ddg.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ def _dump_edge_from_dict(dict_, key, del_key=True):
253253
if a.type == "mem":
254254
if a.actual_addrs is None:
255255
# For now, mem reads don't necessarily have actual_addrs set properly
256-
addr_list = set(state.memory.normalize_address(a.addr.ast, convert_to_valueset=True))
256+
addr_list = set(aw.to_valueset(state) for aw in state.memory._concretize_address_descriptor(a.addr.ast))
257257
else:
258258
addr_list = set(a.actual_addrs)
259259

angr/block.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ def __init__(self, addr, project=None, arch=None, size=None, byte_string=None, v
9090
if byte_string is None:
9191
if backup_state is not None:
9292
self._bytes = self._vex_engine._load_bytes(addr - thumb, size, state=backup_state)[0]
93-
if type(self._bytes) is not bytes:
93+
if type(self._bytes) is memoryview:
94+
self._bytes = bytes(self._bytes)
95+
elif type(self._bytes) is not bytes:
9496
self._bytes = bytes(pyvex.ffi.buffer(self._bytes, size))
9597
else:
9698
self._bytes = None

angr/concretization_strategies/controlled_data.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def __init__(self, limit, fixed_addrs, **kwargs):
1515

1616
def _concretize(self, memory, addr):
1717
# Get all symbolic variables in memory
18-
symbolic_vars = filter(lambda key: not key.startswith("reg_") and not key.startswith("mem_"), memory.mem._name_mapping.keys())
18+
symbolic_vars = filter(lambda key: not key.startswith("reg_") and not key.startswith("mem_"), memory._name_mapping.keys())
1919
controlled_addrs = sorted([_addr for s_var in symbolic_vars for _addr in memory.addrs_for_name(s_var)])
2020
controlled_addrs.extend(self._fixed_addrs)
2121

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
1+
from typing import Optional
2+
3+
from ..errors import SimSolverError
14
from . import SimConcretizationStrategy
25

6+
37
class SimConcretizationStrategyMax(SimConcretizationStrategy):
48
"""
59
Concretization strategy that returns the maximum address.
610
"""
711

12+
def __init__(self, max_addr: Optional[int]=None):
13+
super().__init__()
14+
self._max_addr = max_addr
15+
816
def _concretize(self, memory, addr):
9-
return [ self._max(memory, addr) ]
17+
if self._max_addr is None:
18+
return [ self._max(memory, addr) ]
19+
else:
20+
try:
21+
return [ self._max(memory, addr, extra_constraints=(addr <= self._max_addr,)) ]
22+
except SimSolverError:
23+
return [ self._max(memory, addr) ]

0 commit comments

Comments
 (0)