diff --git a/pwndbg/elf.py b/pwndbg/elf.py index a51908825..9c076c94d 100644 --- a/pwndbg/elf.py +++ b/pwndbg/elf.py @@ -228,57 +228,32 @@ def reset_ehdr_type_loaded(): ehdr_type_loaded = 0 -@pwndbg.abi.LinuxOnly() -def find_elf_magic(pointer, max_pages=1024, search_down=False, ret_addr_anyway=False): - """Search the nearest page which contains the ELF headers - by comparing the ELF magic with first 4 bytes. - - Parameter: - search_down: change the search direction - to search over the lower address. - That is, decreasing the page pointer instead of increasing. - (default: False) - Returns: - An integer address of ELF page base - None if not found within the page limit +def get_ehdr(pointer): """ - addr = pwndbg.memory.page_align(pointer) - step = pwndbg.memory.PAGE_SIZE - if search_down: - step = -step - - max_addr = pwndbg.arch.ptrmask - - for i in range(max_pages): - # Make sure address within valid range or gdb will raise Overflow exception - if addr < 0 or addr > max_addr: - return None - - try: - data = pwndbg.memory.read(addr, 4) - except gdb.MemoryError: - return addr if ret_addr_anyway else None + Returns an ehdr object for the ELF pointer points into. - # Return the address if found ELF header - if data == b'\x7FELF': - return addr - - addr += step + We expect the `pointer` to be an address from the binary. + """ + vmmap = pwndbg.vmmap.find(pointer) + base = None - return addr if ret_addr_anyway else None + # We first check if the begining of the page contains the ELF magic + if pwndbg.memory.read(vmmap.start, 4) == 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.vmmap.get(): + if v.objfile == vmmap.objfile: + vmmap = v + break -def get_ehdr(pointer): - """Returns an ehdr object for the ELF pointer points into. - """ - # Align down to a page boundary, and scan until we find - # the ELF header. - base = pwndbg.memory.page_align(pointer) + if pwndbg.memory.read(vmmap.start, 4) == b'\x7fELF': + base = vmmap.start - # For non linux ABI, the ELF header may not be found in memory. - # This will hang the gdb when using the remote gdbserver to scan 1024 pages - base = find_elf_magic(pointer, search_down=True) if base is None: + # For non linux ABI, the ELF header may not exist at all if pwndbg.abi.linux: print("ERROR: Could not find ELF base!") return None, None @@ -287,7 +262,7 @@ def get_ehdr(pointer): ei_class = pwndbg.memory.byte(base+4) # Find out where the section headers start - Elfhdr = read(Ehdr, base) + Elfhdr = read(Ehdr, base) return ei_class, Elfhdr diff --git a/pwndbg/memory.py b/pwndbg/memory.py index 3bb5ea5f4..f2dfa88cc 100644 --- a/pwndbg/memory.py +++ b/pwndbg/memory.py @@ -333,8 +333,12 @@ def find_upper_boundary(addr, max_pages=1024): # import sys # sys.stdout.write(hex(addr) + '\n') addr += pwndbg.memory.PAGE_SIZE + + # Sanity check in case a custom GDB server/stub + # incorrectly returns a result from read + # (this is most likely redundant, but its ok to keep it?) if addr > pwndbg.arch.ptrmask: - break + return pwndbg.arch.ptrmask except gdb.MemoryError: pass return addr @@ -352,8 +356,11 @@ def find_lower_boundary(addr, max_pages=1024): for i in range(max_pages): pwndbg.memory.read(addr, 1) addr -= pwndbg.memory.PAGE_SIZE + + # Sanity check (see comment in find_upper_boundary) if addr < 0: - break + return 0 + except gdb.MemoryError: addr += pwndbg.memory.PAGE_SIZE return addr diff --git a/pwndbg/stack.py b/pwndbg/stack.py index 1c77f622f..f26dc2a90 100644 --- a/pwndbg/stack.py +++ b/pwndbg/stack.py @@ -38,18 +38,15 @@ def find(address): return stack -def find_upper_stack_boundary(addr, max_pages=1024): - addr = pwndbg.memory.page_align(int(addr)) +def find_upper_stack_boundary(stack_ptr, max_pages=1024): + stack_ptr = pwndbg.memory.page_align(int(stack_ptr)) # We can't get the stack size from stack layout and page fault on bare metal mode, # so we return current page as a walkaround. if not pwndbg.abi.linux: - return addr + pwndbg.memory.PAGE_SIZE + return stack_ptr + pwndbg.memory.PAGE_SIZE - # We don't want to find ELF magic here. We reuse the find_elf_magic func - # as it traverses 4kB pages and can find the boundary for us - # (in other words, we expect the ELF magic to not be present on the stack) - return pwndbg.elf.find_elf_magic(addr, max_pages=max_pages, ret_addr_anyway=True) + return pwndbg.memory.find_upper_boundary(stack_ptr, max_pages) @pwndbg.events.stop