Skip to content

Commit

Permalink
Only look for readable address in retaddr command (#2143)
Browse files Browse the repository at this point in the history
* Only look for readable address in retaddr command

* Rename stack.py to retaddr.py

* Add pwndbg.gdblib.stack.callstack and use it in retaddr

* Add callstack gdb test

* Add QEMU callstack test
  • Loading branch information
gsingh93 committed May 6, 2024
1 parent d6408b9 commit 00adfbb
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 11 deletions.
2 changes: 1 addition & 1 deletion pwndbg/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,7 @@ def load_commands() -> None:
import pwndbg.commands.procinfo
import pwndbg.commands.radare2
import pwndbg.commands.reload
import pwndbg.commands.retaddr
import pwndbg.commands.rizin
import pwndbg.commands.rop
import pwndbg.commands.ropper
Expand All @@ -706,7 +707,6 @@ def load_commands() -> None:
import pwndbg.commands.sigreturn
import pwndbg.commands.slab
import pwndbg.commands.spray
import pwndbg.commands.stack
import pwndbg.commands.start
import pwndbg.commands.telescope
import pwndbg.commands.tips
Expand Down
13 changes: 3 additions & 10 deletions pwndbg/commands/stack.py → pwndbg/commands/retaddr.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from __future__ import annotations

import gdb

import pwndbg.chain
import pwndbg.commands
import pwndbg.gdblib.arch
Expand All @@ -15,17 +13,12 @@
)
@pwndbg.commands.OnlyWhenRunning
def retaddr() -> None:
addresses = pwndbg.gdblib.stack.callstack()

sp = pwndbg.gdblib.regs.sp
stack = pwndbg.gdblib.vmmap.find(sp)

# Enumerate all return addresses
frame = gdb.newest_frame()
addresses = []
while frame:
addresses.append(int(frame.pc()))
frame = frame.older()

# Find all of them on the stack
# Find all return addresses on the stack
start = stack.vaddr
stop = start + stack.memsz
while addresses and start < sp < stop:
Expand Down
17 changes: 17 additions & 0 deletions pwndbg/gdblib/stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

from __future__ import annotations

from typing import List

import gdb

import pwndbg.gdblib.abi
Expand Down Expand Up @@ -153,3 +155,18 @@ def _fetch_via_exploration() -> dict[int, pwndbg.lib.memory.Page]:
curr_thread.switch()

return stacks


def callstack() -> List[int]:
"""
Return the address of the return address for the current frame.
"""
frame = gdb.newest_frame()
addresses = []
while frame:
addr = int(frame.pc())
if pwndbg.gdblib.memory.is_readable_address(addr):
addresses.append(addr)
frame = frame.older()

return addresses
20 changes: 20 additions & 0 deletions tests/gdb-tests/tests/test_callstack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from __future__ import annotations

import gdb

import pwndbg.gdblib.memory
import pwndbg.gdblib.stack
import tests

REFERENCE_BINARY = tests.binaries.get("reference-binary.out")


def test_callstack_readable(start_binary):
start_binary(REFERENCE_BINARY)
gdb.execute("b break_here")
gdb.execute("r")

addresses = pwndbg.gdblib.stack.callstack()

assert len(addresses) > 0
assert all(pwndbg.gdblib.memory.is_readable_address(address) for address in addresses)
11 changes: 11 additions & 0 deletions tests/qemu-tests/tests/system/test_callstack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from __future__ import annotations

import pwndbg.gdblib.memory
import pwndbg.gdblib.stack


def test_callstack_readable():
addresses = pwndbg.gdblib.stack.callstack()

assert len(addresses) > 0
assert all(pwndbg.gdblib.memory.is_readable_address(address) for address in addresses)

0 comments on commit 00adfbb

Please sign in to comment.