You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pwndbg/gef/stack.py

91 lines
2.2 KiB
Python

import gdb
import gef.events
import gef.memory
import gef.memoize
# Dictionary of stack ranges.
# Key is the gdb thread ptid
# Value is a gef.memory.Page object
stacks = {}
# Whether the stack is protected by NX.
# This is updated automatically by is_executable.
nx = False
def find(address):
"""
Returns a gef.memory.Page object which corresponds to the
currently-loaded stack.
"""
for stack in stacks:
if address in stack:
return stack
@gef.events.stop
def update():
"""
For each running thread, updates the known address range
for its stack.
"""
curr_thread = gdb.selected_thread()
try:
for thread in gdb.selected_inferior().threads():
thread.switch()
sp = gef.regs.sp
# If we don't already know about this thread, create
# a new Page mapping for it.
page = stacks.get(thread.ptid, None)
if page is None:
start = gef.memory.find_lower_boundary(sp)
stop = gef.memory.find_upper_boundary(sp)
page = gef.memory.Page(start, stop-start, 6 if not is_executable() else 7, 0, '[stack]')
stacks[thread.ptid] = page
continue
# If we *DO* already know about this thread, just
# udpate the lower boundary.
low = gef.memory.find_lower_boundary(page.vaddr)
if low != page.vaddr:
page.memsz += (page.vaddr - low)
page.vaddr = low
finally:
curr_thread.switch()
@gef.memoize.reset_on_stop
def current():
"""
Returns the bounds for the stack for the current thread.
"""
return find(gef.regs.sp)
@gef.events.exit
def clear():
"""
Clears everything we know about any stack memory ranges.
Called when the target process exits.
"""
stacks.clear()
global nx
nx = False
@gef.events.stop
@gef.memoize.reset_on_exit
def is_executable():
global nx
nx = False
PT_GNU_STACK = 0x6474e551
ehdr = gef.elf.exe()
for phdr in gef.elf.iter_phdrs(ehdr):
p_type = int(phdr['p_type'])
if p_type == PT_GNU_STACK:
nx = True
return not nx