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/
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
- Randomized positions: The same hex code appears at different numbered positions across connections
- Randomized distractors: Most hex codes change between connections — they are random noise
- 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 Code | Appearances | Type |
|---|---|---|
0x00FA | 30/30 | Secret code |
0x1A2B | 30/30 | Secret code |
0x88D1 | 30/30 | Secret code |
0x9C4F | 30/30 | Secret code |
0x3F7E | 1/30 | Random distractor |
0xB2C4 | 1/30 | Random 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
- [reverse][free]TunnelMadness— hackthebox
- [reverse][free]loicense— pingCTF
- [reverse][Pro]Challenge7— tamuctf
- [crypto][Pro]Одноразовый блокнот (One-Time Pad)— hackerlab
- [misc][Pro]Blind Hens— bluehens_ctf_2026