diff --git a/pwndbg/commands/__init__.py b/pwndbg/commands/__init__.py index 421d4a76a..80ca3a352 100644 --- a/pwndbg/commands/__init__.py +++ b/pwndbg/commands/__init__.py @@ -706,7 +706,7 @@ def load_commands() -> None: if pwndbg.dbg.is_gdblib_available(): import pwndbg.commands.ai import pwndbg.commands.attachp - import pwndbg.commands.binja + import pwndbg.commands.binja_functions import pwndbg.commands.branch import pwndbg.commands.cymbol import pwndbg.commands.got @@ -728,6 +728,7 @@ def load_commands() -> None: import pwndbg.commands.asm import pwndbg.commands.auxv import pwndbg.commands.binder + import pwndbg.commands.binja import pwndbg.commands.canary import pwndbg.commands.checksec import pwndbg.commands.comments diff --git a/pwndbg/commands/binja.py b/pwndbg/commands/binja.py index 348e4a59d..e2b60fc83 100644 --- a/pwndbg/commands/binja.py +++ b/pwndbg/commands/binja.py @@ -1,15 +1,8 @@ from __future__ import annotations -from typing import Tuple - -import gdb - -import pwndbg.aglib.proc import pwndbg.aglib.regs import pwndbg.commands -import pwndbg.gdblib.functions import pwndbg.integration.binja -from pwndbg.color import message from pwndbg.commands import CommandCategory @@ -25,49 +18,3 @@ def bn_sync(*args) -> None: Synchronize Binary Ninja's cursor with GDB """ pwndbg.integration.binja.navigate_to(pwndbg.aglib.regs.pc) - - -@pwndbg.gdblib.functions.GdbFunction() -@pwndbg.integration.binja.with_bn() -def bn_sym(name_val: gdb.Value) -> int | None: - """Lookup a symbol's address by name from Binary Ninja.""" - name = name_val.string() - addr: int | None = pwndbg.integration.binja._bn.get_symbol_addr(name) - if addr is None: - return None - return pwndbg.integration.binja.r2l(addr) - - -@pwndbg.gdblib.functions.GdbFunction() -@pwndbg.integration.binja.with_bn() -def bn_var(name_val: gdb.Value) -> int | None: - """Lookup a stack variable's address by name from Binary Ninja.""" - name = name_val.string() - conf_and_offset: Tuple[int, int] | None = pwndbg.integration.binja._bn.get_var_offset_from_sp( - pwndbg.integration.binja.l2r(pwndbg.aglib.regs.pc), name - ) - if conf_and_offset is None: - return None - (conf, offset) = conf_and_offset - if conf < 64: - print(message.warn(f"Warning: Stack offset only has {conf / 255 * 100:.2f}% confidence")) - return pwndbg.aglib.regs.sp + offset - - -@pwndbg.gdblib.functions.GdbFunction() -@pwndbg.integration.binja.with_bn() -def bn_eval(expr: gdb.Value) -> int | None: - """Parse and evaluate a Binary Ninja expression. - - Docs: https://api.binary.ninja/binaryninja.binaryview-module.html#binaryninja.binaryview.BinaryView.parse_expression - - Adds all registers in the current register set as magic variables (e.g. $rip). - Also adds a $piebase magic variable with the computed executable base.""" - magic_vars = {} - for r in pwndbg.aglib.regs.current: - v = pwndbg.aglib.regs[r] - if v is not None: - magic_vars[r] = v - magic_vars["piebase"] = pwndbg.aglib.proc.binary_base_addr - ret: int | None = pwndbg.integration.binja._bn.parse_expr(expr.string(), magic_vars) - return ret diff --git a/pwndbg/commands/binja_functions.py b/pwndbg/commands/binja_functions.py new file mode 100644 index 000000000..c459aa6ab --- /dev/null +++ b/pwndbg/commands/binja_functions.py @@ -0,0 +1,58 @@ +from __future__ import annotations + +from typing import Tuple + +import gdb + +import pwndbg.aglib.proc +import pwndbg.aglib.regs +import pwndbg.commands +import pwndbg.gdblib.functions +import pwndbg.integration.binja +from pwndbg.color import message + + +@pwndbg.gdblib.functions.GdbFunction() +@pwndbg.integration.binja.with_bn() +def bn_sym(name_val: gdb.Value) -> int | None: + """Lookup a symbol's address by name from Binary Ninja.""" + name = name_val.string() + addr: int | None = pwndbg.integration.binja._bn.get_symbol_addr(name) + if addr is None: + return None + return pwndbg.integration.binja.r2l(addr) + + +@pwndbg.gdblib.functions.GdbFunction() +@pwndbg.integration.binja.with_bn() +def bn_var(name_val: gdb.Value) -> int | None: + """Lookup a stack variable's address by name from Binary Ninja.""" + name = name_val.string() + conf_and_offset: Tuple[int, int] | None = pwndbg.integration.binja._bn.get_var_offset_from_sp( + pwndbg.integration.binja.l2r(pwndbg.aglib.regs.pc), name + ) + if conf_and_offset is None: + return None + (conf, offset) = conf_and_offset + if conf < 64: + print(message.warn(f"Warning: Stack offset only has {conf / 255 * 100:.2f}% confidence")) + return pwndbg.aglib.regs.sp + offset + + +@pwndbg.gdblib.functions.GdbFunction() +@pwndbg.integration.binja.with_bn() +def bn_eval(expr: gdb.Value) -> int | None: + """Parse and evaluate a Binary Ninja expression. + + Docs: https://api.binary.ninja/binaryninja.binaryview-module.html#binaryninja.binaryview.BinaryView.parse_expression + + Adds all registers in the current register set as magic variables (e.g. $rip). + Also adds a $piebase magic variable with the computed executable base.""" + magic_vars = {} + for r in pwndbg.aglib.regs.current: + v = pwndbg.aglib.regs[r] + if v is not None: + magic_vars[r] = v + magic_vars["piebase"] = pwndbg.aglib.proc.binary_base_addr + ret: int | None = pwndbg.integration.binja._bn.parse_expr(expr.string(), magic_vars) + return ret diff --git a/pwndbg/commands/integration.py b/pwndbg/commands/integration.py index 9c38651b0..fbc037df5 100644 --- a/pwndbg/commands/integration.py +++ b/pwndbg/commands/integration.py @@ -4,12 +4,7 @@ import argparse import pwndbg.aglib.regs import pwndbg.commands -import pwndbg.dbg import pwndbg.integration - -if pwndbg.dbg.is_gdblib_available(): - import pwndbg.integration.binja - from pwndbg.commands import CommandCategory parser = argparse.ArgumentParser( diff --git a/pwndbg/integration/binja.py b/pwndbg/integration/binja.py index 13e8f8076..a8f0b5187 100644 --- a/pwndbg/integration/binja.py +++ b/pwndbg/integration/binja.py @@ -20,7 +20,6 @@ from typing import List from typing import Tuple from typing import TypeVar -import gdb import pygments import pygments.formatters import pygments.style @@ -43,7 +42,9 @@ from pwndbg.aglib.nearpc import c as nearpc_color from pwndbg.aglib.nearpc import ljust_padding from pwndbg.color import message from pwndbg.color import theme +from pwndbg.dbg import BreakpointLocation from pwndbg.dbg import EventType +from pwndbg.dbg import StopPoint from pwndbg.lib.functions import Argument from pwndbg.lib.functions import Function @@ -219,7 +220,7 @@ def auto_update_pc() -> None: _bn.update_pc_tag(l2r(pc)) -_managed_bps: Dict[int, gdb.Breakpoint] = {} +_managed_bps: Dict[int, StopPoint] = {} @pwndbg.dbg.event_handler(EventType.START) @@ -232,9 +233,12 @@ def auto_update_bp() -> None: bps: List[int] = _bn.get_bp_tags() binja_bps = {r2l(addr) for addr in bps} for k in _managed_bps.keys() - binja_bps: - _managed_bps.pop(k).delete() + bp = _managed_bps.pop(k) + bp.remove() + + inf = pwndbg.dbg.selected_inferior() for k in binja_bps - _managed_bps.keys(): - bp = gdb.Breakpoint("*" + hex(k)) + bp = inf.break_at(BreakpointLocation(k)) _managed_bps[k] = bp @@ -527,7 +531,7 @@ class BinjaProvider(pwndbg.integration.IntegrationProvider): newest = True # try to find the oldest frame that's earlier than the address while True: - upper = gdb_frame_to_dbg(dbg_frame_to_gdb(cur).older()) + upper = cur.parent() if upper is None: break @@ -556,21 +560,3 @@ class BinjaProvider(pwndbg.integration.IntegrationProvider): return f"{var}{suffix}" else: return f"{func}:{var}{suffix}" - - -def dbg_frame_to_gdb(d: pwndbg.dbg_mod.Frame) -> gdb.Frame: - # TODO: fix later to aglib - from pwndbg.dbg.gdb import GDBFrame - - assert isinstance(d, GDBFrame) - return d.inner - - -def gdb_frame_to_dbg(d: gdb.Frame | None) -> pwndbg.dbg_mod.Frame | None: - # TODO: fix later to aglib - from pwndbg.dbg.gdb import GDBFrame - - if d is None: - return None - - return GDBFrame(d)