Skip to content
Packing & Cryptersintermediate

Runtime Crypter Stub

Un crypter encapsule une charge utile chiffrée et un petit stub qui, à l'exécution, déchiffre le code d'origine en mémoire et lui transfère l'exécution, si bien que l'antivirus statique ne voit que le stub et un blob à forte entropie.

Un crypter est un packer dont le but est l'évasion de signatures plutôt que la compression. Il assemble deux parties : une copie chiffrée de la charge utile réelle (RC4, AES ou un XOR glissant) et un petit stub de chargement. À l'exécution, le stub déchiffre intégralement la charge utile en mémoire et l'exécute sur place ou l'injecte dans un processus fraîchement créé. Sur le disque, un moteur antivirus ne voit qu'un code de stub d'apparence anodine suivi d'un bloc opaque à forte entropie, si bien que les signatures d'octets du malware d'origine ne correspondent jamais.

Fonctionnement

Le stub intègre (ou dérive) la clé, parcourt le texte chiffré, le déchiffre dans une région RWX nouvellement allouée, puis transfère le contrôle. Une variante RC4 typique :

c
// stub: decrypt the embedded payload in memory, then run it
BYTE  *blob = payload_rva;          // encrypted payload appended to the stub
SIZE_T len  = payload_size;
BYTE   key[16] = { 0x9A, 0x3C, /* ... */ };  // hard-coded or runtime-derived

void *EOF
cat >> /Users/florianamette/code/reverse-engineering/content/techniques/fr/runtime-crypter.md <<'EOF'
mem = VirtualAlloc(NULL, len, 0x3000 /*COMMIT|RESERVE*/, 0x40 /*RWX*/);
memcpy(mem, blob, len);
rc4(mem, len, key, sizeof key);     // in-place decrypt of the real payload

// run in place (call OEP) ... or hollow a fresh process and write it there
((void(*)())mem)();

Les octets déchiffrés forment un PE complet (mappé manuellement) ou un shellcode indépendant de la position. Beaucoup de crypters enveloppent cela dans du process hollowing : créer un processus légitime suspendu, NtUnmapViewOfSection, écrire l'image déchiffrée, corriger le point d'entrée et reprendre l'exécution.

Détection & contournement

  • Static — Une petite table d'imports ordinaire à côté d'une grande section dont l'entropie avoisine 7,9 bits/octet est révélatrice. Detect It Easy et un histogramme d'entropie manuel signalent le blob chiffré. Une boucle courte avec xor/rol sur un compteur, ou une permutation de 256 octets intégrée en cours de brassage (la KSA de RC4), désigne le chiffrement. La clé codée en dur est fréquemment une constante contiguë près de la boucle.
  • Dynamic — Posez un point d'arrêt sur VirtualAlloc/VirtualProtect et sur la transition vers la nouvelle région. Laissez la boucle de déchiffrement se terminer, puis lisez le tampon fraîchement écrit : la charge utile en clair (en-tête MZ, chaînes lisibles) apparaît juste avant le call/jmp qui y mène. Posez un point d'arrêt matériel sur le premier octet de l'allocation pour saisir le transfert exact.
  • Rebuild — Si vous avez récupéré la clé et l'algorithme, déchiffrez le blob hors ligne (recette RC4/XOR de CyberChef) pour obtenir une charge utile propre sans l'exécuter. Sinon, dumpez le texte en clair en mémoire avec pe-sieve ou Scylla une fois que le stub l'a déchiffré, puis reconstruisez l'IAT et corrigez l'en-tête PE pour obtenir un échantillon exécutable.
  • Tools — x64dbg (points d'arrêt sur l'allocation/la transition), pe-sieve et Scylla (dump mémoire de la charge utile déchiffrée), CyberChef (récupération du chiffrement hors ligne) et YARA exécuté contre l'image déchiffrée plutôt que contre le fichier packé.
Votes

Commentaires(0)