Dix techniques d’injection de processus : étude technique des techniques d’injection de processus courantes et émergentes
Note de la rédaction : Elastic a uni ses forces avec Endgame en octobre 2019, et a migré une partie du contenu du blog Endgame vers elastic.co/fr/. Consultez Elastic Security pour en savoir plus sur nos solutions de sécurité intégrées.
L’injection de processus est une technique d’évasion de défense largement et souvent utilisée dans le domaine des logiciels malveillants et des adversaires sans fichiers, et consiste à exécuter du code personnalisé dans l’espace d’adressage d’un autre processus. L’injection par procédé améliore la discrétion, et certaines techniques atteignent également la persistance. Bien qu’il existe de nombreuses techniques d’injection de procédés, cet article présente dix techniques observées dans la nature, qui exécutent du code malveillant pour un autre procédé. Je fournis également des captures d’écran pour nombre de ces techniques afin de faciliter l’ingénierie inverse et l’analyse de malwares, aidant ainsi à la détection et à la défense contre ces techniques courantes.
1. INJECTION CLASSIQUE DE DLL VIA CREATEREMOTETHREAD ET LOADLIBRARY
Cette technique est l’une des plus couramment utilisées pour injecter des logiciels malveillants dans un autre processus. Le malware écrit le chemin vers sa bibliothèque de liens dynamiques malveillants (DLL) dans l’espace d’adressage virtuel d’un autre processeur, et s’assure que le processus distant le charge en créant un thread distant dans le processus cible.

Le malware doit d’abord cibler un processus d’injection (par exemple svchost.exe). Cela se fait généralement en recherchant dans les processus en appelant un trio d’interfaces de programme d’application (API) : CreateToolhelp32Snapshot, Process32First et Process32Next. CreateToolhelp32Snapshot est une API utilisée pour énumérer les états du tas ou du module d’un processus spécifié ou de tous les processus, et elle renvoie un instantané. Process32First récupère des informations sur le premier processus dans l’instantané, puis Process32Next est utilisé dans une boucle pour les parcourir. Après avoir trouvé le processus cible, le malware prend le contrôle du processus cible en appelant OpenProcess.
Comme montré sur l’illustration 1, le malware appelle VirtualAllocEx pour avoir un espace afin d’écrire le chemin vers sa DLL. Le logiciel malveillant appelle alors WriteProcessMemory pour écrire le chemin dans la mémoire allouée. Enfin, pour que le code soit exécuté dans un autre processus, le malware appelle des API telles que CreateRemoteThread, NtCreateThreadEx ou RtlCreateUserThread. Les deux dernières ne sont pas documentées. Cependant, l’idée générale est de transmettre l’adresse de LoadLibrary à l’une de ces API afin qu’un processus distant doive exécuter la DLL au nom du malware.
CreateRemoteThread est suivi et signalé par de nombreux produits de sécurité. De plus, il nécessite une DLL malveillante sur le disque qui pourrait être détectée. Étant donné que les attaquants injectent le plus souvent du code pour contourner les défenses, les attaquants sophistiqués n’utiliseront probablement pas cette approche. La capture d’écran ci-dessous montre un malware nommé Rebhip en train d’appliquer cette technique.

Sha256: 07b8f25e7b536f5b6f686c12d04edc37e11347c8acd5c53f98a174723078c365
2. INJECTION EXÉCUTABLE PORTABLE (INJECTION PE)
Au lieu de transmettre l’adresse de la LoadLibrary, un malware peut copier son code malveillant dans un processus ouvert existant et provoquer son exécution (soit via un petit shellcode, soit en appelant CreateRemoteThread). Un avantage de l’injection PE par rapport à la technique LoadLibrary est que le malware n’a pas besoin de déposer une DLL malveillante sur le disque. Similaire à la première technique, le malware alloue de la mémoire dans un processus hôte (par exemple VirtualAllocEx), et au lieu d’écrire un « chemin DLL », il écrit son code malveillant en appelant WriteProcessMemory. Cependant, l’obstacle avec cette approche est le changement de l’adresse de base de l’image copiée. Lorsqu’un malware injecte son PE dans un autre processus, il aura une nouvelle adresse de base imprévisible, l’obligeant à recalculer dynamiquement les adresses fixes de son PE. Pour surmonter cela, le malware doit trouver l’adresse de sa table de relocalisation dans le processus hôte, et résoudre les adresses absolues de l’image copiée en bouclant ses descripteurs de relocalisation.

