Skip to content

Module Stomping (DLL Hollowing)

Charger une DLL signée bénigne dans un processus cible et écraser sa section de code avec du shellcode, de sorte que la mémoire malveillante soit adossée à un module légitime et échappe aux scanners de mémoire non adossée.

Le module stomping (aussi appelé DLL hollowing) contourne le plus grand révélateur de la plupart des techniques d'injection — la mémoire privée, exécutable et non adossée. Au lieu d'allouer de la mémoire RWX neuve, l'injecteur charge une vraie DLL signée, par ailleurs inutilisée, dans la cible, puis écrase la section .text de ce module avec du shellcode via WriteProcessMemory. Le code malveillant réside désormais à l'intérieur d'un module légitimement mappé, adossé à une image et signé, de sorte que les scanners qui traquent les régions exécutables non adossées ne voient rien d'anormal.

Fonctionnement

L'attaquant choisit une DLL bénigne que la cible n'utilise pas réellement, la force à se charger (localement ou à distance, p. ex. via LoadLibrary dans la cible), localise la région .text du module, la rend accessible en écriture, et écrase le code d'origine avec le shellcode. L'exécution est ensuite dirigée vers le code écrasé (thread distant, APC, ou un thread détourné pointé vers le décalage écrasé).

text
LoadLibrary("benign_signed.dll")           // map a real signed module in target
base = GetModuleHandle("benign_signed.dll")
VirtualProtectEx(hProc, base+textRVA, len, PAGE_EXECUTE_READWRITE, &old)
WriteProcessMemory(hProc, base+textRVA, shellcode, len)  // stomp .text
VirtualProtectEx(hProc, base+textRVA, len, PAGE_EXECUTE_READ, &old)
CreateRemoteThread(hProc, NULL, 0, base+textRVA, arg, 0, NULL)  // run stomped code

Détection & contournement

  • Statique — L'injecteur importe toujours WriteProcessMemory et VirtualProtectEx aux côtés de LoadLibrary/GetModuleHandle. L'indice statique distinctif est l'absence de VirtualAllocEx pour la région de code — la cible du shellcode est une base de module existante plutôt qu'une allocation neuve. Des noms de DLL bénignes codés en dur que le processus n'a aucune raison d'utiliser peuvent indiquer l'hôte choisi pour le stomping.
  • Dynamique — Surveillez un WriteProcessMemory dont la destination tombe à l'intérieur de la plage d'image d'un module mappé (et non en mémoire privée), souvent encadré par un VirtualProtectEx faisant basculer le code de ce module en écriture puis de nouveau en exécution. Un thread distant ou un APC démarrant à l'intérieur d'un module signé mais à un décalage non-export, en plein .text, est suspect.
  • Forensique mémoire — La région est adossée à une image et signée, donc les analyses de mémoire non adossée la manquent ; le révélateur est une désynchronisation d'octets image/disque. Moneta et pe-sieve comparent les pages du module en mémoire à la DLL sur disque et signalent un code modifié / une désynchronisation de hash dans le .text du module écrasé. Recherchez des pages privées+exécutables ou modifiées au sein d'un module mappé et nommé par ailleurs.
  • Outils — pe-sieve (/imp, détection de code modifié), Moneta (drapeaux image modifiée / privé-dans-mappé), Process Hacker (inspection de la mémoire des modules), API Monitor (cibles de WriteProcessMemory/VirtualProtectEx), Sysmon/ETW et Volatility (ldrmodules + comparaison de hash de pages avec le disque).
Votes

Commentaires(0)