Various updates for symbolizing, auxv. Adds aslr command.

pull/10/head
Zach Riggle 11 years ago
parent c08cb916a1
commit 286206d163

@ -8,6 +8,7 @@ import pwndbg.elf
import pwndbg.proc
import pwndbg.regs
import pwndbg.stack
import pwndbg.stdio
import pwndbg.color
import pwndbg.function
import pwndbg.typeinfo
@ -26,6 +27,7 @@ import pwndbg.commands.ida
import pwndbg.commands.reload
import pwndbg.commands.rop
import pwndbg.commands.shell
import pwndbg.commands.aslr
__all__ = [
'arch',

@ -6,6 +6,7 @@ import pwndbg.events
import pwndbg.info
import pwndbg.memory
import pwndbg.regs
import pwndbg.stack
import pwndbg.typeinfo
example_info_auxv_linux = """
@ -138,7 +139,10 @@ def walk_stack():
if not auxv:
# For whatever reason, sometimes the ARM AUXV under qemu-user is
# not aligned properly.
return walk_stack2(1)
auxv = walk_stack2(1)
if not auxv['AT_EXECFN']:
auxv['AT_EXECFN'] = get_execfn()
return auxv
@ -215,3 +219,24 @@ def walk_stack2(offset=0):
p += 2
return auxv
def get_execfn():
# QEMU does not put AT_EXECFN in the Auxiliary Vector
# on the stack.
#
# However, it does put it at the very top of the stack.
#
# 32c:1960| 0x7fffffffefe0 <-- '/home/user/pwndbg/ld....'
# 32d:1968| 0x7fffffffefe8 <-- 'er/pwndbg/ld.so'
# 32e:1970| 0x7fffffffeff0 <-- 0x6f732e646c2f67 /* 'g/ld.so' */
# 32f:1978| 0x7fffffffeff8 <-- 0
# 330:1980| 0x7ffffffff000
addr = pwndbg.stack.find_upper_stack_boundary(pwndbg.regs.sp)
while pwndbg.memory.byte(addr-1) == 0:
addr -= 1
while pwndbg.memory.byte(addr-1) != 0:
addr -= 1
return pwndbg.strings.get(addr, 1024)

@ -1,3 +1,4 @@
import functools
import traceback
import gdb
@ -37,11 +38,11 @@ class Command(gdb.Command):
commands = []
def __init__(self, function):
self.__doc__ = function.__doc__
super(Command, self).__init__(function.__name__, gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION)
self.function = function
Command.commands.append(self)
functools.update_wrapper(self, function)
def split_args(self, argument):
return gdb.string_to_argv(argument)

@ -0,0 +1,13 @@
import pwndbg.vmmap
import pwndbg.commands
import pwndbg.color
@pwndbg.commands.OnlyWhenRunning
@pwndbg.commands.Command
def aslr():
status = pwndbg.color.red('OFF')
if pwndbg.vmmap.aslr:
status = pwndbg.color.green('ON')
print("ASLR is %s" % status)

@ -130,11 +130,12 @@ def get_ehdr(pointer):
# 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)
if data == b'\x7FELF':
break
else:
print("ERROR: Could not find ELF base!")
return None, None
@ -288,8 +289,3 @@ def map_inner(ei_class, ehdr, objfile):
page.objfile = objfile
return tuple(sorted(pages))
@pwndbg.events.stop
def update_main_exe():
addr = int(exe().address)
map(addr)

@ -5,6 +5,7 @@ Enables callbacks into functions to be automatically invoked
when various events occur to the debuggee (e.g. STOP on SIGINT)
by using a decorator.
"""
import functools
import traceback
import gdb
import sys
@ -31,16 +32,16 @@ class StartEvent(object):
def disconnect(self, function):
if function in self.registered:
self.registered.remove(function)
def on_new_objfile(self, o):
def on_new_objfile(self):
if self.running or not gdb.selected_thread():
return
self.running = True
for function in self.registered:
function(o)
function()
def on_stop(self, e):
def on_stop(self):
self.running = False
gdb.events.start = StartEvent()
@ -65,19 +66,17 @@ def connect(func, event_handler, name=''):
if debug:
print("Connecting", func.__name__, event_handler)
@functools.wraps(func)
def caller(*a):
func.__doc__
if debug: sys.stdout.write('%r %s.%s %r\n' % (name, func.__module__, func.__name__, a))
if pause: return
try:
func()
except Exception as e:
if debug: print(traceback.format_exc())
print(traceback.format_exc())
raise e
registered[event_handler].append(caller)
caller.name = func.__name__
caller.__name__ = func.__name__
event_handler.connect(caller)
return func
@ -102,9 +101,9 @@ def on_reload():
registered[event] = []
@new_objfile
def _start_newobjfile(o=None):
gdb.events.start.on_new_objfile(o)
def _start_newobjfile():
gdb.events.start.on_new_objfile()
@stop
def _start_stop(o=None):
gdb.events.start.on_stop(o)
def _start_stop():
gdb.events.start.on_stop()

@ -5,6 +5,7 @@ Talks to an XMLRPC server running inside of an active IDA Pro instance,
in order to query it about the database. Allows symbol resolution and
interactive debugging.
"""
import functools
import socket
from contextlib import closing
@ -46,7 +47,7 @@ setPort(8888)
class withIDA(object):
def __init__(self, fn):
self.fn = fn
self.__name__ = fn.__name__
functools.update_wrapper(self, fn)
def __call__(self, *args, **kwargs):
if _ida is not None:
return self.fn(*args, **kwargs)
@ -55,14 +56,14 @@ class withIDA(object):
class takes_address(object):
def __init__(self, fn):
self.fn = fn
self.__name__ = fn.__name__
functools.update_wrapper(self, fn)
def __call__(self, address, *args):
return self.fn(l2r(address), *args)
class returns_address(object):
def __init__(self, fn):
self.fn = fn
self.__name__ = fn.__name__
functools.update_wrapper(self, fn)
def __call__(self, *a, **kw):
return r2l(self.fn(*a, **kw))

@ -18,6 +18,12 @@ import pwndbg.events
debug = False
class memoize(object):
def __init__(self, func):
self.func = func
self.cache = {}
self.caches.append(self)
functools.update_wrapper(self, func)
def __call__(self, *args):
how = None
@ -61,11 +67,6 @@ class reset_on_stop(memoize):
caches = []
kind = 'stop'
def __init__(self, func):
self.func = func
self.cache = {}
self.caches.append(self)
@staticmethod
@pwndbg.events.stop
def __reset():
@ -76,13 +77,6 @@ class reset_on_exit(memoize):
caches = []
kind = 'exit'
def __init__(self, func):
self.func = func
self.cache = {}
self.caches.append(self)
self.__name__ = func.__name__
self.__module__ = func.__module__
@staticmethod
@pwndbg.events.exit
def __reset():
@ -93,13 +87,6 @@ class reset_on_objfile(memoize):
caches = []
kind = 'objfile'
def __init__(self, func):
self.func = func
self.cache = {}
self.caches.append(self)
self.__name__ = func.__name__
self.__module__ = func.__module__
@staticmethod
@pwndbg.events.new_objfile
def __reset():
@ -110,13 +97,6 @@ class reset_on_start(memoize):
caches = []
kind = 'start'
def __init__(self, func):
self.func = func
self.cache = {}
self.caches.append(self)
self.__name__ = func.__name__
self.__module__ = func.__module__
@staticmethod
@pwndbg.events.stop
@pwndbg.events.start

@ -11,9 +11,6 @@ PAGE_SIZE = 0x1000
MMAP_MIN_ADDR = 0x10000
def read(addr, count):
if count < 0:
import pdb
pdb.set_trace()
result = gdb.selected_inferior().read_memory(addr, count)
if pwndbg.compat.python3:
@ -77,6 +74,8 @@ def find_upper_boundary(addr, max_pages=1024):
try:
for i in range(max_pages):
pwndbg.memory.read(addr, 1)
import sys
sys.stdout.write(hex(addr) + '\n')
addr += pwndbg.memory.PAGE_SIZE
except gdb.MemoryError:
pass

@ -5,6 +5,7 @@ Provides values which would be available from /proc which
are not fulfilled by other modules.
"""
import sys
import functools
from types import ModuleType
import gdb
@ -28,13 +29,10 @@ class module(ModuleType):
auxv = pwndbg.auxv.get()
def OnlyWhenRunning(self, func):
@functools.wraps(func)
def wrapper(*a, **kw):
func.__doc__
if self.alive:
return func(*a, **kw)
wrapper.__name__ = func.__name__
wrapper.__module__ = func.__module__
wrapper.__doc__ = func.__doc__
return wrapper
# To prevent garbage collection

@ -27,11 +27,27 @@ def find(address):
Returns a pwndbg.memory.Page object which corresponds to the
currently-loaded stack.
"""
if not stacks:
update()
for stack in stacks:
if address in stack:
return stack
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
@pwndbg.events.stop
@pwndbg.memoize.reset_on_stop
def update():
"""
For each running thread, updates the known address range
@ -49,7 +65,7 @@ def update():
page = stacks.get(thread.ptid, None)
if page is None:
start = pwndbg.memory.find_lower_boundary(sp)
stop = pwndbg.memory.find_upper_boundary(sp)
stop = find_upper_stack_boundary(sp)
page = pwndbg.memory.Page(start, stop-start, 6 if not is_executable() else 7, 0, '[stack]')
stacks[thread.ptid] = page
continue
@ -57,7 +73,7 @@ def update():
page.objfile = '[stack]'
# If we *DO* already know about this thread, just
# udpate the lower boundary.
# update the lower boundary.
low = pwndbg.memory.find_lower_boundary(page.vaddr)
if low != page.vaddr:
page.memsz += (page.vaddr - low)

@ -0,0 +1,18 @@
"""
Provides functionality to circumvent GDB's hooks on sys.stdin and sys.stdout
which prevent output from appearing on-screen inside of certain event handlers.
"""
import gdb
import io
import sys
debug = True
def get(fd, mode):
file = io.open(1, mode=mode, buffering=0, closefd=False)
return io.TextIOWrapper(file, write_through=True)
if debug:
sys.stdin = get(0, 'rb')
sys.stdout = get(1, 'wb')
sys.stderr = get(2, 'wb')

@ -27,7 +27,10 @@ def update_length():
message = message.strip('.')
length = int(message)
def get(address):
def get(address, maxlen = None):
if maxlen is None:
maxlen = length
try:
sz = gdb.Value(address)
sz = sz.cast(pwndbg.typeinfo.pchar)
@ -39,7 +42,7 @@ def get(address):
if not all(s in string.printable for s in sz.rstrip('\x00')):
return None
if len(sz) < length:
if len(sz) < maxlen:
return sz
return sz[:length] + '...'
return sz[:maxlen] + '...'

@ -12,8 +12,9 @@ import pwndbg.elf
import pwndbg.ida
import pwndbg.memoize
import pwndbg.memory
import pwndbg.remote
import pwndbg.stack
import pwndbg.vmmap
@pwndbg.memoize.reset_on_objfile
def get(address):
@ -67,3 +68,15 @@ def address(symbol):
return int(address, 0)
except gdb.error:
return None
@pwndbg.events.stop
@pwndbg.memoize.reset_on_start
def add_main_exe_to_symbols():
if not pwndbg.remote.is_remote():
return
exe = pwndbg.elf.exe()
addr = exe.address
path = pwndbg.vmmap.find(addr).objfile
if addr and path:
gdb.execute('add-symbol-file %s %#x' % (path, addr), from_tty=False, to_string=True)

@ -322,8 +322,17 @@ def check_aslr():
vmmap = sys.modules[__name__]
vmmap.aslr = False
system_aslr = True
data = ''
try: data = pwndbg.file.get('/proc/sys/kernel/randomize_va_space')
except OSError: pass
output = gdb.execute('show disable-randomization', to_string=True)
if "is off." in output:
vmmap.aslr = True
return vmmap.aslr

Loading…
Cancel
Save