MediumTJCTF 2026 — find-da-code (Misc) Writeup | by silentzer0 | Medium
Sitemap

TJCTF 2026 — find-da-code (Misc) Writeup

3 min readJun 7, 2026

--

Hi Everyone, I’m Muhammad Jilani (A.K.A silentzer0)

Recently I had the opportunity to participate in TJCTF 2026. Here is my writeup for the Misc category chall find-da-code.

At first glance, the challenge looked like a simple guessing game, but after observing the server behavior carefully across multiple connections, a pattern started to appear.

In this writeup, I’ll walk through the entire solving process step by step, including:

  • Initial observations,
  • Identifying the hidden pattern,
  • Understanding the authentication logic,
  • Automating the solve using Python.

Even if you’re new to CTFs, this challenge is a great example of how careful observation can completely break an authentication system.

Initial Enumeration

After connecting to the remote service using netcat, I was presented with a terminal-like authentication system consisting of 4 stages.

Each stage displayed 10 hexadecimal values and required selecting one option:

=== SECURE TERMINAL LOGIN ===
Stage 1
1. 0x08BC
2. 0x88D1
3. 0xDB34
4. 0xD6E3
5. 0x81A1
6. 0xD01B
7. 0xE5FD
8. 0x792B
9. 0x5246
10. 0x7BDA
Enter choice for stage 1 (1-10):

At this point, the challenge looked similar to a randomized authentication puzzle where we somehow needed to identify the “correct” values.

My first assumption was that:

  • Either the values followed a hidden mathematical pattern,
  • Or the challenge relied on observing behavior across multiple connections.

Looking for Patterns

Since the challenge description mentioned “4 unique codes,” I suspected that some values might remain constant between sessions.

Get silentzer0’s stories in your inbox

Join Medium for free to get updates from this writer.

To test this theory, I repeatedly connected to the service and compared the generated hexadecimal values from each run.

The key observation was that, connecting multiple times reveals that 4 specific hex values appear in every session, while the other 36 are random each time:

Tokens Always Presents :

0x1A2B✅

0x00FA✅

0x88D1✅

0x9C4F✅

These 4 values are generated with a fixed PRNG seed, making them invariant across connections. The remaining 36 values are randomly generated decoys. The 4 fixed values are the “4 unique codes” we were assigned — they never change, we just forgot them.

The “bypass” is simply recognizing that these codes are always the same and can be rediscovered by observing multiple connections.

Approach

  1. Connect to the terminal
  2. Scan each stage for the 4 known tokens (0x1A2B, 0x00FA, 0x88D1, 0x9C4F)
  3. Submit the position of one found token per stage
  4. Receive “ACCESS GRANTED” and the flag

Solution Script

import socket
import time
import re

CORRECT_TOKENS = [0x1A2B, 0x00FA, 0x88D1, 0x9C4F]

s = socket.socket()
s.settimeout(10)
s.connect((‘tjc.tf’, 31004))

positions = []
all_data = b’’

for stage_idx in range(4):
buf = b’’
while True:
try:
chunk = s.recv(4096)
if not chunk:
raise Exception(“Connection closed”)
buf += chunk
if b’Enter choice for stage’ in chunk:
break
except socket.timeout:
raise Exception(“Timeout waiting for stage data”)

all_data += buf
text = buf.decode(‘utf-8’, errors=’replace’)
vals = [int(v, 16) for v in re.findall(r’0x([0–9A-F]{4})’, text)]

found = False
for i, val in enumerate(vals):
if val in CORRECT_TOKENS:
positions.append(i + 1)
found = True
break

if not found:
positions.append(1) # fallback (should never happen)

s.send(f’{positions[-1]}\n’.encode())
time.sleep(0.05)

time.sleep(0.5)
try:
while True:
chunk = s.recv(4096)
if not chunk:
break
all_data += chunk
except:
pass

s.close()
result = all_data.decode(‘utf-8’, errors=’replace’)
print(result)

Upon running the solution script we get our flag :

tjctf{brut3_f0rc3_th3_t3rm1n4l}

I Hope You Benefit From This Write Up , And Wait Another Write ups Soon And Don’t Forget To Follow Me!!!

Happy Hacking

--

--