Cette technique est similaire à d’autres techniques, telles que l’injection réfléchissante de DLL et le module mémoire, puisqu’ils ne déposent aucun fichier sur le disque. Cependant, les approches d’injection par module mémoire et DLL réfléchissante sont encore plus discrètes. Ils ne dépendent d’aucune API Windows supplémentaire (par exemple, CreateRemoteThread ou LoadLibrary), car ils se chargent et s’exécutent eux-mêmes en mémoire. L’injection de DLL réfléchissante fonctionne en créant une DLL qui s’emporte en mémoire lors de son exécution, au lieu de dépendre du chargeur de la fenêtre. Le module mémoire est similaire à l’injection de DLL réfléchissante, sauf que l’injecteur ou le chargeur est responsable de mapper la DLL cible en mémoire plutôt que la DLL elle-même. Dans un précédent article de blog, ces deux approches en mémoire ont été largement discutées.
Lors de l’analyse de l’injection de PE, il est très courant de voir des boucles (généralement deux boucles « for », l’une imbriquée dans l’autre), avant un appel à CreateRemoteThread. Cette technique est très populaire parmi les crypteurs (logiciels qui chiffrent et masquent les logiciels malveillants). Dans l’illustration 2, le test unitaire d’échantillon tire parti de cette technique. Le code possède deux boucles imbriquées pour ajuster sa table de relocalisation, visibles avant les appels vers WriteProcessMemory et CreateRemoteThread. L’instruction « and 0x0fff » est également un autre bon indicateur, montrant que les 12 premiers bits servent à obtenir le décalage dans l’adresse virtuelle du bloc de relocalisation qui le contient. Maintenant que le malware a recalculé toutes les adresses nécessaires, il ne lui reste plus qu’à transmettre son adresse de départ à CreateRemoteThread et qu’il soit exécuté.

Sha256: ce8d7590182db2e51372a4a04d6a0927a65b2640739f9ec01cfd6c143b1110da
3. CREUSEMENT DE PROCÉDÉ (AUSSI APPELÉ REMPLACEMENT DE PROCÉDÉ ET RUNPE)
Au lieu d’injecter du code dans un programme hôte (par exemple, injection de DLL), les malwares peuvent effectuer une technique appelée vidage de processus. Le vidage des processus se produit lorsqu’un malware démappe (creuse) le code légitime de la mémoire du processus cible, et écrase l’espace mémoire du processus cible (par exemple, svchost.exe) avec un exécutable malveillant.

Le malware crée d’abord un nouveau processus pour héberger le code malveillant en mode suspendu. Comme montré sur l’illustration 3, cela se fait en appelant CreateProcess et en définissant le drapeau de création de processus sur CREATE_SUSPENDED (0x00000004). Le thread principal du nouveau processus est créé en état suspendu et ne s’exécute que lorsque la fonction ResumeThread est appelée. Ensuite, le malware doit remplacer le contenu du fichier légitime par sa charge utile malveillante. Cela se fait en démappant la mémoire du processus cible en appelant soit ZwUnmapViewOfSection soit NtUnmapViewOfSection. Pour schématiser, ces deux API libèrent toute la mémoire pointée par une section. Maintenant que la mémoire est démappée, le chargeur effectue VirtualAllocEx pour allouer de la nouvelle mémoire au malware, et utilise WriteProcessMemory pour écrire chacune des sections du malware dans l’espace de traitement cible. Le malware appelle SetThreadContext pour orienter le point d’entrée vers une nouvelle section de code qu’il a écrite. À la fin, le malware reprend le thread suspendu en appelant ResumeThread pour sortir le processus de l’état suspendu.

Sha256: eae72d803bf67df22526f50fc7ab84d838efb2865c27aef1a61592b1c520d144
4. DÉTOURNEMENT D’EXÉCUTION DE THREAD (ÉGALEMENT APPELÉ SUSPENDRE, INJECTER ET REPRENDRE (SIR))
Cette technique présente certaines similitudes avec la technique de creusement du procédé précédemment évoquée. Dans le détournement d’exécution de threads, un malware cible un thread existant d’un processus et évite tout processus bruyant ou toute opération de création de thread bruyante. Ainsi, lors de l’analyse, vous verrez probablement des appels vers CreateToolhelp32Snapshot et Thread32First, suivis d’OpenThread.

