# LAIN_Br34kC0r3 V2 — Solution

**Chapitre 2 : Core Analysis** | Difficulté : Hard | Flag : `ESPILON{3sp32_fl4sh_dump_r3v3rs3d}`

## Overview

Ce challenge fournit un dump flash complet d'un ESP32 (bootloader + partition table + NVS + firmware applicatif). Le joueur doit extraire le firmware, le reverse engineer pour trouver les clés AES-256-CBC, puis déchiffrer le flag stocké dans la NVS.

## Étape 1 — Récupérer le dump flash

```bash
# Terminal 1 : TX (lecture)
nc <host> 1111 | tee flash_output.txt

# Terminal 2 : RX (écriture)
echo "dump_flash" | nc <host> 2222
```

Le dump est envoyé en base64. Extraire et décoder :

```python
import base64

with open("flash_output.txt") as f:
    lines = f.readlines()

# Extract base64 lines between markers
b64_data = ""
capture = False
for line in lines:
    if "BEGIN FLASH DUMP" in line:
        capture = True
        continue
    if "END FLASH DUMP" in line:
        break
    if capture:
        b64_data += line.strip()

flash = base64.b64decode(b64_data)
with open("flash_dump.bin", "wb") as f:
    f.write(flash)
```

## Étape 2 — Analyse du dump flash

```bash
# Identifier les composants
binwalk flash_dump.bin

# Ou utiliser esptool
esptool.py image_info --version 2 flash_dump.bin
```

Structure identifiée :
```
0x0000  Padding (0xFF)
0x1000  ESP32 bootloader (magic 0xE9)
0x8000  Partition table
0x9000  NVS partition (24 KiB)
0xF000  PHY init data
0x10000 Application firmware (magic 0xE9)
```

## Étape 3 — Extraire le firmware applicatif

```bash
# Extraire l'app à partir de l'offset 0x10000
dd if=flash_dump.bin of=app_firmware.bin bs=1 skip=$((0x10000))

# Vérifier
file app_firmware.bin
# Devrait montrer un binaire ESP32 ou "data"

hexdump -C app_firmware.bin | head -5
# Premier byte devrait être 0xE9 (ESP image magic)
```

## Étape 4 — Reverse Engineering

### Méthode rapide : strings

```bash
strings -n 10 app_firmware.bin | grep -i "key\|aes\|iv\|wired\|therapy"
```

Résultats attendus :
```
W1R3D_M3D_TH3R4PY_K3Y_2024_L41N!    # AES-256 key (32 bytes)
L41N_WIRED_IV_01                      # AES IV (16 bytes)
WIRED-MED Therapy Module
```

### Méthode complète : Ghidra

1. Ouvrir Ghidra, importer `app_firmware.bin` (ou mieux, l'ELF si disponible)
2. Architecture : **Xtensa:LE:32:default**
3. Analyser → chercher `app_main` dans les symboles
4. Suivre les appels : `app_main()` → `wired_med_crypto_init()` → `mbedtls_aes_setkey_enc()`
5. Les arguments de `mbedtls_aes_setkey_enc()` pointent vers `therapy_aes_key` dans `.rodata`
6. Extraire les 32 bytes de la clé et les 16 bytes de l'IV

## Étape 5 — Récupérer le flag chiffré

### Option A : Commande directe
```
encrypted_data
```
→ Retourne le ciphertext en hex

### Option B : Parser la NVS
```bash
# Extraire la partition NVS
dd if=flash_dump.bin of=nvs_dump.bin bs=1 skip=$((0x9000)) count=$((0x6000))

# Utiliser nvs_tool.py de ESP-IDF (si disponible)
python3 $IDF_PATH/components/nvs_flash/nvs_partition_tool/nvs_tool.py --dump nvs_dump.bin
```

Chercher l'entrée : namespace `wired_med`, key `encrypted_flag`, type blob

## Étape 6 — Déchiffrement AES-256-CBC

```python
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad

key = b"W1R3D_M3D_TH3R4PY_K3Y_2024_L41N!"  # 32 bytes
iv  = b"L41N_WIRED_IV_01"                   # 16 bytes

# Ciphertext from encrypted_data command or NVS
ciphertext = bytes.fromhex("...")

cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size)
print(plaintext.decode())
# ESPILON{3sp32_fl4sh_dump_r3v3rs3d}
```

## Résumé de la chaîne d'attaque

```
dump_flash → base64 decode → binwalk → extract app @ 0x10000
    → strings/Ghidra (Xtensa RE) → find AES key + IV in .rodata
    → encrypted_data (or NVS parse) → AES-256-CBC decrypt → FLAG
```

## Script de solve complet

Voir `solve/solve.py`
