# Runbook : reproduction pas à pas (Clop, MT19937/GetTickCount)

## A. Acquisition

```bash
h=389e03b1a1fd1c527d48df74d3c26a0483a5b105f36841193172f1ee80e62c1b
curl -s -X POST https://mb-api.abuse.ch/api/v1/ -H "Auth-Key: $(cat .mb_api_key)" \
  -d "query=get_file&sha256_hash=$h" -o sample.zip
7z x -pinfected sample.zip
sha256sum $h.exe
file $h.exe
```
Retour : `PE32 executable for MS Windows 4.00 (GUI), Intel i386, 3 sections`, hash conforme.

## B. Triage import PE : pourquoi ce n'est pas le payload

```bash
python3 -c "
import pefile
pe = pefile.PE('$h.exe', fast_load=True); pe.parse_data_directories()
for e in pe.DIRECTORY_ENTRY_IMPORT:
    print(e.dll.decode(), [i.name.decode() if i.name else i.ordinal for i in e.imports])
"
```
Retour : aucun import CryptoAPI (`ADVAPI32.dll`/`CRYPT32.dll` absents), `GetTickCount` seule fonction temporelle/aléa présente. Indice que la génération de clé, si elle existe, est artisanale et encore chiffrée/compressée à ce stade.

## C. Décompilation Ghidra headless (PyGhidra)

```bash
pip install /opt/ghidra/Ghidra/Features/PyGhidra/pypkg/dist/pyghidra-3.1.0-py3-none-any.whl
python3 - <<'EOF'
import pyghidra
pyghidra.start(install_dir="/opt/ghidra")
from ghidra.app.decompiler import DecompInterface
from ghidra.util.task import ConsoleTaskMonitor
with pyghidra.open_program("389e03b1....exe", analyze=True) as flat_api:
    # xref sur GetTickCount, decompilation des fonctions appelantes
    ...
EOF
```
Retour : `FUN_00401000` (appelée depuis `main`) fait `VirtualAlloc` + une boucle de décodage XOR/ROL9/soustraction d'un blob embarqué (`&DAT_0040831c`, 0x564 DWORD, clé `DAT_00408318`), puis saute dedans. `GetTickCount` ici n'alimente rien : anti-sandbox isolé (voir clop-mt19937-killchain.md §2).

## D. Rejouer le décodage de l'étage 0, identifier l'étage 1

```bash
python3 - <<'EOF'
import pefile, struct
# lire DAT_00408318 (cle) et &DAT_0040831c (blob), appliquer
# ((in^cle) rol 9 ^cle) - index sur 0x564 DWORD, ecrire stage2_decoded.bin
EOF
r2 -a x86 -b 32 -q -c "pd 60" -n stage2_decoded.bin
```
Retour : code x86 valide (pas du bruit), construction de chaînes sur la pile pour résoudre dynamiquement `GetProcAddress`/`VirtualAlloc`/`VirtualProtect`/`LoadLibraryA`/`VirtualFree`/`VirtualQuery`/`TerminateThread`. Confirme un reflective PE loader.

## E. Décompilation de l'étage 1, découverte du second blob et de la décompression aPLib

Décompiler `stage2_decoded.bin` (même méthode PyGhidra que C, base 0, langage `x86:LE:32:default`) donne la fonction principale complète : lecture d'un contexte (`hKernel32`, pointeur vers un blob à `0x004098b0`, taille `0x19ed8`, clé XOR à `0x004098ac`, taille destination à `0x00423788`), dé-entrelacement (saute 2 octets sur 3), même transformation XOR/ROL9/soustraction, puis un appel à une fonction dont la structure (lecteur de bits MSB, décodeur de longueur gamma, seuils de distance 31999/0x4ff/0x80) est celle de l'algorithme **aPLib** publié.

Portage direct en Python (`tools/aplib_depack.py`), puis pipeline complet (`tools/unpack_clop.py`) :