Après avoir obtenu un handle du thread cible, le malware met le thread en mode suspendu en appelant SuspendThread pour effectuer son injection. Le malware appelle VirtualAllocEx et WriteProcessMemory pour allouer la mémoire et effectuer l’injection de code. Le code peut contenir du shellcode, le chemin vers la DLL malveillante et l’adresse de LoadLibrary.
L’illustration 4 montre un cheval de Troie générique utilisant cette technique. Pour détourner l’exécution du thread, le malware modifie le registre EIP (un registre contenant l’adresse de l’instruction suivante) du thread ciblé en appelant SetThreadContext. Ensuite, le malware reprend le thread pour exécuter le shellcode qu’il a écrit sur le processus hôte. Du point de vue de l’attaquant, l’approche SIR peut poser problème car suspendre et reprendre un thread en plein appel système peut provoquer le plantage du système. Pour éviter cela, un malware plus sophistiqué reprendrait et réessayerait plus tard si le registre EIP se trouve dans la plage de NTDLL.dll.

Sha256: 787cbc8a6d1bc58ea169e51e1ad029a637f22560660cc129ab8a099a745bd50e
5. INJECTION DE HOOK VIA SETWINDOWSHOOKEX
Le hooking est une technique utilisée pour intercepter des appels de fonction. Les malwares peuvent exploiter la fonctionnalité de hooking pour charger leur DLL malveillant lorsqu’un événement est déclenché dans un fil spécifique. Cela se fait généralement en appelant SetWindowsHookEx pour installer une routine de hooking dans la chaîne de hooks. La fonction SetWindowsHookEx prend quatre arguments. Le premier argument concerne le type d’événement. Les événements reflètent la gamme des types de hooks, et varient de l’appui sur les touches du clavier (WH_KEYBOARD) aux entrées de la souris (WH_MOUSE), de la TCC, etc. Le second argument est un pointage vers la fonction que le malware souhaite invoquer lors de l’exécution de l’événement. Le troisième argument est un module qui contient la fonction. Ainsi, il est très courant de voir des appels vers LoadLibrary et GetProcAddress avant d’appeler SetWindowsHookEx. Le dernier argument à cette fonction est le fil auquel la procédure du hook doit être associée. Si cette valeur est réglée à zéro, tous les threads effectuent l’action lorsque l’événement est déclenché. Cependant, les malwares ciblent généralement un seul thread pour moins de bruit, il est donc aussi possible de voir les appels CreateToolhelp32Snapshot et Thread32Next avant SetWindowsHookEx pour trouver et cibler un seul thread. Une fois la DLL injectée, le malware exécute son code malveillant au nom du processus pour lequel son threadId a été transmis à la fonction SetWindowsHookEx. Sur l’illustration 5, Locky Ransomware met en œuvre cette technique.

Sha256: 5d6ddb8458ee5ab99f3e7d9a21490ff4e5bc9808e18b9e20b6dc2c5b27927ba1
6. INJECTION ET PERSISTANCE VIA MODIFICATION DU REGISTRE (PAR EXEMPLE APPINIT_DLLS, APPCERTDLLS, IFEO)
Appinit_DLL, AppCertDll et IFEO (Image File Execution Options) sont toutes des clés de registre utilisées par un malware à la fois pour l’injection et la persistance. Les inscriptions sont situées aux emplacements suivants :
HKLM\Software\Microsoft\Windows NT\CurrentVersion\Windows\Appinit_Dlls HKLM\Software\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Windows\Appinit_Dlls HKLM\System\CurrentControlSet\Control\Session Manager\AppCertDlls HKLM\Software\Microsoft\Windows NT\currentversion\image options d’exécution du fichier
AppInit_DLLs
Les logiciels malveillants peuvent insérer l’emplacement de leur bibliothèque malveillante sous la clé Appinit_Dlls registre pour qu’un autre processus charge leur bibliothèque. Chaque bibliothèque sous cette clé de registre est chargée dans chaque processus qui charge User32.dll. User32.dll est une bibliothèque très courante utilisée pour stocker des éléments graphiques tels que les boîtes de dialogue. Ainsi, lorsqu’un malware modifie cette sous-clé, la majorité des processus chargeront la bibliothèque malveillante. L’illustration 6 montre le cheval de Troie Ginwui s’appuyant sur cette approche pour l’injection et la persistance. Il ouvre simplement la clé du registre Appinit_Dlls en appelant RegCreateKeyEx, et modifie ses valeurs en appelant RegSetValueEx.

