mobilefreemedium

Jigsaw

HackTheBox

A secret lies hidden, protected by layers of logic and scattered clues. Your task is to uncover these fragments, piece them together, and solve the mystery. It's a challenge of patience, creativity, and determination. Can you reveal the secret?

$ ls tags/ techniques/
flutter_debug_kernel_blob_extractionjava_arithmetic_shift_rornative_so_disassemblyaes_cbc_decryptionmulti_layer_key_assembly

$ cat /etc/rate-limit

Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.

Jigsaw — HackTheBox

Description

A secret lies hidden, protected by layers of logic and scattered clues. Your task is to uncover these fragments, piece them together, and solve the mystery. It's a challenge of patience, creativity, and determination. Can you reveal the secret?

The challenge provides a password-protected ZIP containing Jigsaw.apk — a Flutter Android application (~72MB).

Analysis

Initial Reconnaissance

  1. Extracted APK (which is a ZIP) and identified it as a Flutter application
  2. Key files discovered:
    • assets/flutter_assets/kernel_blob.bin — Contains Dart source code (Flutter debug build)
    • lib/x86_64/libmenascyber.so — Small native library (4952 bytes) with exported functions partthree_1 and partthree_2
    • classes3.dex — Java/Kotlin classes: MainActivity.kt, piecesOf.kt

Architecture: 3-Layer Key Assembly

The flag is encrypted with AES-256-CBC. The 32-byte key and 16-byte IV are assembled from three independent sources, each requiring a different reverse engineering approach:

LayerSourceLanguageKey bytesIV bytes
Part 1kernel_blob.binDart[0:8][0:4]
Part 2classes3.dexJava/Kotlin[8:16][4:8]
Part 3libmenascyber.soC++ (native)[16:32][8:16]

Combined AES Key (32 bytes):

partone_key[0:8] + parttwo_key[0:8] + partthree_key[0:16]

Combined AES IV (16 bytes):

partone_iv[0:4] + parttwo_iv[0:4] + partthree_iv[0:8]

Dart Source Recovery (kernel_blob.bin)

Using strings on kernel_blob.bin, full Dart source code was recovered across three files:

  • package:jigsaw/main.dart — Login UI, calls Finally.decryptFlag()
  • package:jigsaw/flag.dart — Contains encrypted flag base64: aZ/KF0GsnN81j5XStQyKz3vXtktTVN5zFqy5lwTmub6fx5w70c+p08O0OWcn/9nh
  • package:jigsaw/services.dart — Contains AESCombinedService which assembles the AES key/IV from 3 parts

The Finally class has the decryption logic but the return statement is commented out (//return decrypted;), returning "Developer forgot to uncomment" instead — forcing manual key recovery.

Solution

...

$ grep --similar

Similar writeups