Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
s = ""
block_addrs = list(set([ a for a, _ in self.slice.nodes() ]))
for block_addr in block_addrs:
block_str = " IRSB %#x\n" % block_addr
block = self.project.factory.block(block_addr, backup_state=self._base_state).vex
included_stmts = set([ stmt for _, stmt in self.slice.nodes() if _ == block_addr ])
default_exit_included = any(stmt == DEFAULT_STATEMENT for _, stmt in self.slice.nodes() if _ == block_addr)
for i, stmt in enumerate(block.statements):
if arch is not None:
if isinstance(stmt, pyvex.IRStmt.Put):
reg_name = arch.translate_register_name(stmt.offset)
stmt_str = stmt.__str__(reg_name=reg_name)
elif isinstance(stmt, pyvex.IRStmt.WrTmp) and isinstance(stmt.data, pyvex.IRExpr.Get):
reg_name = arch.translate_register_name(stmt.data.offset)
stmt_str = stmt.__str__(reg_name=reg_name)
else:
stmt_str = str(stmt)
else:
stmt_str = str(stmt)
block_str += "%02s %02d | %s\n" % ("+" if i in included_stmts else " ",
i,
stmt_str
)
block_str += " + " if default_exit_included else " "
# + 07 | t11 = 32Sto64(t12)
# + 10 | t2 = Add64(0x0000000000571df0,t11)
#
# all_addr_holders will be {(0x4c64c4, 11): (AddressTransferringTypes.SignedExtension, 32, 64,),
# (0x4c64c4, 12); (AddressTransferringTypes.Assignment,),
# }
all_addr_holders = OrderedDict()
while True:
preds = list(b.slice.predecessors(stmt_loc))
if len(preds) != 1:
break
block_addr, stmt_idx = stmt_loc = preds[0]
block = project.factory.block(block_addr, backup_state=self.base_state).vex
stmt = block.statements[stmt_idx]
if isinstance(stmt, (pyvex.IRStmt.WrTmp, pyvex.IRStmt.Put)):
if isinstance(stmt.data, (pyvex.IRExpr.Get, pyvex.IRExpr.RdTmp)):
# data transferring
stmts_to_remove.append(stmt_loc)
if isinstance(stmt, pyvex.IRStmt.WrTmp):
all_addr_holders[(stmt_loc[0], stmt.tmp)] = (AddressTransferringTypes.Assignment,)
continue
elif isinstance(stmt.data, pyvex.IRExpr.ITE):
# data transferring
# t16 = if (t43) ILGop_Ident32(LDle(t29)) else 0x0000c844
# > t44 = ITE(t43,t16,0x0000c844)
stmts_to_remove.append(stmt_loc)
if isinstance(stmt, pyvex.IRStmt.WrTmp):
all_addr_holders[(stmt_loc[0], stmt.tmp)] = (AddressTransferringTypes.Assignment,)
continue
elif isinstance(stmt.data, pyvex.IRExpr.Unop):
if stmt.data.op == 'Iop_32Sto64':
if cfg_node is None:
# not found
raise KeyError('CFGNode for instruction %#x is not found.' % self._insn_addr)
# determine the statement ID
vex_block = self._project.factory.block(cfg_node.addr,
size=cfg_node.size,
opt_level=self._cfg._iropt_level
).vex
stmt_idx = None
insn_addr = cfg_node.addr
for i, stmt in enumerate(vex_block.statements):
if isinstance(stmt, pyvex.IRStmt.IMark):
insn_addr = stmt.addr + stmt.delta
elif insn_addr == self._insn_addr:
if isinstance(stmt, pyvex.IRStmt.Put) and stmt.offset == reg_offset:
stmt_idx = i
break
elif insn_addr > self._insn_addr:
break
if stmt_idx is None:
raise KeyError('Cannot find the statement.')
# create a program variable
variable = SimRegisterVariable(reg_offset, size)
location = CodeLocation(cfg_node.addr, stmt_idx, ins_addr=self._insn_addr)
pv = ProgramVariable(variable, location, arch=self._project.arch)
return DDGViewItem(self._ddg, pv, simplified=self._simplified)
def resolve_stmt(stmt):
if type(stmt) is pyvex.IRStmt.WrTmp:
tmps[stmt.tmp] = resolve_expr(stmt.data)
elif type(stmt) is pyvex.IRStmt.Store:
state.store(resolve_expr(stmt.addr), resolve_expr(stmt.data))
elif type(stmt) is pyvex.IRStmt.Put:
state.put(stmt.offset, resolve_expr(stmt.data))
else:
raise CouldNotResolveException
and isinstance(arg1_src_stmt.data, pyvex.IRExpr.Load):
# Loading a constant/variable from memory (and later the value is stored in a register)
# Same as above, we will need to overwrite it when executing the slice to guarantee the full recovery
# of jump table targets.
#
# Here is an example:
# mov eax, [0x625a3c]
# cmp eax, 0x4
# ja 0x40899d (default)
# loc_408899:
# mov eax, eax
# mov rax, qword [rax*8+0x220741]
# jmp rax
#
self.state.stmts_to_instrument.append(('mem_read', ) + arg1_src)
elif isinstance(arg1_src_stmt, pyvex.IRStmt.Put):
# Storing a constant/variable in register
# Same as above...
#
# Here is an example:
# movzx eax, byte ptr [rax+12h]
# movzx eax, al
# cmp eax, 0xe
# ja 0x405b9f (default)
# loc_405b34:
# mov eax, eax
# mov rax, qword [rax*8+0x2231ae]
#
self.state.stmts_to_instrument.append(('reg_write', ) + arg1_src)
def resolve_stmt(stmt):
if type(stmt) is pyvex.IRStmt.WrTmp:
tmps[stmt.tmp] = resolve_expr(stmt.data)
elif self.track_mem and type(stmt) is pyvex.IRStmt.Store:
state.store(resolve_expr(stmt.addr), resolve_expr(stmt.data))
elif type(stmt) is pyvex.IRStmt.Put:
state.put(stmt.offset, resolve_expr(stmt.data))
else:
raise CouldNotResolveException
@staticmethod
def _find_source(statements, put_stmt_id):
'''
Execute the statements backwards and figure out where the value comes from
This is not a slicer. It only take care of a small portion of statement types.
:param statements:
:param put_stmt_id:
:return:
'''
temps = set()
src_stmt_ids = set()
if not isinstance(statements[put_stmt_id], pyvex.IRStmt.Put):
return None
if not isinstance(statements[put_stmt_id].data, pyvex.IRExpr.RdTmp):
return None
temps.add(statements[put_stmt_id].data.tmp)
for i in xrange(put_stmt_id, -1, -1):
stmt = statements[i]
if isinstance(stmt, pyvex.IRStmt.WrTmp):
data = None
if stmt.tmp in temps:
data = stmt.data
if isinstance(data, pyvex.IRExpr.RdTmp):
temps.add(data.tmp)
elif isinstance(data, pyvex.IRExpr.Get):
if self.arch.name in ('ARMEL', 'ARMHF'):
# hard code alignment for ARM code
instruction_alignment = 4
try:
while True:
tick()
bb = self._block(addr, skip_stmts=False)
step_forward = False
# the block shouldn't touch any cc_* registers
if self.arch.name in ('X86', 'AMD64', 'ARMEL', 'ARMHF', 'ARMCortexM'):
cc_regs = { self.arch.registers['cc_op'][0], self.arch.registers['cc_ndep'][0],
self.arch.registers['cc_dep1'][0], self.arch.registers['cc_dep2'][0]
}
if any([ isinstance(stmt, pyvex.IRStmt.Put) and stmt.offset in cc_regs
for stmt in bb.statements ]):
step_forward = True
elif any( [ isinstance(stmt, pyvex.IRStmt.WrTmp) and isinstance(stmt.data, pyvex.IRExpr.Get)
and stmt.data.offset in cc_regs for stmt in bb.statements ]):
step_forward = True
if step_forward:
# only steps one instruction forward
addr += instruction_alignment
continue
if block_is_good(bb):
break
if bb.jumpkind == 'Ijk_NoDecode':
addr += instruction_alignment
else:
:return:
"""
temps = set()
regs = set()
# Retrieve the target: are we slicing from a register(IRStmt.Put), or a temp(IRStmt.WrTmp)?
try:
stmts = self._get_irsb(self._dst_run).statements
except SimTranslationError:
return
if self._dst_stmt_idx != -1:
dst_stmt = stmts[self._dst_stmt_idx]
if type(dst_stmt) is pyvex.IRStmt.Put:
regs.add(dst_stmt.offset)
elif type(dst_stmt) is pyvex.IRStmt.WrTmp:
temps.add(dst_stmt.tmp)
else:
raise AngrBladeError('Incorrect type of the specified target statement. We only support Put and WrTmp.')
prev = (self._get_addr(self._dst_run), self._dst_stmt_idx)
else:
next_expr = self._get_irsb(self._dst_run).next
if type(next_expr) is pyvex.IRExpr.RdTmp:
temps.add(next_expr.tmp)
elif type(next_expr) is pyvex.IRExpr.Const:
# A const doesn't rely on anything else!
pass
def _post_process_ARM(self, block):
# Jumpkind
if block.jumpkind == "Ijk_Boring":
# If PC is moved to LR, then this should be an Ijk_Call
#
# Example:
# MOV LR, PC
# MOV PC, R8
stmts = block.statements
lr_store_id = None
inst_ctr = 1
for i, stmt in reversed(list(enumerate(stmts))):
if isinstance(stmt, pyvex.IRStmt.Put):
if stmt.offset == self.arch.registers['lr'][0]:
lr_store_id = i
break
if isinstance(stmt, pyvex.IRStmt.IMark):
inst_ctr += 1
if lr_store_id is not None and inst_ctr == 2:
block.jumpkind = "Ijk_Call"
return block