archlinux / r3t0x@portfolio
ALL SYSTEMS NOMINAL /
← Back to archive · Pwn

Securinets Friendly CTF 2026 / Pwn WRITEUP

Chop's Last Fetch

CyberLeek entrusted the final piece of the GTA VI build to the only courier in Los Santos who could never be bribed, traced, or questioned. Chop still has the drop, but he only listens to handlers who can follow every command without falling behind. Keep up, and he may return with more than a stick.

EVENTSecurinets Friendly CTF 2026CATEGORYPwnDIFFICULTYeasyPOINTS200
pwntools

Walkthrough

Solution

This is a timed parser challenge. For each of 45 rounds, read the exact package length and apply every command from left to right. FETCH leaves the bytes alone; the remaining operations reverse, change case, repeat, rotate left, slice with an exclusive end, sort, XOR into lowercase hexadecimal, or return the byte count.

Using the advertised package length avoids delimiter mistakes. Send the transformed bytes before the two-second alarm on every round to receive the flag.

Reference solver

The reference solver supplied with the writeup:

#!/usr/bin/env python3
from pwn import *

context.log_level = "error"


def solve_command(data, command):
    commands = command.split(b" | ")

    for current in commands:
        words = current.split()

        if words[0] == b"FETCH":
            pass
        elif words[0] == b"REVERSE":
            data = data[::-1]
        elif words[0] == b"BARK":
            data = data.upper()
        elif words[0] == b"WHISPER":
            data = data.lower()
        elif words[0] == b"REPEAT":
            data = data * int(words[1])
        elif words[0] == b"ROTATE":
            amount = int(words[1])
            data = data[amount:] + data[:amount]
        elif words[0] == b"SLICE":
            start = int(words[1])
            end = int(words[2])
            data = data[start:end]
        elif words[0] == b"SORT":
            data = bytes(sorted(data))
        elif words[0] == b"XOR":
            key = int(words[1])
            data = bytes(byte ^ key for byte in data).hex().encode()
        elif words[0] == b"COUNT":
            data = str(len(data)).encode()

    return data


io = remote("127.0.0.1", 9003)

for _ in range(45):
    io.recvuntil(b"COMMAND: ")
    command = io.recvline().strip()

    io.recvuntil(b"PACKAGE SIZE: ")
    package_size = int(io.recvline())

    io.recvuntil(b"PACKAGE: ")
    package = io.recvn(package_size)

    answer = solve_command(package, command)
    io.sendlineafter(b"CHOP RETURNS: ", answer)

io.recvuntil(b"CHOP'S LAST FETCH:\n")
flag = io.recvline().decode().strip()
print(flag)
io.close()

Flag

Securinets{g00d_b0y_ch0p_br0ught_b4ck_th3_bu1ld}
Published 2026-09-28 · by r3t0x← Back to archive · Pwn
0xSEARCH_INDEX

Trace a memory.

INDEX ONLINE0 addresses
↑↓ TRACEENTER OPENESC DISMISS