Source code for angr.analyses.cfg.indirect_jump_resolvers.amd64_elf_got

import logging

from capstone.x86_const import X86_REG_RIP

from pyvex.stmt import IMark

from .resolver import IndirectJumpResolver

l = logging.getLogger(name=__name__)


[docs]class AMD64ElfGotResolver(IndirectJumpResolver): """ A timeless indirect jump resolver that resolves GOT entries on AMD64 ELF binaries. """
[docs] def __init__(self, project): super().__init__(project, timeless=True)
[docs] def filter(self, cfg, addr, func_addr, block, jumpkind): if jumpkind != "Ijk_Call": return False return True
[docs] def resolve( # pylint:disable=unused-argument self, cfg, addr, func_addr, block, jumpkind, func_graph_complete: bool = True, **kwargs ): # Find the address and size of the last instruction last_insn_addr = None last_insn_size = None for stmt in reversed(block.statements): if isinstance(stmt, IMark): last_insn_addr = stmt.addr last_insn_size = stmt.len break if last_insn_addr is None: # Cannot find the last instruction return False, [] # lift one instruction insn = self.project.factory.block(last_insn_addr, size=last_insn_size).capstone.insns[-1] opnd = insn.insn.operands[0] # Must be of the form: call [rip + 0xABCD] if not (opnd.mem and opnd.mem.disp and opnd.mem.base == X86_REG_RIP and not opnd.mem.index): return False, [] disp = insn.insn.disp slot = disp + insn.address + insn.size target = cfg._fast_memory_load_pointer(slot) if target is None: l.warning("Address %# is not mapped.", slot) return False, [] if not self.project.is_hooked(target): return False, [] dest = self.project.hooked_by(target) l.debug("Resolved target to %s", dest.display_name) return True, [target]