From 3bc91c1cb20a25f43e993b89b8bc0744879b81b9 Mon Sep 17 00:00:00 2001 From: peace-maker Date: Thu, 11 May 2023 18:35:17 +0200 Subject: [PATCH] Add heuristic to add executable base in qemu-user (#1695) vmmap would try to add the executable to memory pages if the `info auxv` command contained an address, but the memory maps would be accessed recursively when trying to lookup the start of the ELF based on the given address. Since qemu doesn't provide memory map info, do a leap of faith and try if the start of the page of the given address contains the ELF magic header. Since the program headers are more likely to be on the same page as the ELF header than the program entrypoint, try both. --- pwndbg/gdblib/elf.py | 46 ++++++++++++++++++++++++------------------ pwndbg/gdblib/vmmap.py | 8 +++++++- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/pwndbg/gdblib/elf.py b/pwndbg/gdblib/elf.py index c6f8f2a2b..d0efb14bd 100644 --- a/pwndbg/gdblib/elf.py +++ b/pwndbg/gdblib/elf.py @@ -273,33 +273,39 @@ def get_ehdr(pointer): We expect the `pointer` to be an address from the binary. """ - # This just does not work :( - if pwndbg.gdblib.qemu.is_qemu(): - return None, None - - vmmap = pwndbg.gdblib.vmmap.find(pointer) base = None - # If there is no vmmap for the requested address, we can't do much - # (e.g. it could have been unmapped for whatever reason) - if vmmap is None: - return None, None - - # We first check if the beginning of the page contains the ELF magic - if pwndbg.gdblib.memory.read(vmmap.start, 4, partial=True) == b"\x7fELF": - base = vmmap.start - - # The page did not have ELF magic; it may be that .text and binary start are split - # into two pages, so let's get the first page from the pointer's page objfile + if pwndbg.gdblib.qemu.is_qemu(): + # Only check if the beginning of the page contains the ELF magic, + # since we cannot get the memory map in qemu-user. + page_start = pwndbg.lib.memory.page_align(pointer) + if pwndbg.gdblib.memory.read(page_start, 4, partial=True) == b"\x7fELF": + base = page_start + else: + return None, None else: - for v in pwndbg.gdblib.vmmap.get(): - if v.objfile == vmmap.objfile: - vmmap = v - break + vmmap = pwndbg.gdblib.vmmap.find(pointer) + + # If there is no vmmap for the requested address, we can't do much + # (e.g. it could have been unmapped for whatever reason) + if vmmap is None: + return None, None + # We first check if the beginning of the page contains the ELF magic if pwndbg.gdblib.memory.read(vmmap.start, 4, partial=True) == b"\x7fELF": base = vmmap.start + # The page did not have ELF magic; it may be that .text and binary start are split + # into two pages, so let's get the first page from the pointer's page objfile + else: + for v in pwndbg.gdblib.vmmap.get(): + if v.objfile == vmmap.objfile: + vmmap = v + break + + if pwndbg.gdblib.memory.read(vmmap.start, 4, partial=True) == b"\x7fELF": + base = vmmap.start + if base is None: # For non linux ABI, the ELF header may not exist at all if pwndbg.gdblib.abi.linux: diff --git a/pwndbg/gdblib/vmmap.py b/pwndbg/gdblib/vmmap.py index c7cf9f1dd..c43464ab0 100644 --- a/pwndbg/gdblib/vmmap.py +++ b/pwndbg/gdblib/vmmap.py @@ -675,7 +675,13 @@ def info_auxv(skip_exe=False): phdr = auxv.AT_PHDR if not skip_exe and (entry or phdr): - pages.extend(pwndbg.gdblib.elf.map(entry or phdr, exe_name)) + for addr in [entry, phdr]: + if not addr: + continue + new_pages = pwndbg.gdblib.elf.map(addr, exe_name) + if new_pages: + pages.extend(new_pages) + break if base: pages.extend(pwndbg.gdblib.elf.map(base, "[linker]"))