Enhance remote QEMU targets debugging experience (#603)

* Enhance remote QEMU targets debugging experience

- improve vmmap command help and inform user that the result might not
be accurate for QEMU targets
- updating stack pages (`pwndbg.stack.stacks`): skip detecting stack pages if SP is 0 (this lead to displaying memory page that started at -0x1000)
- `pwndbg.vmmap.find` - don't skip addresses below `pwndbg.memory.MMAP_MIN_ADDR` -
this function is used by `pwndbg.color.memory.get` which is used by
`vmmap` command - because we skipped addresses - a memory page starting
below that address wasn't colored on `vmmap` display
- memory pages found with exploration will now display with `<explored>` name in `vmmap`
- skip `proc_pid_maps` for QEMU kernel targets too (this was bug-prone
as QEMU targets have 42000 pid returned by GDB and we potentially tried adding
memory pages from another process, which luckily usually wasn't there)

* Update pwndbg/vmmap.py
pull/606/head
Disconnect3d 7 years ago committed by GitHub
parent 0f4e31e72a
commit 09e1b37c8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -39,7 +39,12 @@ def pages_filter(s):
parser = argparse.ArgumentParser()
parser.description = 'Print virtual memory map pages. Results can be filtered by providing address/module name.'
parser.description = '''Print virtual memory map pages. Results can be filtered by providing address/module name.
Please note that memory pages on QEMU targets are detected through AUXV (sometimes with finding AUXV on the stack first)
or by exploring values e.g. from registers.
Memory pages can also be added manually, see vmmap_add, vmmap_clear and vmmap_load commands.'''
parser.add_argument('pages_filter', type=pages_filter, nargs='?', default=None,
help='Address or module name.')
@ -57,6 +62,9 @@ def vmmap(pages_filter=None):
for page in pages:
print(M.get(page.vaddr, text=str(page)))
if pwndbg.qemu.is_qemu():
print("\n[QEMU target detected - vmmap result might not be accurate; see `help vmmap`]")
parser = argparse.ArgumentParser()
parser.description = 'Add Print virtual memory map page.'

@ -22,6 +22,10 @@ def is_qemu():
if not pwndbg.remote.is_remote():
return False
# Example:
# pwndbg> maintenance packet Qqemu.sstepbits
# sending: "Qqemu.sstepbits"
# received: "ENABLE=1,NOIRQ=2,NOTIMER=4"
response = gdb.execute('maintenance packet Qqemu.sstepbits',
to_string=True,
from_tty=False)

@ -66,7 +66,9 @@ def update():
thread.switch()
sp = pwndbg.regs.sp
if sp is None:
# Skip if sp is None or 0
# (it might be 0 if we debug a qemu kernel)
if not sp:
continue
sp_low = sp & ~(0xfff)

@ -62,11 +62,10 @@ def get():
@pwndbg.memoize.reset_on_stop
def find(address):
if address is None or address < pwndbg.memory.MMAP_MIN_ADDR:
if address is None:
return None
if address:
address = int(address)
address = int(address)
for page in get():
if address in page:
@ -103,6 +102,7 @@ def explore(address_maybe):
flags |= 1 if not pwndbg.stack.nx else 0
page = find_boundaries(address_maybe)
page.objfile = '<explored>'
page.flags = flags
explored_pages.append(page)
@ -150,7 +150,9 @@ def proc_pid_maps():
A list of pwndbg.memory.Page objects.
"""
if pwndbg.qemu.is_qemu_usermode():
# If we debug remotely a qemu-user or qemu-system target,
# there is no point of hitting things further
if pwndbg.qemu.is_qemu():
return tuple()
example_proc_pid_maps = """

Loading…
Cancel
Save