ShinyHunter
hackthebox
A Pokémon-themed challenge where you connect to a remote service that simulates a "Poketmon" game. You need to obtain a shiny Pokémon to get the flag. The title "ShinyHunter" hints at Pokémon shiny hunting and PRNG manipulation.
$ ls tags/ techniques/
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
ShinyHunter — HackTheBox
Description
A Pokémon-themed challenge where you connect to a remote service that simulates a "Poketmon" game. You need to obtain a shiny Pokémon to get the flag. The title "ShinyHunter" hints at Pokémon shiny hunting and PRNG manipulation.
Remote: 154.57.164.78:32331
Files
chall.py— Python challenge server (runs via socat on port 1337 inside Docker)
Analysis
Source Code Structure
The challenge implements a Pokémon starter selection game with a shiny check:
- Random MAC generation:
get_mac()generates a random MAC address displayed in the boot logo - Battery died:
system_timeis reset to 0, eliminating real-world clock entropy - Seed computation:
time_passed = time.time() - boot_time dialog_time = system_time + time_passed # = 0 + time_passed formatted_time = int(dialog_time) initial_seed = int(formatted_time + int(device_mac.replace(":", ""), 16)) seed = lcg(initial_seed) - Trainer IDs from seed:
def generate_ids(seed): random.seed(seed) tid = random.randint(0, 65535) sid = random.randint(0, 65535) return tid, sid - Shiny check:
shiny_value = ((tid ^ sid) ^ (pid & 0xFFFF) ^ (pid >> 16))— shiny if< 8 - LCG:
lcg(seed, a=1664525, c=1013904223, m=2**32)— standard Numerical Recipes LCG - 3 starters generated with
seed+0,seed+1,seed+2
Vulnerability: Fully Deterministic PRNG
The PRNG seed is completely predictable:
| Component | Status | Why |
|---|---|---|
| MAC address | Known | Displayed in the ASCII art logo output |
system_time | Zero | battery_died = True resets it to 0 |
time_passed | Controllable | We control when we send input (name), which triggers seed computation |
formatted_time | Predictable | int(time_passed) — integer seconds since boot |
Given the seed, all random values (tid, sid, pid) are fully predictable, so we can determine which starters will be shiny before choosing.
...
$ grep --similar
Similar writeups
- [web][free]egg— b01lersc
- [web][Pro]Rickroll— alfactf
- [reverse][Pro]Randser— spbctf
- [forensics][Pro]Secure Random (Безопасный рандом)— HackerLab
- [misc][free]Character— hackthebox