Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def _get_last_statement(self, block):
if type(block) is SequenceNode:
if block.nodes:
return self._get_last_statement(block.nodes[-1])
elif type(block) is CodeNode:
return self._get_last_statement(block.node)
elif type(block) is ailment.Block:
if not block.statements:
raise EmptyBlockNotice()
return block.statements[-1]
elif type(block) is Block:
return block.vex.statements[-1]
elif type(block) is BlockNode:
b = self.project.factory.block(block.addr, size=block.size)
return b.vex.statements[-1]
elif type(block) is MultiNode:
# get the last node
for the_block in reversed(block.nodes):
try:
last_stmt = self._get_last_statement(the_block)
return last_stmt
except EmptyBlockNotice:
continue
self._sequence = sequence
self._cfg = cfg
self.text = None
self.posmap = None
self.nodemap = None
self._indent = indent
self._handlers = {
SequenceNode: self._handle_Sequence,
CodeNode: self._handle_Code,
LoopNode: self._handle_Loop,
ConditionNode: self._handle_Condition,
ConditionalBreakNode: self._handle_ConditionalBreak,
MultiNode: self._handle_MultiNode,
Block: self._handle_AILBlock,
# AIL statements
Stmt.Store: self._handle_Stmt_Store,
Stmt.Assignment: self._handle_Stmt_Assignment,
Stmt.Call: self._handle_Stmt_Call,
# AIL expressions
Expr.Register: self._handle_Expr_Register,
Expr.Load: self._handle_Expr_Load,
Expr.Tmp: self._handle_Expr_Tmp,
Expr.Const: self._handle_Expr_Const,
Expr.UnaryOp: self._handle_Expr_UnaryOp,
Expr.BinaryOp: self._handle_Expr_BinaryOp,
Expr.Convert: self._handle_Expr_Convert,
Expr.StackBaseOffset: self._handle_Expr_StackBaseOffset,
Expr.DirtyExpression: self._handle_Expr_Dirty,
# SimVariables
SimStackVariable: self._handle_Variable_SimStackVariable,
def _convert_all(self):
"""
:return:
"""
for block_node in self.function.graph.nodes():
ail_block = self._convert(block_node)
if type(ail_block) is ailment.Block:
self._blocks[(block_node.addr, block_node.size)] = ail_block
self.node_observe(node.addr, state, OP_BEFORE)
state = state.copy()
state, self._visited_blocks = engine.process(
state,
block=block,
fail_fast=self._fail_fast,
visited_blocks=self._visited_blocks
)
self._node_iterations[block_key] += 1
if not self._graph_visitor.successors(node):
# no more successors. kill definitions of certain registers
if isinstance(node, ailment.Block):
codeloc = CodeLocation(node.addr, len(node.statements))
elif isinstance(node, Block):
codeloc = CodeLocation(node.addr, len(node.vex.statements))
else: #if isinstance(node, CodeNode):
codeloc = CodeLocation(node.addr, 0)
state.kill_definitions(Register(self.project.arch.sp_offset, self.project.arch.bytes),
codeloc)
state.kill_definitions(Register(self.project.arch.ip_offset, self.project.arch.bytes),
codeloc)
self.node_observe(node.addr, state, OP_AFTER)
if self._node_iterations[block_key] < self._max_iterations:
return True, state
else:
return False, state
cond = last_stmt.condition
target = last_stmt.true_target.value
elif last_stmt.false_target.value in loop_successors and \
last_stmt.true_target.value in loop_nodes:
cond = ailment.Expr.UnaryOp(last_stmt.condition.idx, 'Not', (last_stmt.condition))
target = last_stmt.false_target.value
else:
l.warning("I'm not sure which branch is jumping out of the loop...")
raise Exception()
# remove the last statement from the node
self._remove_last_statement(node)
new_node = ConditionalBreakNode(last_stmt.ins_addr, cond, target)
if new_node is not None:
# special checks if node goes empty
if isinstance(node, ailment.Block) and not node.statements:
replaced_nodes[node] = new_node
preds = list(loop_region_graph.predecessors(node))
loop_region_graph.remove_node(node)
for pred in preds:
loop_region_graph.add_edge(pred, new_node)
else:
loop_region_graph.add_edge(node, new_node)
# update node
node = new_node
for dst in successors:
# sanity check
if dst not in loop_subgraph:
# what's this node?
l.error("Found a node that belongs to neither loop body nor loop successors. Something is wrong.")
raise Exception()
def _init_subject(subject):
"""
:param ailment.Block|angr.Block|Function subject:
:return Tuple[ailment.Block|angr.Block, SimCC, Function, GraphVisitor, Boolean]:
Return the values for `_block`, `_cc`, `_function`, `_graph_visitor`, `_init_func`.
"""
if isinstance(subject, Function):
return (None, cc, subject, FunctionGraphVisitor(subject, func_graph), init_func)
elif isinstance(subject, (ailment.Block, Block)):
return (subject, None, None, SingleNodeGraphVisitor(subject), False)
else:
raise ValueError('Unsupported analysis target.')
def _process_block(self, state, block): # pylint:disable=no-self-use
"""
Scan through all statements and perform the following tasks:
- Find stack pointers and the VEX temporary variable storing stack pointers
- Selectively calculate VEX statements
- Track memory loading and mark stack and global variables accordingly
:param angr.Block block:
:return:
"""
l.debug('Processing block %#x.', block.addr)
processor = self._ail_engine if isinstance(block, ailment.Block) else self._vex_engine
processor.process(state, block=block, fail_fast=self._fail_fast)
# readjusting sp at the end for blocks that end in a call
if block.addr in self._node_to_cc:
cc = self._node_to_cc[block.addr]
if cc is not None and cc.sp_delta is not None:
state.processor_state.sp_adjustment += cc.sp_delta
state.processor_state.sp_adjusted = True
l.debug('Adjusting stack pointer at end of block %#x with offset %+#x.',
block.addr, state.processor_state.sp_adjustment)
def _run_on_node(self, node, state):
if isinstance(node, ailment.Block):
block = node
block_key = node.addr
engine = self._engine_ail
else:
block = self.project.factory.block(node.addr, node.size, opt_level=0)
block_key = node.addr
engine = self._engine_vex
state = state.copy()
state = engine.process(state, block=block, fail_fast=self._fail_fast)
# clear the tmp store
# state.tmp_uses.clear()
# state.tmp_definitions.clear()
self._node_iterations[block_key] += 1
# Initialize handler map
self.GOTO_HANDLERS = {
SequenceNode: self._goto_handle_sequencenode,
CodeNode: self._goto_handle_codenode,
MultiNode: self._goto_handle_multinode,
LoopNode: self._goto_handle_loopnode,
ConditionNode: self._goto_handle_conditionnode,
ailment.Block: self._goto_handle_block,
}
self.IFS_HANDLERS = {
SequenceNode: self._ifs_handle_sequencenode,
CodeNode: self._ifs_handle_codenode,
MultiNode: self._ifs_handle_multinode,
LoopNode: self._ifs_handle_loopnode,
ConditionNode: self._ifs_handle_conditionnode,
ailment.Block: self._ifs_handle_block,
}
self._simplify()
def _initial_abstract_state(self, node):
if isinstance(node, ailment.Block):
# AIL
state = PropagatorAILState(arch=self.project.arch)
else:
# VEX
state = PropagatorVEXState(arch=self.project.arch)
state.store_register(self.project.arch.sp_offset,
self.project.arch.bytes,
SpOffset(self.project.arch.bits, 0)
)
return state