SimEngineclass) to emulate the effects that of a given section of code has on an input state. The execution core of angr simply tries all the available engines in sequence, taking the first one that is able to handle the step. The following is the default list of engines, in order:
UNICORNstate option is enabled and there is no symbolic data in the state
project.factory.successors(state, **kwargs), which passes its arguments onto each of the engines. This function is at the heart of
simulation_manager.step(). It returns a SimSuccessors object, which we discussed briefly before. The purpose of SimSuccessors is to perform a simple categorization of the successor states, stored in various list attributes. They are:
successorslist can have symbolic instruction pointers. This is rather confusing, as elsewhere in the code (i.e., in
SimEngineVEX.process, when it's time to step that state forward), we make assumptions that a single program state only represents the execution of a single spot in the code. To alleviate this, when we encounter states in
successorswith symbolic instruction pointers, we compute all possible concrete solutions (up to an arbitrary threshold of 256) for them, and make a copy of the state for each such solution. We call this process "flattening". These
flat_successorsare states, each of which has a different, concrete instruction pointer. For example, if the instruction pointer of a state in
Xhad constraints of
X > 0x800000and
X <= 0x800010, we would flatten it into 16 different
flat_successorsstates, one with an instruction pointer of
0x800006, one with
0x800007, and so on until
unconstrained_successorsand not in
successors + unsat_successors + unconstrained_successors.
state.inspectduring the appropriate breakpoint callback to access the appropriate values. You can even modify these value to modify further uses of the values!
inspect.bto make the breakpoint conditional:
mem_readbreakpoint gets triggered anytime there are memory reads by either the executing program or the binary analysis. If you are using breakpoint on
mem_readand also using
state.memto load data from memory addresses, then know that the breakpoint will be fired as you are technically reading memory.
mem_readbreakpoint you have had set up, then use
state.memory.loadwith the keyword arguments
state.findand you can use the same keyword arguments to prevent
mem_readbreakpoints from firing.