Support bare metal environment (#369)

* Add elf.find_elf_magic() and remove duplicate code

* Add pwndbg.abi.LinuxOnly decorator

* Support bare metal environment

Use @pwndbg.abi.LinuxOnly and pwndbg.abi.linux to disable
several util functions which search the memory to find
the AUXV, the ELF header, or the page bound.
pull/372/head
Meng-Huan Yu 8 years ago committed by Disconnect3d
parent 8a5a6da0a3
commit 31f468e0d1

@ -4,6 +4,11 @@ from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import functools
import re
import gdb
import pwndbg.arch
@ -111,3 +116,37 @@ linux_arm_sigreturn = SigreturnABI(['r7'], 4, 0)
linux_i386_srop = ABI(['eax'], 4, 0)
linux_amd64_srop = ABI(['rax'], 4, 0)
linux_arm_srop = ABI(['r7'], 4, 0)
@pwndbg.events.start
def update():
global abi
global linux
# Detect current ABI of client side by 'show osabi'
osabi_string = gdb.execute('show osabi', to_string=True)
# The return string will be:
# The current OS ABI is "auto" (currently "GNU/Linux").
match = re.search('currently "([^"]+)"', osabi_string)
if match:
# 'GNU/Linux': linux
# 'none': bare metal
abi = match.group(1)
linux = 'Linux' in abi
def LinuxOnly(default=None):
"""Create a decorator that the function will be called when ABI is Linux.
Otherwise, return `default`.
"""
def decorator(func):
@functools.wraps(func)
def caller(*args, **kwargs):
if linux:
return func(*args, **kwargs)
else:
return default
return caller
return decorator

@ -7,6 +7,7 @@ from __future__ import unicode_literals
import gdb
import pwndbg.abi
import pwndbg.arch
import pwndbg.events
import pwndbg.memory
@ -25,6 +26,7 @@ envp = None
envc = None
@pwndbg.events.start
@pwndbg.abi.LinuxOnly()
def update():
global argc
global argv

@ -11,6 +11,7 @@ import sys
import gdb
import pwndbg.abi
import pwndbg.arch
import pwndbg.events
import pwndbg.info
@ -150,6 +151,8 @@ def find_stack_boundary(addr):
return addr
def walk_stack():
if not pwndbg.abi.linux:
return None
if pwndbg.qemu.is_qemu_kernel():
return None

@ -18,6 +18,8 @@ import sys
import gdb
from six.moves import reload_module
import pwndbg.abi
import pwndbg.arch
import pwndbg.auxv
import pwndbg.elftypes
import pwndbg.events
@ -120,6 +122,45 @@ def reset_ehdr_type_loaded():
global ehdr_type_loaded
ehdr_type_loaded = 0
@pwndbg.abi.LinuxOnly()
def find_elf_magic(pointer, max_pages=1024, search_down=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
"""
base = 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 base < 0 or base > max_addr:
return None
try:
data = pwndbg.memory.read(base, 4)
except gdb.MemoryError:
return None
# Return the address if found ELF header
if data == b'\x7FELF':
return base
base += step
return None
def get_ehdr(pointer):
"""Returns an ehdr object for the ELF pointer points into.
"""
@ -127,21 +168,14 @@ def get_ehdr(pointer):
# the ELF header.
base = pwndbg.memory.page_align(pointer)
try:
data = pwndbg.memory.read(base, 4)
# Do not search more than 4MB of memory
for i in range(1024):
if data == b'\x7FELF':
break
base -= pwndbg.memory.PAGE_SIZE
data = pwndbg.memory.read(base, 4)
# XXX: 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
if not pwndbg.abi.linux:
return None, None
else:
print("ERROR: Could not find ELF base!")
return None, None
except gdb.MemoryError:
base = find_elf_magic(pointer, search_down=True)
if base is None:
print("ERROR: Could not find ELF base!")
return None, None
# Determine whether it's 32- or 64-bit

@ -14,6 +14,7 @@ from __future__ import unicode_literals
import gdb
import pwndbg.elf
import pwndbg.events
import pwndbg.memoize
import pwndbg.memory
@ -41,15 +42,10 @@ def find(address):
def find_upper_stack_boundary(addr, max_pages=1024):
addr = pwndbg.memory.page_align(int(addr))
try:
for i in range(max_pages):
data = pwndbg.memory.read(addr, 4)
if b'\x7fELF' == pwndbg.memory.read(addr, 4):
break
addr += pwndbg.memory.PAGE_SIZE
except gdb.MemoryError:
pass
return addr
base = pwndbg.elf.find_elf_magic(addr)
return base if base is not None else addr
@pwndbg.events.stop
@pwndbg.memoize.reset_on_stop

@ -17,6 +17,7 @@ import sys
import gdb
import pwndbg.abi
import pwndbg.compat
import pwndbg.elf
import pwndbg.events
@ -66,6 +67,7 @@ def find(address):
return explore(address)
@pwndbg.abi.LinuxOnly()
def explore(address_maybe):
"""
Given a potential address, check to see what permissions it has.

Loading…
Cancel
Save