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_state_of_method(method_name):
# get SootAddressDescriptor of method entry
soot_method = next(project.loader.main_object.get_method(method_name))
method = SootMethodDescriptor.from_soot_method(soot_method)
addr = SootAddressDescriptor(method, 0, 0)
# create call state
state = project.factory.blank_state(addr=addr)
# run until no successors exists
# Note: this does not work if conditional branches are present
states = [state]
succ = states[-1].step()
while len(succ.successors) == 1:
states += succ
succ = states[-1].step()
# last state is the 'Terminator' state
# => return the state before
return states[-2]
def get_entry_state_of_method(project, method_fullname):
# get SootAddressDescriptor of method entry
soot_method = project.loader.main_object.get_soot_method(method_fullname)
method = SootMethodDescriptor.from_soot_method(soot_method)
addr = SootAddressDescriptor(method, 0, 0)
# create call state
return project.factory.blank_state(addr=addr, add_options={angr.options.ZERO_FILL_UNCONSTRAINED_MEMORY})
def get_entry_state_of_method(project, method_fullname):
# get SootAddressDescriptor of method entry
soot_method = project.loader.main_object.get_soot_method(method_fullname)
method = SootMethodDescriptor.from_soot_method(soot_method)
addr = SootAddressDescriptor(method, 0, 0)
# create call state
return project.factory.blank_state(addr=addr)
def address(self, block_idx=0, stmt_idx=0):
"""
:return Address of the method.
:rtype: SootAddressDescriptor
"""
return SootAddressDescriptor(self, block_idx, stmt_idx)
successors = [ ]
has_default_exit = True
next_stmt_id = block.label + len(block.statements)
last_stmt_id = method.blocks[-1].label + len(method.blocks[-1].statements) - 1
if next_stmt_id >= last_stmt_id:
# there should not be a default exit going to the next block
has_default_exit = False
# scan through block statements, looking for those that generate new exits
for stmt in block.statements[addr.stmt_idx - block.label : ]:
if isinstance(stmt, IfStmt):
succ = (stmt.label, addr,
SootAddressDescriptor(function_id, method.block_by_label[stmt.target].idx, stmt.target),
'Ijk_Boring'
)
successors.append(succ)
elif isinstance(stmt, InvokeStmt):
invoke_expr = stmt.invoke_expr
succs = self._soot_create_invoke_successors(stmt, addr, invoke_expr)
if succs:
successors.extend(succs)
has_default_exit = False
break
elif isinstance(stmt, GotoStmt):
target = stmt.target
succ = (stmt.label, addr, SootAddressDescriptor(function_id, method.block_by_label[target].idx, target),
# setup callsite
ret_addr = self._get_next_linear_instruction(state, stmt_idx)
if 'NATIVE' in method.attrs:
# the target of the call is a native function
# => we need to setup a native call-site
l.debug("Native invoke: %r", method)
addr = self.project.simos.get_addr_of_native_method(method)
if not addr:
# native function could not be found
# => skip invocation and continue execution linearly
return False
invoke_state = self._setup_native_callsite(invoke_state, addr, method, args, ret_addr, ret_var)
else:
l.debug("Invoke: %r", method)
self.setup_callsite(invoke_state, args, ret_addr, ret_var)
addr = SootAddressDescriptor(method, 0, 0)
# add invoke state as the successor and terminate execution
# prematurely, since Soot does not guarantee that an invoke stmt
# terminates a block
successors.add_successor(invoke_state, addr, state.solver.true, 'Ijk_Call')
return True
# add jmp exit
elif s_stmt.has_jump_targets:
for target, condition in s_stmt.jmp_targets_with_conditions:
if not target:
target = self._get_next_linear_instruction(state, stmt_idx)
l.debug("Possible jump: %s -> %s", state._ip, target)
successors.add_successor(state.copy(), target, condition, 'Ijk_Boring')
return True
# add return exit
'Ijk_Boring'
)
successors.append(succ)
elif isinstance(stmt, InvokeStmt):
invoke_expr = stmt.invoke_expr
succs = self._soot_create_invoke_successors(stmt, addr, invoke_expr)
if succs:
successors.extend(succs)
has_default_exit = False
break
elif isinstance(stmt, GotoStmt):
target = stmt.target
succ = (stmt.label, addr, SootAddressDescriptor(function_id, method.block_by_label[target].idx, target),
'Ijk_Boring')
successors.append(succ)
# blocks ending with a GoTo should not have a default exit
has_default_exit = False
break
elif isinstance(stmt, AssignStmt):
expr = stmt.right_op
if isinstance(expr, SootInvokeExpr):
succs = self._soot_create_invoke_successors(stmt, addr, expr)
if succs:
successors.extend(succs)
has_default_exit = False
def _loc_to_funcloc(self, location):
if isinstance(location, SootAddressDescriptor):
return location.method
return location
def _get_next_linear_instruction(state, stmt_idx):
addr = state.addr.copy()
addr.stmt_idx = stmt_idx
method = state.regs._ip_binary.get_soot_method(addr.method)
current_bb = method.blocks[addr.block_idx]
new_stmt_idx = addr.stmt_idx + 1
if new_stmt_idx < len(current_bb.statements):
return SootAddressDescriptor(addr.method, addr.block_idx, new_stmt_idx)
else:
new_bb_idx = addr.block_idx + 1
if new_bb_idx < len(method.blocks):
return SootAddressDescriptor(addr.method, new_bb_idx, 0)
else:
l.warning("falling into a non existing bb: %d in %s",
new_bb_idx, SootMethodDescriptor.from_soot_method(method))
raise IncorrectLocationException()
def copy(self):
return SootAddressDescriptor(method=self.method,
block_idx=self.block_idx,
stmt_idx=self.stmt_idx)