command robustness improvements and graceful errors (#185)

* search: fix --word -2 param and allow --short in reflect to --type short

Search failed when using the --word (-2) parameter as 'word' was
not found in the type lookup. Using 'word' instead of 'short' seems
to be the better option as that matches better in this context.

* search: more robust and graceful error messages for invalid input

This makes error messages for wrong input more graceful instead of
dying and printing an ugly full traceback exception.

* harden hexdump and telescope commands against malformed arguments

* only allow retaddr and canary commands when in running mode

* xor: gracefully complain on invalid memory address

* next: check if proc is alive while continuing to avoid exceptions

If the program terminates while we are still looping/continuing for
the according next command, then an internal gdb.error is thrown as
the program is not being run.
We avoid such situations by adding the proc.alive to the looping
conditions.

* memory: force write_memory to be bytes for python2 gdb

* catch general gdb.error instead of specific gdb.MemoryError
pull/189/head
Levente Polyak 9 years ago committed by Zach Riggle
parent 1869b8a8a3
commit 433bf23177

@ -6,6 +6,7 @@ from __future__ import print_function
from __future__ import unicode_literals
import argparse
import gdb
import pwndbg.arch
import pwndbg.commands
@ -32,13 +33,17 @@ parser.add_argument('count', nargs='?', default=pwndbg.config.hexdump_bytes,
def hexdump(address=None, count=pwndbg.config.hexdump_bytes):
address = int(address)
address &= pwndbg.arch.ptrmask
count = int(count)
count = max(int(count), 0)
width = int(pwndbg.config.hexdump_width)
if count > address > 0x10000:
count -= address
data = pwndbg.memory.read(address, count, partial=True)
try:
data = pwndbg.memory.read(address, count, partial=True)
except gdb.error as e:
print(e)
return
for line in pwndbg.hexdump.hexdump(data, address=address, width=width):
print(line)

@ -77,6 +77,7 @@ def distance(a, b):
print("%#x->%#x is %#x bytes (%#x words)" % (a, b, distance, distance // _arch.ptrsize))
@_pwndbg.commands.Command
@_pwndbg.commands.OnlyWhenRunning
def canary():
"""Print out the current stack canary"""
auxv = _pwndbg.auxv.get()

@ -53,7 +53,7 @@ def next_syscall(*args):
"""
Breaks at the next syscall.
"""
while not pwndbg.next.break_next_interrupt() and pwndbg.next.break_next_branch():
while pwndbg.proc.alive and not pwndbg.next.break_next_interrupt() and pwndbg.next.break_next_branch():
continue
pwndbg.commands.context.context()

@ -6,6 +6,7 @@ from __future__ import print_function
from __future__ import unicode_literals
import argparse
import binascii
import codecs
import os
import struct
@ -50,11 +51,11 @@ auto_save = pwndbg.config.Parameter('auto-save-search', False,
parser = argparse.ArgumentParser(description='''
Search memory for byte sequences, strings, pointers, and integer values
''')
parser.add_argument('-t', '--type', choices=['byte','short','dword','qword','pointer','string','bytes'],
parser.add_argument('-t', '--type', choices=['byte','short','word','dword','qword','pointer','string','bytes'],
help='Size of search target', default='bytes', type=str)
parser.add_argument('-1', '--byte', dest='type', action='store_const', const='byte',
help='Search for a 1-byte integer')
parser.add_argument('-2', '--word', dest='type', action='store_const', const='word',
parser.add_argument('-2', '--word', '--short', dest='type', action='store_const', const='word',
help='Search for a 2-byte integer')
parser.add_argument('-4', '--dword', dest='type', action='store_const', const='dword',
help='Search for a 4-byte integer')
@ -95,7 +96,11 @@ def search(type, hex, string, executable, writable, value, mapping, save, next):
save = bool(pwndbg.config.auto_save_search)
if hex:
value = codecs.decode(value, 'hex')
try:
value = codecs.decode(value, 'hex')
except binascii.Error as e:
print('invalid input for type hex: {}'.format(e))
return
# Convert to an integer if needed, and pack to bytes
if type not in ('string', 'bytes'):
@ -107,11 +112,17 @@ def search(type, hex, string, executable, writable, value, mapping, save, next):
}[pwndbg.arch.endian] + {
'byte': 'B',
'short': 'H',
'word': 'H',
'dword': 'L',
'qword': 'Q'
}[type]
value = struct.pack(fmt, value)
try:
value = struct.pack(fmt, value)
except struct.error as e:
print('invalid input for type {}: {}'.format(type, e))
return
# Null-terminate strings
elif type == 'string':

@ -19,6 +19,7 @@ Print out the stack addresses that contain return addresses
''')
@pwndbg.commands.ArgparsedCommand(p)
@pwndbg.commands.OnlyWhenRunning
def retaddr():
sp = pwndbg.regs.sp
stack = pwndbg.vmmap.find(sp)

@ -16,12 +16,12 @@ def xor_memory(address, key, count):
Helper function for xorring memory in gdb
"""
mem = pwndbg.memory.read(address, count, partial=True)
for index, byte in enumerate(mem):
key_index = index % len(key)
mem[index] = byte ^ ord(key[key_index])
return mem
return mem
@pwndbg.commands.Command
@pwndbg.commands.OnlyWhenRunning
@ -31,10 +31,17 @@ def xor(address, key, count):
XOR ``count`` bytes at ``address`` with the key ``key``.
'''
if not isinstance(address, six.integer_types):
address = int(address, 16)
try:
address = int(address, 0)
except ValueError:
print('Invalid address %s' % address)
return
xorred_memory = xor_memory(address, key, count)
pwndbg.memory.write(address, xorred_memory)
try:
xorred_memory = xor_memory(address, key, count)
pwndbg.memory.write(address, xorred_memory)
except gdb.error as e:
print(e)
@pwndbg.commands.Command
@pwndbg.commands.OnlyWhenRunning
@ -44,7 +51,14 @@ def memfrob(address, count):
Run the memfrob command on a region of memory
'''
if not isinstance(address, six.integer_types):
address = int(address, 16)
try:
address = int(address, 0)
except ValueError:
print('Invalid address %s' % address)
return
xorred_memory = xor_memory(address, '*', count)
pwndbg.memory.write(address, xorred_memory)
try:
xorred_memory = xor_memory(address, '*', count)
pwndbg.memory.write(address, xorred_memory)
except gdb.error as e:
print(e)

@ -38,6 +38,7 @@ def read(addr, count, partial=False):
or ``None``.
"""
result = b''
count = max(int(count), 0)
try:
result = gdb.selected_inferior().read_memory(addr, count)
@ -96,7 +97,7 @@ def write(addr, data):
addr(int): Address to write
data(str,bytes,bytearray): Data to write
"""
gdb.selected_inferior().write_memory(addr, data)
gdb.selected_inferior().write_memory(addr, bytes(data))
def peek(address):
"""peek(address) -> str

@ -79,7 +79,7 @@ def break_next_interrupt(address=None):
return ins
def break_next_call(address=None):
while True:
while pwndbg.proc.alive:
ins = break_next_branch(address)
if not ins:

Loading…
Cancel
Save