Securinets Friendly CTF 2026 / Misc WRITEUP
Human After All
Haters gonna say it s AI
Walkthrough
The service puts the player's note in the last comment of Submission.java and runs the supplied byte classifier. Notes are printable ASCII, at most 72 bytes, and cannot contain */.
The model has a byte embedding, four convolution widths (3, 5, 7, 11), ReLU, global max pooling, and one linear output. The source, model, threshold and weights given to players are the exact files used by the server.
The local detector, threshold, preprocessing, source template, and weights are all public and deterministic.
Intended solution
Look at channels with negative output weights. For each position in one of those filters, try every printable byte and keep the embedding with the largest dot product. This gives one good string per filter.
Not every recovered n-gram is useful:
- several negative channels are already saturated by
Submission.java; - some attractive negative channels also activate positive channels;
- all recovered strings do not fit in the note.
Score those strings locally and keep the best score reduction per byte. Some negative filters are already active in the Java file, and a few candidate strings also activate positive filters, so blindly joining all of them does not work. See solver.py for the short reference implementation.
Reference solver
The reference solver supplied with the writeup:
#!/usr/bin/env python3
import socket
import sys
from attachments.detector import Detector, PRINTABLE
def solve():
detector = Detector()
words = []
for branch in detector.branches:
for channel, head in zip(branch["weight"], branch["head"]):
if head >= 0:
continue
word = bytes(
max(
PRINTABLE,
key=lambda char: sum(
a * b for a, b in zip(detector.embedding[char], weights)
),
)
for weights in channel
)
if b"*/" not in word and word not in words:
words.append(word)
payload = b""
score = detector.score(payload)
while score >= detector.threshold:
best = None
for word in words:
for separator in ((b"",) if not payload else (b" ", b"_", b"~", b"|")):
extra = separator + word
trial = payload + extra
if len(trial) > detector.max_note or b"*/" in trial:
continue
new_score = detector.score(trial)
gain = score - new_score
if gain <= 0:
continue
key = (gain / len(extra), gain)
if best is None or key > best[0]:
best = (key, word, trial, new_score)
if best is None:
raise RuntimeError("no payload found")
_, word, payload, score = best
words.remove(word)
return detector, payload
def send(host, port, payload):
with socket.create_connection((host, port)) as sock:
data = b""
while b"note> " not in data:
data += sock.recv(4096)
sock.sendall(payload + b"\n")
while True:
block = sock.recv(4096)
if not block:
break
sys.stdout.buffer.write(block)
def main():
detector, payload = solve()
print(payload.decode(), flush=True)
print(
f"{len(payload)}/{detector.max_note} bytes, logit {detector.score(payload):.4f}",
flush=True,
)
if len(sys.argv) == 3:
send(sys.argv[1], int(sys.argv[2]), payload)
elif len(sys.argv) != 1:
raise SystemExit(f"usage: {sys.argv[0]} [host port]")
if __name__ == "__main__":
main()Flag
Securinets{c0mm3nts_4r3_f34tur3s_t00}