Skip to content

Nanomites

Les sauts conditionnels sont remplacés par des points d'arrêt INT3 tandis qu'un processus débogueur parent détient une table associant chaque adresse à la cible et à la condition réelles du saut, corrigeant l'exécution à chaque exception de débogage.

Les nanomites sont une technique anti-dump et anti-altération popularisée par le protecteur Armadillo. Le protecteur retire les sauts conditionnels du programme et remplace chacun par un unique octet INT3 (0xCC). Le processus s'exécute sous son propre « débogueur » parent, qui conserve une table associant chaque adresse de nanomite à la cible, à la taille et à la condition réelles du saut. Chaque fois que l'enfant atteint un 0xCC implanté, une exception de débogage est remise au parent, qui consulte la table, évalue la condition à partir des drapeaux de l'enfant et reprend l'enfant soit à la suite, soit à la cible du saut. Détachez ou tuez le parent et l'enfant plante immédiatement sur le premier 0xCC, si bien qu'un simple dump mémoire est non fonctionnel.

Fonctionnement

Le branchement a disparu de l'enfant ; seuls un point d'arrêt et une entrée de table subsistent :

text
original child code:            after nanomite protection:
    cmp  eax, ebx                   cmp  eax, ebx
    jz   0x00401080                 int3            ; 0xCC nanomite (1 byte)
    ...                             ...

parent debugger holds a table:
  nanomite[0] = { addr: 0x00401055, type: JZ,
                  taken_target: 0x00401080, size: 6, fallthrough: 0x0040105B }

on EXCEPTION_BREAKPOINT at 0x00401055:
  if (child.EFLAGS.ZF) child.EIP = 0x00401080;   // jump taken
  else                 child.EIP = 0x0040105B;    // fall through
  ContinueDebugEvent(...);

Le flux de contrôle réel réside entièrement dans la table du parent ; les octets de l'enfant sont délibérément incomplets.

Détection & contournement

  • Static — Le corps .text est parsemé d'octets 0xCC isolés qui interrompent un code par ailleurs normal, et le binaire s'auto-débogue (un parent crée l'enfant avec DEBUG_PROCESS / DbgUiConnectToDbg). Detect It Easy et les scans de signatures repèrent les protecteurs de type Armadillo ; une forte densité de INT3 d'un seul octet au milieu d'une fonction est l'indice.
  • Dynamic — Vous ne pouvez pas simplement attacher votre propre débogueur car le protecteur exige d'être le seul débogueur ; tenter de le faire déclenche l'anti-débogage. Analysez plutôt le gestionnaire d'exceptions du parent pour voir comment il lit la table et corrige EIP/les drapeaux, et localisez la table de nanomites dans la mémoire du parent (souvent un blob chiffré déchiffré au démarrage).
  • Rebuild — Extrayez la table de nanomites du parent (adresse, type de condition, cibles prise/non prise par entrée), puis pour chaque 0xCC de l'enfant reconstruisez le saut conditionnel d'origine et réinjectez-le dans le dump, rétablissant le flux de contrôle réel. Lorsque le format de la table est opaque, émulez la logique de correction du parent pour récupérer chaque décision de branchement et reconstruire les sauts par programme. C'est l'une des tâches de décompactage les plus laborieuses.
  • Tools — x64dbg avec scripting personnalisé pour dumper et parcourir la table, un émulateur basé sur Unicorn pour rejouer les corrections d'exceptions du parent, et PE-bear pour réinjecter les sauts reconstruits dans l'image dumpée.
Votes

Commentaires(0)