← Back to EHAX 2026

Kaje

Reverse Engineering 467 pts

Challenge

  • Name: Kaje
  • Category: Reverse Engineering
  • Points: 467
  • Solves: 42
  • Author: Anonimbus
  • Description: "I don't know what is the intended solution anymore."

Solution

Binary Overview

The challenge provides a 64-bit ELF binary (kaje), not stripped, compiled from final.c. It contains three key functions: main, gen_entropy, and gen_keystream.

Analysis

gen_entropy (0x1290)

This function determines a seed value based on the runtime environment:

  1. Docker detection: Checks if /.dockerenv exists using access().
    • If the file exists (we are in Docker): r12 = 0xcd9aadd8d9c9a989
    • If the file does not exist (not in Docker): r12 = 0x1337133713371337
  2. Overlay filesystem detection: Opens /proc/self/mountinfo and searches each line for the string "overlay".
    • If found: r12 ^= 0xabcdef1234567890
  3. Finalization: Applies the murmur3 64-bit finalizer (mix64) to r12 and returns it as the seed.

This creates four possible seed values depending on the environment.

gen_keystream (0x13b0)

Generates 32 bytes of keystream from the seed using a chained murmur3 hash:

s = seed
for i in 0..31:
    v = s + i
    s = mix64(v)
    keystream[i] = s & 0xFF

Where mix64 is the standard murmur3 64-bit finalizer:

x ^= x >> 33
x *= 0xff51afd7ed558ccd
x ^= x >> 33
x *= 0xc4ceb9fe1a85ec53
x ^= x >> 33

main (0x1120)

  1. Calls gen_entropy() to get the seed.
  2. Calls gen_keystream(seed) to generate 32 bytes of keystream on the stack.
  3. XORs the keystream with 32 bytes of encrypted data stored in .rodata (at offsets 0x2030 and 0x2040) using SSE pxor instructions.
  4. Prints the result with puts().

Encrypted Data

From .rodata:

0x2030: 9f 12 d9 1b e2 12 bb ba fb f5 fe e8 a6 32 ac c6
0x2040: 04 36 92 d4 c9 3b bd be 22 a2 b4 83 6b 45 03 d3

Solving

The challenge description hints at multiple approaches -- but fundamentally, there are only four possible seeds based on the two boolean checks (docker present, overlay present). By trying all four combinations:

Environment r12 Decrypted Output
Docker + overlay 0x665742caed9fd119 Valid flag output
Docker + no overlay 0xcd9aadd8d9c9a989 garbage
No docker + overlay 0xb8fafc2527616ba7 garbage
No docker + no overlay 0x1337133713371337 garbage

The correct environment is Docker with overlay filesystem (the "intended" execution environment, matching how CTF challenges are typically deployed in containers).

The flag text mirrors the challenge description "I don't know what is the intended solution anymore."