```bash
python3 tools/unpack_clop.py 389e03b1....exe -o clop_unpacked.bin
```
Retour :
```
132096 octets ecrits dans clop_unpacked.bin
MZ ? True
SHA256 : f59e2dde0fc19129329b3e950e27f4107536c5538c6413e7004c653c3b342941
```

## F. Confirmation indépendante du déballage

```bash
curl -s -X POST https://mb-api.abuse.ch/api/v1/ -H "Auth-Key: $(cat .mb_api_key)" \
  -d "query=get_info&hash=389e03b1a1fd1c527d48df74d3c26a0483a5b105f36841193172f1ee80e62c1b"
```
Champ `vendor_intel.UnpacMe` : deux hashs listés, dont `f59e2dde0fc19129329b3e950e27f4107536c5538c6413e7004c653c3b342941`, **identique** au résultat de l'étape E obtenu indépendamment. `vendor_intel.ReversingLabs` : `Win32.Ransomware.ClopCrypt`, MALICIOUS, 24/29 (82,76 %).

## G. Confirmation MT19937 sur le payload déballé

```bash
python3 -c "
import struct
data = open('clop_unpacked.bin','rb').read()
for name, val in [('matrix_A',0x9908b0df), ('init_mult',0x6c078965)]:
    print(name, data.count(struct.pack('<I', val)))
"
```
Retour : `matrix_A` x1, `init_mult` x5. Décompilation de `FUN_00403940`/`FUN_00403840` (mêmes outils qu'en C) : `init_genrand`/`genrand_int32` standard, sans variation. `FUN_00402b20` : seed `GetTickCount()` (une fois par valeur de tick distincte), tirage `genrand_int32() % range + min`. `FUN_00402d10` : 117 tirages `FUN_00402b20(0, 0x100)`, indexation d'une table de substitution, repli sur une clé statique si les premiers octets sont nuls (voir clop-mt19937-killchain.md §3/§5).

## H. Confirmation RC4 + enveloppe RSA

Décompilation de `FUN_004032f0` (KSA), `FUN_00403270` (PRGA) : RC4 standard sans variante. `FUN_00401420` : `CryptEncrypt` sur un handle RSA importé via `CryptImportPublicKeyInfo`/`CryptDecodeObjectEx`, la clé de 117 octets n'est jamais transmise à la CryptoAPI pour être générée, seulement pour être enveloppée après coup (voir clop-mt19937-killchain.md §4).

## I. PoC de récupération par brute-force

```bash
python3 tools/mt19937_key_poc.py
```
Retour : simulation d'un seed `GetTickCount()`, chiffrement d'un texte de test avec la clé réellement produite pour ce seed, brute-force sur une fenêtre de 100 001 candidats (20,15 s, ~4 960 candidats/s en Python pur mono-cœur), seed et fichier en clair retrouvés à l'identique. Détail et mise en garde sur la portée du PoC : voir clop-mt19937-killchain.md §8 et §9.

## J. YARA

Règles dans `clop_mt19937.yar` : IOC sur les deux hashs (stub + payload déballé) et signature structurelle sur les constantes MT19937 + la taille de clé 0x75, validées sur l'échantillon de ce dossier.

## K. Validation bit-exacte via Unicorn (vrai code machine, pas la transcription)

```bash
python3 tools/validate_mt19937_unicorn.py clop_unpacked.bin
```
Exécute réellement `FUN_00403940`/`FUN_00403840`/`FUN_00402b20`/`FUN_004032f0`/`FUN_00403270` du payload déballé (PE32 i386, cdecl), avec uniquement `GetTickCount` hooké (patch du slot IAT vers un stub `ret` dont Unicorn fixe la valeur de retour). Retour :

```
6/6 etats internes (624 mots) bit-exact.
2600/2600 tirages 32 bits bit-exact (650 tirages/seed, dont la torsion #2).
appel 1/2/3 (cache de seed sur tick) : OK
8/8 paires KSA+PRGA bit-exact.
TOUT CONFIRME bit-exact contre le vrai code machine du payload deballe.
```
Détail et portée de cette validation : voir clop-mt19937-killchain.md §7.
