Fix aslr command and file.get_file on QEMU targets

The ASLR command did not work properly on QEMU kernel targets: it read /proc/sys/kernel/randomize_va_space and then /proc/<pid>/personality on local filesystem which was wrong, and returned that it couldn't read personality.

Now, this commit made so that:
- the `pwndbg.file.get_file` will print a warning if it returns a local path on remote targets
- the `check_aslr` was refactored: we don't run this on `new_objfile` or cache its result; the `pwndbg.vmmap.aslr` was also removed as it was never used
- the `pwndbg.vmmap.check_aslr` and `aslr` command will now return info if we couldn't detect ASLR on QEMU targets
pull/880/head
Disconnect3d 4 years ago
parent 27506431e8
commit 69094409f5

@ -7,11 +7,15 @@ import pwndbg.events
import pwndbg.file import pwndbg.file
import pwndbg.memoize import pwndbg.memoize
import pwndbg.remote import pwndbg.remote
import pwndbg.qemu
@pwndbg.memoize.reset_on_start @pwndbg.memoize.reset_on_start
@pwndbg.memoize.reset_on_exit @pwndbg.memoize.reset_on_exit
def is_android(): def is_android():
if pwndbg.qemu.is_qemu():
return False
try: try:
if pwndbg.file.get('/system/etc/hosts'): if pwndbg.file.get('/system/etc/hosts'):
return True return True

@ -30,9 +30,12 @@ def aslr(state=None):
print("Change will take effect when the process restarts") print("Change will take effect when the process restarts")
aslr, method = pwndbg.vmmap.check_aslr() aslr, method = pwndbg.vmmap.check_aslr()
status = message.off('OFF')
if aslr: if aslr is True:
status = message.on('ON') status = message.on('ON')
elif aslr is False:
status = message.off('OFF')
else:
status = message.off('???')
print("ASLR is %s (%s)" % (status, method)) print("ASLR is %s (%s)" % (status, method))

@ -29,7 +29,8 @@ def get_file(path):
qemu_root = pwndbg.qemu.root() qemu_root = pwndbg.qemu.root()
if qemu_root: if qemu_root:
return os.path.join(qemu_root, path) return os.path.join(qemu_root, path)
elif pwndbg.remote.is_remote() and not pwndbg.qemu.is_qemu(): elif pwndbg.remote.is_remote():
if not pwndbg.qemu.is_qemu():
local_path = tempfile.mktemp(dir=pwndbg.symbol.remote_files_dir) local_path = tempfile.mktemp(dir=pwndbg.symbol.remote_files_dir)
error = None error = None
try: try:
@ -41,6 +42,8 @@ def get_file(path):
if error: if error:
raise OSError("Could not download remote file %r:\n" \ raise OSError("Could not download remote file %r:\n" \
"Error: %s" % (path, error)) "Error: %s" % (path, error))
else:
print("[pwndbg warning]: pwndbg.file.get(%s) returns local path" % path)
return local_path return local_path

@ -425,31 +425,23 @@ def find_boundaries(addr, name='', min=0):
return pwndbg.memory.Page(start, end-start, 4, 0, name) return pwndbg.memory.Page(start, end-start, 4, 0, name)
aslr = False
@pwndbg.events.new_objfile
@pwndbg.memoize.while_running
def check_aslr(): def check_aslr():
vmmap = sys.modules[__name__] """
vmmap.aslr = False Detects the ASLR status. Returns True, False or None.
# Check to see if ASLR is disabled on the system.
# if not pwndbg.remote.is_remote():
system_aslr = True
data = b''
None is returned when we can't detect ASLR.
"""
# QEMU does not support this concept. # QEMU does not support this concept.
if pwndbg.qemu.is_qemu_usermode(): if pwndbg.qemu.is_qemu():
return vmmap.aslr return None, 'Could not detect ASLR on QEMU targets'
# Systemwide ASLR is disabled # Systemwide ASLR is disabled
try: try:
data = pwndbg.file.get('/proc/sys/kernel/randomize_va_space') data = pwndbg.file.get('/proc/sys/kernel/randomize_va_space')
if b'0' in data: if b'0' in data:
vmmap.aslr = False return False, 'kernel.randomize_va_space == 0'
return vmmap.aslr, 'kernel.randomize_va_space == 0'
except Exception as e: except Exception as e:
print("Could not check ASLR: Couldn't get randomize_va_space") print("Could not check ASLR: can't read randomize_va_space")
pass pass
# Check the personality of the process # Check the personality of the process
@ -457,11 +449,9 @@ def check_aslr():
try: try:
data = pwndbg.file.get('/proc/%i/personality' % pwndbg.proc.pid) data = pwndbg.file.get('/proc/%i/personality' % pwndbg.proc.pid)
personality = int(data, 16) personality = int(data, 16)
if personality & 0x40000 == 0: return (personality & 0x40000 == 0), 'read status from process\' personality'
vmmap.aslr = True
return vmmap.aslr, 'read status from process\' personality'
except: except:
print("Could not check ASLR: Couldn't get personality") print("Could not check ASLR: can't read process' personality")
pass pass
# Just go with whatever GDB says it did. # Just go with whatever GDB says it did.
@ -469,10 +459,7 @@ def check_aslr():
# This should usually be identical to the above, but we may not have # This should usually be identical to the above, but we may not have
# access to procfs. # access to procfs.
output = gdb.execute('show disable-randomization', to_string=True) output = gdb.execute('show disable-randomization', to_string=True)
if "is off." in output: return ("is off." in output), 'show disable-randomization'
vmmap.aslr = True
return vmmap.aslr, 'show disable-randomization'
@pwndbg.events.cont @pwndbg.events.cont
def mark_pc_as_executable(): def mark_pc_as_executable():

Loading…
Cancel
Save