Securinets Friendly CTF 2026 / Pwn WRITEUP
CyberLeek's Final Upload
The final GTA VI archive is already leaving Rockstar's internal network. CyberLeek reached the relay, but the interface was destroyed and the upload continues as an unreadable stream. Keep the last copy of the build from disappearing!
Walkthrough
Solution
Treat the connection as a binary stream because each frame is deliberately split across short writes. Read LEEK, then the big-endian sequence, operation, payload length, payload, and checksum. Verify that the checksum is the 32-bit sum of the payload bytes.
Apply the requested operation: reverse, XOR, rotate left, sort, or byte-wise add. For XOR, rotate, and add, the first payload byte is the key rather than data. Reply with ACK!, the original sequence, result length, result, and its big-endian checksum. Processing all 32 frames reveals the flag.
Reference solver
The reference solver supplied with the writeup:
#!/usr/bin/env python3
from pwn import *
context.log_level = "error"
io = remote("127.0.0.1", 9004)
io.recvuntil(b"BEGIN UPLOAD\n")
for _ in range(32):
io.recvuntil(b"LEEK")
sequence = u16(io.recvn(2), endian="big")
operation = io.recvn(1)[0]
length = u16(io.recvn(2), endian="big")
payload = io.recvn(length)
received_sum = u32(io.recvn(4), endian="big")
assert received_sum == sum(payload) & 0xffffffff
data = payload
if operation in (2, 3, 5):
key = payload[0]
data = payload[1:]
if operation == 1:
result = data[::-1]
elif operation == 2:
result = bytes(byte ^ key for byte in data)
elif operation == 3:
shift = key % len(data)
result = data[shift:] + data[:shift]
elif operation == 4:
result = bytes(sorted(data))
else:
result = bytes((byte + key) & 0xff for byte in data)
reply = b"ACK!"
reply += p16(sequence, endian="big")
reply += p16(len(result), endian="big")
reply += result
reply += p32(sum(result) & 0xffffffff, endian="big")
io.send(reply)
io.recvuntil(b"UPLOAD COMPLETE\n")
print(io.recvline().decode().strip())
io.close()Flag
Securinets{r4w_fr4m3s_c4rr13d_th3_f1n4l_bu1ld}