miscfreeeasy

find-da-code

TJCTF 2026

Task: 4-stage terminal authentication where each stage shows 10 hex codes and you must pick the correct one; codes are randomized per connection. Solution: statistical frequency analysis over 30+ connections reveals 4 persistent hex codes (0x00FA, 0x1A2B, 0x88D1, 0x9C4F) that always appear — one per stage — among random distractors.

$ ls tags/ techniques/
statistical_frequency_analysismulti_connection_samplingautomated_code_selection

find-da-code — TJCTF 2026

Description

You were assigned 4 unique codes to remember a year ago, but you forgot them! Now you need to figure out a way to get in...

P.S. This challenge was inspired by a particular authentication system I had to bypass because I forgot my pictures lol

Connection: nc tjc.tf 31004

English summary: A 4-stage terminal authentication system inspired by picture-based password systems (like Passfaces). Each stage displays 10 hex codes and asks you to pick the correct one — your "assigned" code. The codes and their positions are randomized between connections, so you must figure out which 4 codes are the persistent secrets.

Analysis

Initial Reconnaissance

Connecting to the service shows:

=== SECURE TERMINAL LOGIN ===
Stage 1:
1. 0x3F7E
2. 0x00FA
3. 0xB2C4
4. 0x5D91
5. 0x7A08
6. 0xE6F3
7. 0x4C1D
8. 0xD8A5
9. 0x12B6
10. 0x6E39
Enter choice for stage 1 (1-10):

This repeats for 4 stages. Choosing wrong codes results in:

ERROR: Invalid Authentication Sequence. Connection terminated.

Key Observations

  1. Randomized positions: The same hex code appears at different numbered positions across connections
  2. Randomized distractors: Most hex codes change between connections — they are random noise
  3. No feedback per stage: You only learn if the full 4-stage sequence was correct or not after all stages

Statistical Frequency Analysis

The core insight comes from connecting 30+ times and recording which hex codes appear in each stage. By tallying frequencies:

  • 4 specific codes appear in nearly every connection: 0x00FA, 0x1A2B, 0x88D1, 0x9C4F
  • Exactly one of these 4 codes is always present in every stage (100% appearance rate)
  • Only one known code appears per stage — never two in the same stage
  • All other codes are random distractors that appear only ~once across all samples

This makes sense given the challenge theme: these 4 codes are the user's "assigned" authentication codes from a year ago. The system places one in each stage among 9 random distractors, simulating a picture-based auth system where you recognize your assigned image among decoys.

Frequency Table (example from 30 samples)

Hex CodeAppearancesType
0x00FA30/30Secret code
0x1A2B30/30Secret code
0x88D130/30Secret code
0x9C4F30/30Secret code
0x3F7E1/30Random distractor
0xB2C41/30Random distractor
.........

Solution

Once the 4 persistent codes are identified, the solve is straightforward: connect, parse each stage's options, find which known code is present, and select it.

Data Collection Script

#!/usr/bin/env python3 """Phase 1: Collect frequency data across many connections to identify persistent codes.""" from pwn import * import re from collections import Counter context.log_level = 'error' stage_counters = {i: Counter() for i in range(1, 5)} for attempt in range(30): try: r = remote('tjc.tf', 31004, timeout=5) data = r.recvuntil(b'(1-10): ', timeout=5).decode() stage = 1 for line in data.strip().split('\n'): m = re.match(r'(\d+)\.\s+(0x[0-9A-Fa-f]+)', line.strip()) if m: stage_counters[stage][m.group(2)] += 1 if 'Enter choice for stage' in line and stage < 4: stage += 1 r.sendline(b'1') # send dummy answer r.close() except: pass # Print codes that appear in >50% of connections for stage_num, counter in stage_counters.items(): print(f"\nStage {stage_num} - frequent codes:") for code, count in counter.most_common(5): if count > 15: print(f" {code}: {count}/30")

Solve Script

#!/usr/bin/env python3 """Phase 2: Authenticate using the 4 identified persistent codes.""" from pwn import * import re known_codes = {'0x00FA', '0x9C4F', '0x1A2B', '0x88D1'} r = remote('tjc.tf', 31004) for stage in range(1, 5): data = r.recvuntil(b'(1-10): ').decode() # Parse the numbered hex codes for this stage code_map = {} for line in data.strip().split('\n'): m = re.match(r'(\d+)\.\s+(0x[0-9A-Fa-f]+)', line.strip()) if m: code_map[m.group(2)] = m.group(1) # Find which known code is present in this stage present = set(code_map.keys()) & known_codes target = present.pop() log.info(f"Stage {stage}: selecting {target} (option {code_map[target]})") r.sendline(code_map[target].encode()) result = r.recvall().decode() print(result) # ACCESS GRANTED. # tjctf{brut3_f0rc3_th3_t3rm1n4l}

$ cat /etc/motd

Liked this one?

Pro unlocks every writeup, every flag, and API access. $9/mo.

$ cat pricing.md

$ grep --similar

Similar writeups