Mobile / Sea of Secrets CTF 2026

The Cursed APK

01 Nov 2026 · 1 min read

The challenge pushes you towards Frida and an emulator-hiding setup, but the root/emulator checks aren't a gate. They change a number that goes into the key, so on a "wrong" device you…

Mobile Security, Hard, 300 pts

FLAG{d34d_m3n_t3ll_n0_t4l35_fr1d4_unl0ck5_th3_cur53d_v4ult}

The challenge pushes you towards Frida and an emulator-hiding setup, but the root/emulator checks aren't a gate. They change a number that goes into the key, so on a "wrong" device you just get garbage out. You can skip the device entirely and compute the clean-device key offline.

Honeypot has a decoy flag (y0u_f0und_f00ls_g0ld_matey). The real logic is in VaultCore.

Oath. getSeaOath() builds the passphrase in three parts: bytes [30,31,27,30,5,23,31,20,5] XOR 90 give DEAD_MEN_, a literal TELL_NO_, and ints minus 50 give TALES_1718. The oath is DEAD_MEN_TELL_NO_TALES_1718.

Tide token. calculateTideToken returns 322420958 on a clean device. It returns a different constant if Sentry.isRooted, and XORs with 48879 if Sentry.isEmulator. In hex the clean value is 1337c0de.

Key and IV.

  • key = SHA-256(oath + ":" + tokenHex), AES-256
  • iv = first 16 bytes of SHA-256("SALT_CARIBBEAN_TIDES_1718:" + tokenHex)
  • mode: CBC, PKCS5

I tried all four combinations of root/emulator and only the clean one (1337c0de) decrypts to something that starts with FLAG{. The other three give random bytes, which is the "curse" in the story.