Kaje
Category: Reversing Points: 338 Author: Anonimbus
Challenge Description
I don't know what is the intended solution anymore.
Solution
Step 1: Identify the Binary
$ file kaje
kaje: ELF 64-bit LSB pie executable, x86-64, dynamically linked, not stripped
Not stripped — we have symbols: main, gen_entropy, gen_keystream.
Step 2: Reverse the Logic
The binary has three key functions:
gen_entropy() — Environment-dependent seed generation:
c
seed = 0xCD9AADD8D9C9A989; // default (Docker)
if (!dockerenv_exists)
seed = 0x1337133713371337; // not Docker
if (overlay_in_mountinfo)
seed ^= 0xABCDEF1234567890;
return splitmix64_finalize(seed);It checks:
access("/.dockerenv", 0)— does the Docker sentinel file exist?strstr(mountinfo, "overlay")— is overlay filesystem present?
Then applies a splitmix64 hash finalizer (multiply by 0xFF51AFD7ED558CCD, shift, multiply by 0xC4CEB9FE1A85EC53, shift).
gen_keystream(buf, seed) — Generates 32 bytes using iterative splitmix64 mixing.
main() — XORs 32 bytes of embedded ciphertext with the keystream and prints the result.
Step 3: Determine the Correct Environment
The binary was meant to run inside Docker (which uses overlay fs), giving:
seed = 0xCD9AADD8D9C9A989 ^ 0xABCDEF1234567890 = 0x665742CAED9F2119
Step 4: Decrypt
python
MASK = 0xFFFFFFFFFFFFFFFF
C1, C2 = 0xFF51AFD7ED558CCD, 0xC4CEB9FE1A85EC53
def splitmix64_mix(v):
v = (v ^ (v >> 33)) & MASK
v = (v * C1) & MASK
v = (v ^ (v >> 33)) & MASK
v = (v * C2) & MASK
return (v ^ (v >> 33)) & MASK
def gen_keystream(seed):
ks, a2 = bytearray(32), seed
for i in range(32):
val = ((a2 + i) ^ ((a2 + i) >> 33)) & MASK
val = (val * C1) & MASK
val = ((val >> 33) ^ val) & MASK
val = (val * C2) & MASK
a2 = ((val >> 33) ^ val) & MASK
ks[i] = a2 & 0xFF
return ks
enc = bytes([0x9f,0x12,0xd9,0x1b,0xe2,0x12,0xbb,0xba,
0xfb,0xf5,0xfe,0xe8,0xa6,0x32,0xac,0xc6,
0x04,0x36,0x92,0xd4,0xc9,0x3b,0xbd,0xbe,
0x22,0xa2,0xb4,0x83,0x6b,0x45,0x03,0xd3])
seed = 0xCD9AADD8D9C9A989 ^ 0xABCDEF1234567890
ks = gen_keystream(splitmix64_mix(seed))
print(bytes(a ^ b for a, b in zip(enc, ks)).decode())Flag
EH4X{dUnn0_wh4tt_1z_1nt3NTenD3d}
Key Takeaways
- The binary uses environment fingerprinting (Docker + overlay fs) to derive the decryption key
- Running outside Docker produces garbage — static reversing is required
- The splitmix64 finalizer is a well-known PRNG mixing function, recognizable by its constants
0xFF51AFD7ED558CCDand0xC4CEB9FE1A85EC53 - Only 4 possible environment combinations exist, so brute-forcing all cases trivially finds the flag