Port emulator to aglib api (#2547)

* emu/emulator.py: port to aglib

* emu/emulator.py: fix darwin and setting pwndbg.config
pull/2554/head
patryk4815 1 year ago committed by GitHub
parent 8955a1170a
commit 30f7ea08dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -7,11 +7,11 @@ from __future__ import annotations
import collections
import re
from typing import Any
import sys
from typing import DefaultDict
from typing import List
from typing import Set
from typing import Tuple
from typing import Union
import capstone
from capstone import * # noqa: F403
@ -20,6 +20,7 @@ import pwndbg
import pwndbg.aglib.arch
import pwndbg.aglib.disasm.arch
import pwndbg.aglib.memory
import pwndbg.emu.emulator
import pwndbg.lib.cache
from pwndbg.aglib.disasm.arch import DEBUG_ENHANCEMENT
from pwndbg.aglib.disasm.instruction import ALL_JUMP_GROUPS
@ -29,16 +30,9 @@ from pwndbg.aglib.disasm.instruction import make_simple_instruction
from pwndbg.color import message
from pwndbg.dbg import EventType
# Emulation hasn't been ported yet.
if pwndbg.dbg.is_gdblib_available():
import gdb
try:
import pwndbg.emu.emulator
except Exception:
pwndbg.emu = None
else:
pwndbg.emu = None
CapstoneArch = {
"arm": CS_ARCH_ARM,
@ -308,8 +302,16 @@ def can_run_first_emulate() -> bool:
try:
from mmap import mmap, MAP_ANON, MAP_PRIVATE, PROT_EXEC, PROT_READ, PROT_WRITE # isort:skip
access_mode = PROT_WRITE | PROT_READ | PROT_EXEC
if sys.platform == "darwin":
# On macOS (Darwin), creating mmap with 'rwx' permissions is blocked
# by System Integrity Protection (SIP), which prevents execution of code
# from writable and readable memory regions. Therefore, we restrict
# the access mode to 'rw' (read and write only).
access_mode = PROT_WRITE | PROT_READ
mm = mmap( # novm
-1, 1024 * 1024 * 1024, MAP_PRIVATE | MAP_ANON, PROT_WRITE | PROT_READ | PROT_EXEC
-1, 1024 * 1024 * 1024, MAP_PRIVATE | MAP_ANON, access_mode
)
mm.close()
except OSError:
@ -322,7 +324,7 @@ def can_run_first_emulate() -> bool:
"Either free your memory or explicitly set `set emulate off` in your Pwndbg config"
)
)
gdb.execute("set emulate off", to_string=True)
pwndbg.config.emulate.value = "off"
return False
return True
@ -385,9 +387,8 @@ def near(
if address == pc and emulate and (not first_time_emulate or can_run_first_emulate()):
try:
emu = pwndbg.emu.emulator.Emulator()
except gdb.error as e:
message = str(e)
match = re.search(r"Memory at address (\w+) unavailable\.", message)
except pwndbg.dbg_mod.Error as e:
match = re.search(r"Memory at address (\w+) unavailable\.", str(e))
if match:
return ([], -1)
else:

@ -13,26 +13,29 @@ from typing import NamedTuple
from typing import Tuple
import capstone as C
import gdb
import unicorn as U
import unicorn.riscv_const
import pwndbg.aglib.arch
import pwndbg.aglib.disasm
import pwndbg.aglib.memory
import pwndbg.aglib.regs
import pwndbg.aglib.strings
import pwndbg.aglib.vmmap
import pwndbg.chain
import pwndbg.color.enhance as E
import pwndbg.color.memory as M
import pwndbg.dbg
import pwndbg.enhance
import pwndbg.gdblib.memory
import pwndbg.gdblib.regs
import pwndbg.gdblib.strings
import pwndbg.gdblib.symbol
import pwndbg.gdblib.vmmap
import pwndbg.integration
import pwndbg.lib.memory
import pwndbg.lib.regs
from pwndbg import color
from pwndbg.color.syntax_highlight import syntax_highlight
if pwndbg.dbg.is_gdblib_available():
import gdb
def parse_consts(u_consts) -> Dict[str, int]:
"""
@ -219,7 +222,7 @@ class Emulator:
debug(DEBUG_INIT, "uc = U.Uc(%r, %r)", (arch_to_UC[self.arch], self.uc_mode))
self.uc = U.Uc(arch_to_UC[self.arch], self.uc_mode)
self.regs: pwndbg.lib.regs.RegisterSet = pwndbg.gdblib.regs.current
self.regs: pwndbg.lib.regs.RegisterSet = pwndbg.aglib.regs.current
# Whether the emulator is allowed to emulate instructions
# There are cases when the emulator is incorrect or we want to disable it for certain instruction types,
@ -248,7 +251,7 @@ class Emulator:
if reg in blacklisted_regs:
debug(DEBUG_INIT, "Skipping blacklisted register %r", reg)
continue
value = getattr(pwndbg.gdblib.regs, reg)
value = getattr(pwndbg.aglib.regs, reg)
if None in (enum, value):
if reg not in blacklisted_regs:
debug(DEBUG_INIT, "# Could not set register %r", reg)
@ -269,7 +272,7 @@ class Emulator:
self.hook_add(U.UC_HOOK_INTR, self.hook_intr)
# Map in the page that $pc is on
self.map_page(pwndbg.gdblib.regs.pc)
self.map_page(pwndbg.aglib.regs.pc)
# Instruction tracing
if DEBUG & DEBUG_TRACE:
@ -291,7 +294,7 @@ class Emulator:
# Read size worth of memory, return None on error
def read_memory(self, address: int, size: int) -> bytes | None:
# Don't attempt if the address is not mapped on the host process
if not pwndbg.gdblib.vmmap.find(address):
if not pwndbg.aglib.vmmap.find(address):
return None
value = None
@ -371,7 +374,7 @@ class Emulator:
# Colorize the chain
rest = []
for link in chain:
symbol = pwndbg.gdblib.symbol.get(link) or None
symbol = pwndbg.dbg.selected_inferior().symbol_name_at_address(link) or None
if symbol:
symbol = f"{link:#x} ({symbol})"
rest.append(M.get(link, symbol))
@ -405,9 +408,9 @@ class Emulator:
# Near identical to pwndbg.enhance.enhance, just read from emulator memory
# Determine if its on a page - we do this in the real processes memory
page = pwndbg.gdblib.vmmap.find(value)
page = pwndbg.aglib.vmmap.find(value)
can_read = True
if not page or None is pwndbg.gdblib.memory.peek(value):
if not page or None is pwndbg.aglib.memory.peek(value):
can_read = False
if not can_read:
@ -433,7 +436,7 @@ class Emulator:
if pwndbg.config.syntax_highlight:
instr = syntax_highlight(instr)
# szval = pwndbg.gdblib.strings.get(value) or None
# szval = pwndbg.aglib.strings.get(value) or None
# Read from emulator memory
szval = self.memory_read_string(value, max_string_len=enhance_string_len, max_read=None)
szval0 = szval
@ -445,7 +448,7 @@ class Emulator:
return E.integer(pwndbg.enhance.int_str(value))
# Read from emulator memory
# intval = int(pwndbg.gdblib.memory.get_typed_pointer_value(pwndbg.gdblib.typeinfo.pvoid, value))
# intval = int(pwndbg.aglib.memory.get_typed_pointer_value(pwndbg.aglib.typeinfo.pvoid, value))
read_value = self.read_memory(value, pwndbg.aglib.arch.ptrsize)
if read_value is not None:
# intval = pwndbg.aglib.arch.unpack(read_value)
@ -507,10 +510,10 @@ class Emulator:
# Return None if cannot find str
def memory_read_string(self, address: int, max_string_len=None, max_read=None) -> str | None:
if max_string_len is None:
max_string_len = pwndbg.gdblib.strings.length
max_string_len = pwndbg.aglib.strings.length
if max_read is None:
max_read = pwndbg.gdblib.strings.length
max_read = pwndbg.aglib.strings.length
# Read string
sz = self.read_memory(address, max_read)
@ -542,7 +545,7 @@ class Emulator:
def update_pc(self, pc=None) -> None:
if pc is None:
pc = pwndbg.gdblib.regs.pc
pc = pwndbg.aglib.regs.pc
self.uc.reg_write(self.get_reg_enum(self.regs.pc), pc)
def read_thumb_bit(self) -> int:
@ -554,7 +557,7 @@ class Emulator:
Return None if the Thumb bit is not relevent to the current architecture
Mimics the `read_thumb_bit` function defined in gdblib/arch.py
Mimics the `read_thumb_bit` function defined in aglib/arch.py
"""
if self.arch == "arm":
if (cpsr := self.cpsr) is not None:
@ -574,16 +577,19 @@ class Emulator:
if arch == "armcm":
mode |= (
(U.UC_MODE_MCLASS | U.UC_MODE_THUMB)
if (pwndbg.gdblib.regs.xpsr & (1 << 24))
if (pwndbg.aglib.regs.xpsr & (1 << 24))
else U.UC_MODE_MCLASS
)
elif arch in ("arm", "aarch64"):
mode |= U.UC_MODE_THUMB if (pwndbg.gdblib.regs.cpsr & (1 << 5)) else U.UC_MODE_ARM
mode |= U.UC_MODE_THUMB if (pwndbg.aglib.regs.cpsr & (1 << 5)) else U.UC_MODE_ARM
elif arch == "mips" and "isa32r6" in gdb.newest_frame().architecture().name():
elif (
arch == "mips"
and pwndbg.dbg.is_gdblib_available()
and "isa32r6" in gdb.newest_frame().architecture().name()
):
mode |= U.UC_MODE_MIPS32R6
else:
mode |= {4: U.UC_MODE_32, 8: U.UC_MODE_64}[pwndbg.aglib.arch.ptrsize]
@ -601,9 +607,9 @@ class Emulator:
debug(DEBUG_MEM_MAP, "# Mapping %#x-%#x", (page, page + size))
try:
data = pwndbg.gdblib.memory.read(page, size)
data = pwndbg.aglib.memory.read(page, size)
data = bytes(data)
except gdb.MemoryError:
except pwndbg.dbg_mod.Error:
debug(DEBUG_MEM_MAP, "Could not map page %#x during emulation! [exception]", page)
return False

Loading…
Cancel
Save