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é).
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 codeDétection & contournement
- Statique — L'injecteur importe toujours
WriteProcessMemoryetVirtualProtectExaux côtés deLoadLibrary/GetModuleHandle. L'indice statique distinctif est l'absence deVirtualAllocExpour 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
WriteProcessMemorydont 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 unVirtualProtectExfaisant 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
.textdu 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 deWriteProcessMemory/VirtualProtectEx), Sysmon/ETW et Volatility (ldrmodules+ comparaison de hash de pages avec le disque).