active
stash, which is where your states get put when you initialize a new simulation manager..step()
..run()
method.exit
syscall, it is removed from the active stash and placed in the deadended
stash..move()
, which takes from_stash
, to_stash
, and filter_func
(optional, default is to move everything). For example, let's move everything that has a certain string in its output:one_
, you will be given the first state in the stash. If you prepend the name of a stash with mp_
, you will be given a mulpyplexed version of the stash.step
, run
, and any other method that operates on a single stash of paths can take a stash
argument, specifying which stash to operate on.LAZY_SOLVES
, states are not checked for satisfiability unless absolutely necessary. When a state is found to be unsat in the presence of LAZY_SOLVES
, the state hierarchy is traversed to identify when, in its history, it initially became unsat. All states that are descendants of that point (which will also be unsat, since a state cannot become un-unsat) are pruned and put in this stash.save_unconstrained
option is provided to the SimulationManager constructor, states that are determined to be unconstrained (i.e., with the instruction pointer controlled by user data or some other source of symbolic data) are placed here.save_unsat
option is provided to the SimulationManager constructor, states that are determined to be unsatisfiable (i.e., they have constraints that are contradictory, like the input having to be both "AAAA" and "BBBB" at the same time) are placed here.errored
. If, during execution, an error is raised, then the state will be wrapped in an ErrorRecord
object, which contains the state and the error it raised, and then the record will be inserted into errored
. You can get at the state as it was at the beginning of the execution tick that caused the error with record.state
, you can see the error that was raised with record.error
, and you can launch a debug shell at the site of the error with record.debug()
. This is an invaluable debugging tool!.explore()
method..explore()
with a find
argument, execution will run until a state is found that matches the find condition, which can be the address of an instruction to stop at, a list of addresses to stop at, or a function which takes a state and returns whether it meets some criteria. When any of the states in the active stash match the find
condition, they are placed in the found
stash, and execution terminates. You can then explore the found state, or decide to discard it and continue with the other ones. You can also specify an avoid
condition in the same format as find
. When a state matches the avoid condition, it is put in the avoided
stash, and execution continues. Finally, the num_find
argument controls the number of states that should be found before returning, with a default of 1. Of course, if you run out of states in the active stash before finding this many solutions, execution will stop anyway.simgr.use_technique(tech)
, where tech is an instance of an ExplorationTechnique subclass. angr's built-in exploration techniques can be found under angr.exploration_techniques
.deferred
stash until it deadends or errors..explore()
functionality, allowing you to search for and avoid addresses.spinning
stash and pulling them out again if we run out of otherwise viable states.veritesting=True
in the SimulationManager constructor! Note that it frequenly doesn't play nice with other techniques due to the invasive way it implements static symbolic execution.