Sha256: 9f10ec2786a10971eddc919a5e87a927c652e1655ddbbae72d376856d30fa27c
AppCertDlls
Cette approche est très similaire à l’approche AppInit_DLLs, sauf que les DLL sous cette clé de registre sont chargées dans chaque processus appelant les fonctions API Win32 CreateProcess, CreateProcessAsUser, CreateProcessWithLogonW, CreateProcessWithTokenW et WinExec.
Options d’exécution de fichier image (IFEO)
IFEO est généralement utilisé à des fins de débuggage. Les développeurs peuvent définir la « Valeur de débuggage » sous cette clé de registre pour associer un programme à un autre exécutable pour le débogage. Ainsi, chaque fois que l’exécutable est lancé, le programme qui y est attaché sera lancé. Pour utiliser cette fonctionnalité, vous pouvez simplement donner le chemin vers le débogueur et l’attacher à l’exécutable que vous souhaitez analyser. Les logiciels malveillants peuvent modifier cette clé de registre pour s’injecter dans l’exécutable cible. Dans l’illustration 7, Diztakun met en œuvre cette technique en modifiant la valeur du débuggueur du Gestionnaire des tâches.

Sha256: f0089056fc6a314713077273c5910f878813fa750f801dfca4ae7e9d7578a148
7. INJECTION D’APC ET BOMBARDEMENT ATOMIQUE
Les logiciels malveillants peuvent profiter des appels de procédure asynchrone (APC) pour forcer un autre thread à exécuter leur code personnalisé en le rattachant à la file d’attente APC du thread cible. Chaque thread dispose d’une file d’attente de CPA qui attendent leur exécution lorsque le thread cible entre dans l’état altérable. Un thread entre en état d’alerte s’il appelle les fonctions SleepEx, SignalObjectAndWait, MsgWaitForMultipleObjectsEx, WaitForMultipleObjectsEx ou WaitForSingleObjectEx. Le malware recherche généralement tout thread en état modifiable, puis appelle OpenThread et QueueUserAPC pour mettre un APC en file d’attente vers un thread. QueueUserAPC prend trois arguments : 1) un handle vers le thread cible ; 2) un pointeur vers la fonction que le malware souhaite exécuter ; 3) et le paramètre qui est transmis au pointeur de fonction. Dans l’illustratoin 8, le malware Amanahe appelle d’abord OpenThread pour acquérir un handle d’un autre thread, puis appelle QueueUserAPC avec LoadLibraryA comme pointeur de fonction pour injecter sa DLL malveillante dans un autre thread.
L’atomBombing est une technique introduite pour la première fois par la recherche enSilo, puis utilisée dans Dridex V4. Comme nous l’avons vu en détail dans un article précédent, la technique repose également sur l’injection de CPA. Cependant, il utilise des tables d’atomes pour écrire en mémoire un autre processus.

Sha256: f74399cc0be275376dad23151e3d0c2e2a1c966e6db6a695a05ec1a30551c0ad
8. INJECTION DE MÉMOIRE DE FENÊTRE SUPPLÉMENTAIRE (EWMI) VIA SETWINDOWLONG
EWMI repose sur l’injection dans la mémoire de fenêtres supplémentaires du bac de l’Explorateur, et a été utilisé plusieurs fois parmi des familles de malwares telles que Gapz et PowerLoader. Lors de l’enregistrement d’une classe fenêtre, une application peut spécifier un certain nombre d’octets supplémentaires de mémoire, appelés mémoire de fenêtre supplémentaire (EWM). Cependant, il n’y a pas beaucoup de place dans l’EWM. Pour contourner cette limitation, le malware écrit du code dans une section partagée de explorer.exe, et utilise SetWindowLong et SendNotifyMessage pour disposer d’un pointeur de fonction pointant vers le shellcode, puis l’exécuter.
Le malware a deux options pour écrire dans une section partagée. Il peut soit créer une section partagée et la faire mapper à la fois à elle-même et à un autre processus (par exemple, explorer.exe), soit simplement ouvrir une section partagée déjà existante. La première a la surcharge d’allouer l’espace du tas et d’appeler NTMapViewOfSection en plus de quelques autres appels API, donc la seconde approche est plus souvent utilisée. Après que le malware ait écrit son shellcode dans une section partagée, il utilise GetWindowLong et SetWindowLong pour accéder et modifier la mémoire de fenêtre supplémentaire de « Shell_TrayWnd ». GetWindowLong est une API utilisée pour récupérer la valeur de 32 bits au décalage spécifié dans la mémoire de fenêtre supplémentaire d’un objet de classe fenêtre, et SetWindowLong est utilisé pour modifier les valeurs au décalage spécifié. En procédant ainsi, le malware peut simplement modifier le décalage d’un pointeur de fonction dans la classe fenêtre, et le pointer vers le shellcode écrit dans la section partagée.
Comme pour la plupart des autres techniques mentionnées ci-dessus, le malware doit déclencher le code qu’il a écrit. Dans les techniques déjà évoquées, les logiciels malveillants y parvenaient en appelant des API telles que CreateRemoteThread, QueueUserAPC ou SetThreadContext. Avec cette approche, le malware déclenche plutôt le code injecté en appelant SendNotifyMessage. Lors de l’exécution de SendNotifyMessage, Shell_TrayWnd reçoit et transfère le contrôle à l’adresse pointée par la valeur précédemment définie par SetWindowLong. Dans l’illustration 9, un malware nommé PowerLoader utilise cette technique.


Sha256: 5e56a3c4d4c304ee6278df0b32afb62bd0d01e2a9894ad007f4cc5f873ab5cf
9. INJECTION À L’AIDE DE CALES
Microsoft fournit des cales aux développeurs principalement pour la rétrocompatibilité. Les cales permettent aux développeurs d’appliquer des correctifs à leurs programmes sans avoir à réécrire le code. En utilisant les cales (shims), les développeurs peuvent indiquer au système d’exploitation comment gérer leur application. Les cales sont en fait un moyen de s’accrocher à des API et de cibler des exécutables spécifiques. Les malwares peuvent exploiter les cales pour cibler un exécutable à la fois pour la persistance et l’injection. Windows exécute le Shim Engine lorsqu’il charge un binaire pour vérifier la présence de bases de données de shimming afin d’appliquer les correctifs appropriés.
Il existe de nombreux correctifs applicables, mais les préférés des malwares sont ceux qui sont en partie liés à la sécurité (par exemple, DisableNX, DisableSEH, InjectDLL, etc.). Pour installer une base de données de shimming, les malwares peuvent déployer différentes approches. Par exemple, une approche courante consiste simplement à exécuter sdbinst.exe et à le diriger vers le fichier SD malveillant. Dans l’illustration 10, un adware, « Search Protect by Conduit », utilise une cale pour la persistance et l’injection. Il effectue une cale « InjectDLL » dans Google Chrome pour charger vc32loader.dll. Il existe quelques outils pour analyser les fichiers sdb, mais pour l’analyse des fichiers sdb listés ci-dessous, j’ai utilisé python-sdb.

Sha256: 6d5048baf2c3bba85adc9ac5ffd96b21c9a27d76003c4aa657157978d7437a20
10. HOOK IAT ET HOOK EN LIGNE (AUSSI APPELÉS ROOTKITS USERLAND)
Le hooking IAT et le hook en ligne sont généralement appelés rootkits userland. Le hooking IAT est une technique utilisée par un malware pour modifier la table d’adresses d’importation. Lorsqu’une application légitime appelle une API située dans une DLL, la fonction remplacée est exécutée à la place de l’originale. En revanche, avec le hooking en ligne, le malware modifie la fonction API elle-même. Dans l’illustration 11, le malware FinFisher effectue un hooking IAT en modifiant l’emplacement du CreateWindowEx.

Sha256: f827c92fbe832db3f09f47fe0dcaafd89b40c7064ab90833a1f418f2d1e75e8e
CONCLUSION
Dans cet article, j’ai abordé dix techniques différentes utilisées par un malware pour masquer son activité dans un autre processus. En général, un malware injecte directement son shellcode dans un autre processus ou force un autre processus à charger sa bibliothèque malveillante. Dans le tableau 1, j’ai classé les différentes techniques et fourni des échantillons servant de référence pour observer chaque technique d’injection abordée dans cet article. Les chiffres inclus tout au long de l’article aideront le chercheur à reconnaître les différentes techniques pour inverser les logiciels malveillants.

Les attaquants et chercheurs découvrent régulièrement de nouvelles techniques pour obtenir l’injection et assurer la discrétion. Cet article détaille dix techniques courantes et émergentes, mais il en existe d’autres, comme le détournement COM. La mission de détection des défenseurs ne sera jamais « terminée », de même qu’ils tenteront toujours d’empêcher l’injection furtive de procédés, car les adversaires ne cesseront jamais d’innover.
Chez Endgame, nous recherchons constamment des techniques avancées d’infiltration et intégrons des protections dans notre produit. Nous superposons des capacités qui détectent les DLL malveillantes qui se chargent avec une certaine persistance (comme les DLL AppInit, les détournements COM, et plus encore), empêchent de nombreuses formes d’injection de code en temps réel grâce à notre protection brevetée contre l’injection de shellcode, et détectent les charges utiles injectées malveillantes fonctionnant en mémoire délivrées via l’une des techniques ci-dessus via nos techniques de détection d’attaques sans fichiers brevetées. Cette approche permet à notre plateforme d’être plus efficace que tout autre produit sur le marché pour se protéger contre l’injection de code, tout en maximisant la résilience face au contournement grâce aux techniques émergentes d’injection de code.