L'injection de processus est l'une des techniques les plus importantes en matière de cybersécurité. Cette technique consiste à déposer du code dans l'espace d'adressage d'un autre processus déjà en cours d'exécution et à exécuter le code dans cet espace. Il s'agit d'un véritable désastre du point de vue de la sécurité, car cela permet au code de s'exécuter sous les autorisations du processus cible, qui peut être en mesure de contourner les contrôles de sécurité en utilisant l'escalade de privilèges existante du processus cible, les mécanismes de détection, etc.
L'injection de processus est un vecteur de menace qui a donné naissance à de nombreuses formes de logiciels malveillants infestant l'internet et menaces persistantes avancées (APT). Bien qu'il s'agisse d'une technique valable dans un environnement de développement logiciel pour déboguer ou étendre une application, elle est souvent utilisée par les acteurs malveillants pour exécuter du code sans autorisation, échapper à la persistance et rester indétectables.
Ce blog analyse les principes de l'injection de processus, ses mécanismes fondamentaux, les techniques courantes, les méthodes de détection et les moyens de la prévenir. Nous explorerons également certains principes fondamentaux, tels que les opérations mémoire, les techniques d'injection, les méthodes de détection et des exemples pratiques d'attaques.
Qu'est-ce que l'injection de processus ?
L'injection de processus permet d'injecter un code dans l'espace mémoire d'un autre processus en cours d'exécution. Dans cette technique, l'attaquant force le processus cible à exécuter un code arbitraire en écrivant son propre code dans l'espace d'adressage de ce processus. Le code injecté s'exécute dans le contexte et avec les droits du processus vulnérable, héritant ainsi de tous ses droits d'accès et de son niveau de confiance sur le système.
L'injection de processus repose essentiellement sur les composants techniques suivants : acquisition du descripteur de processus, allocation de mémoire dans le processus cible, opérations d'écriture de code et mécanismes de déclenchement de l'exécution. Elle utilise des fonctions API Windows telles que OpenProcess(), VirtualAllocEx(), WriteProcessMemory() et CreateRemoteThread() pour exécuter le processus d'injection.
Pourquoi l'injection de processus est-elle dangereuse ?
Plusieurs aspects techniques rendent ce type d'attaque relativement dangereux. Le code exécuté à partir du thread injecté dispose des mêmes privilèges que le processus cible, ce qui se traduit concrètement par un accès privilégié au système. Cette méthode contourne tout scan de sécurité basé sur les fichiers, car le code non sécurisé n'existe que dans la mémoire.
Elle a également un effet néfaste sur la stabilité et la sécurité des systèmes. Les opérations d'injection peuvent être interrompues par les processus cibles et entraîner une instabilité dans l'ensemble du système. Pour ce faire, elles mettent fin aux processus des produits de sécurité, volent des données dans les applications protégées et établissent un accès persistant au système qui échappe aux techniques de nettoyage courantes.
Principes fondamentaux de la mémoire des processus
La base technique des techniques d'injection de processus réside dans la compréhension des structures et des opérations de la mémoire des processus. Le modèle de gestion de la mémoire du système d'exploitation Windows comporte des fonctionnalités internes qui permettent et limitent également les interactions et l'accès à la mémoire entre les processus. Elles modifient instantanément le fonctionnement de l'injection de processus et la manière dont les défenseurs peuvent la détecter et s'en protéger.
Mémoire virtuelle et espace d'adressage des processus
Chaque processus Windows dispose de son propre espace d'adressage virtuel, isolé des autres processus s'exécutant sur le même système. La plage de cet espace d'adressage virtuel est comprise entre 0 et 0x7FFFFFFF pour les processus 32 bits et entre 0 et 0x7FFFFFFFFFF pour les processus 64 bits. Le mappage des adresses virtuelles vers les emplacements de mémoire physique est effectué à l'aide de la technique de pagination par le gestionnaire de mémoire Windows.
Le processus comporte plusieurs régions dans son espace d'adressage, telles que le code exécutable du processus, les DLL chargées, les allocations de tas et l'espace de pile. Ces régions ont des fonctions et des types de données spécifiques. Windows dispose de tables de pages qui décrivent l'emplacement des pages de cadres mémoire et indiquent si elles se trouvent dans l'espace d'adressage virtuel.
Autorisations et protection de la mémoire
Il existe des autorisations d'accès aux régions de mémoire, qui décrivent la manière dont les processus doivent interagir avec elles. Ces autorisations comprennent :
- PAGE_EXECUTE : La mémoire peut être exécutée en tant que code
- PAGE_READ : La mémoire peut être lue
- PAGE_WRITE : La mémoire peut être écrite
- PAGE_EXECUTE_READ : La mémoire peut être exécutée et lue
- PAGE_EXECUTE_READWRITE : La mémoire peut être exécutée, lue et écrite
Ces autorisations sont appliquées par le gestionnaire de mémoire Windows au niveau de la page. Si une application (ou un processus) tente d'accéder à la mémoire d'une manière non autorisée, le système génère une violation d'accès.
API Windows critiques pour les opérations mémoire
Windows dispose de quelques API importantes pour la manipulation de la mémoire. Ces API sont les éléments constitutifs de l'injection de processus. Les versions " Ex " de ces fonctions sont destinées aux processus externes, tandis que leurs successeurs classiques sont destinés à l'espace mémoire du processus appelant. La connaissance de ces API permet de détecter et de suivre les activités d'injection potentielles.
- VirtualAlloc/VirtualAllocEx : Réserve et engage de la mémoire dans un processus
- VirtualProtect/VirtualProtectEx : modifie les autorisations d'accès à la région mémoire
- ReadProcessMemory : Lit les données à partir de l'espace mémoire d'un autre processus
- WriteProcessMemory : Écrit des données dans l'espace mémoire d'un autre processus
- VirtualFree/VirtualFreeEx : Libère les régions de mémoire allouées
Types de techniques d'injection de processus
L'injection de processus comprend un certain nombre de techniques différentes qui utilisent toutes une forme d'exécution de code pour les processus cibles. Cette différence dans les appels API Windows et la manipulation de la mémoire crée des modèles de fonctionnement et des signatures de détection uniques pour chaque technique.
L'analyse de ces techniques peut aider les équipes de sécurité à identifier et à répondre à des méthodes d'injection spécifiques.
1. Injection de DLL
L'injection de DLL consiste à forcer un processus à charger des fichiers DLL malveillants. Elle utilise un ensemble de fonctions API : OpenProcess(), VirtualAllocEx() et CreateRemoteThread(). Elle commence par réserver de la mémoire dans le processus cible pour contenir le chemin d'accès à la DLL. Elle lance ensuite un thread distant qui appelle LoadLibrary() avec le chemin d'accès comme paramètre pour demander au processus cible de charger la DLL malveillante.
Une DLL injectée a un accès complet aux fonctions/processus cibles avec les adresses mémoire de l'ensemble de l'espace mémoire du processus cible et de tous les autres modules que la cible a chargés en mémoire.
2. Injection de code
L'injection de code est une forme d'attaque qui consiste à injecter du code malveillant dans l'espace mémoire d'un processus, où le code s'exécute. Il s'agit simplement d'écrire un code à l'adresse d'un espace mémoire de processus. Cette technique en plusieurs étapes consiste à obtenir un descripteur du processus, à utiliser VirtualAllocEx() pour allouer de la mémoire, WriteProcessMemory() pour écrire le code, puis enfin CreateRemoteThread() pour l'exécuter.
Le code qu'il exécute dispose des autorisations du processus cible dans lequel il s'exécute, et tous les privilèges de sécurité et droits d'accès seront hérités.
3. Détournement d'exécution de thread
Le détournement d'exécution de thread suspend un thread dans le processus cible, modifie son contexte d'exécution pour pointer vers le code de l'attaquant et poursuit l'exécution. Dans cette technique, l'attaquant utilise les API SuspendThread(), GetThreadContext() et SetThreadContext() et ResumeThread().
Comme elle utilise un thread légitime, elle est plus difficile à détecter, car le thread détourné s'exécute avec ses privilèges existants pour exécuter le code malveillant.
4. Injection APC (appel de procédure asynchrone)
L'injection APC met en file d'attente le code malveillant à exécuter lorsqu'un thread entre en état d'alerte. Cette méthode met le code en file d'attente sur un thread à l'aide de QueueUserAPC(). Le code injecté dans le thread est exécuté lorsqu'il traite sa file d'attente APC, ce qui se produit généralement lors d'appels système ou d'opérations d'attente particuliers. Cette méthode est bien adaptée aux threads qui visitent de manière répétée des états mutables.
5. Injection de DLL réfléchissante
La méthode d'injection de DLL réfléchissante charge une DLL à l'aide d'un chargeur Windows et n'écrit pas d'artefact dans le système de fichiers. Il s'agit d'une DLL personnalisée contenant des instructions sur la manière de la mapper et de l'adresser en mémoire. Cette astuce consiste à injecter le code du chargeur et la DLL dans la mémoire du processus cible, puis à exécuter le chargeur pour préparer la DLL. Elle permet d'éviter la détection par les mécanismes normaux de chargement des DLL et la surveillance.
6. Process Hollowing
Le Process Hollowing est une technique d'injection furtive dans laquelle les attaquants créent un processus légitime en état suspendu (à l'aide de CreateProcess avec CREATE_SUSPENDED), désactivent son espace mémoire d'origine (via NtUnmapViewOfSection/ZwUnmapViewOfSection), allouent une nouvelle mémoire (VirtualAllocEx), écrivent du code malveillant (WriteProcessMemory), corrigent l'en-tête PE et les relocalisations, mettent à jour le bloc d'environnement de processus (PEB) et enfin redirigent le point d'entrée (SetThreadContext) avant de reprendre l'exécution (ResumeThread). Cela permet au code malveillant de s'exécuter sous l'identité et les privilèges d'un processus légitime.
Comment fonctionne l'injection de processus ?
Les injections de processus suivent une série d'étapes dans le but d'exécuter du code dans un processus cible. Quelle que soit la méthode d'injection, la mise en œuvre technique suit certaines étapes qui manipulent la mémoire du processus et modifient la façon dont le flux du processus s'exécute.
La première étape consiste à identifier le processus cible et à acquérir l'accès. Le processus malveillant utilise OpenProcess() pour obtenir un descripteur sur le processus cible. Les droits d'accès requis pour ce descripteur sont PROCESS_CREATE_THREAD, PROCESS_QUERY_INFORMATION, PROCESS_VM_OPERATION, PROCESS_VM_WRITE et PROCESS_VM_READ.
La deuxième étape cruciale est l'allocation de mémoire dans le processus cible. La fonction VirtualAllocEx() alloue de l'espace mémoire dans l'espace d'adressage du processus cible en réservant et en validant des pages de la mémoire virtuelle.
La troisième étape consiste à copier le shellcode dans la zone mémoire allouée. WriteProcessMemory() copie les octets de code du tampon source vers la région mémoire du processus cible. Cette opération doit tenir compte des exigences d'alignement et de taille.
La dernière étape du déclenchement de l'exécution représente les composants centraux finaux. Chaque technique utilise un mécanisme ou un autre :
- CreateRemoteThread() crée un nouveau thread pour exécuter le code injecté
- QueueUserAPC() met en file d'attente l'exécution du code dans un thread existant
- SetThreadContext() modifie le flux d'exécution du thread existant
- Modification directe des pointeurs de fonction ou des hooks
Une fois l'exécution lancée, le code injecté s'exécute dans le contexte du processus cible, avec accès aux ressources et au jeton de sécurité de ce dernier. Ce code peut alors effectuer toutes les tâches pour lesquelles il a été conçu, en s'exécutant avec les privilèges et le niveau de confiance du processus cible.
Comment détecter les attaques par injection de processus ?
L'injection de processus est difficile à détecter car elle implique plusieurs composants et comportements du système. Pour identifier une activité d'injection, les systèmes de sécurité doivent surveiller les mouvements de mémoire, les appels API et tous les comportements des processus.
Ces méthodes de détection, combinées, forment une stratégie de détection globale.
Analyse des modèles de mémoire
L'analyse de la mémoire se concentre sur la recherche de modèles courants dans les régions de mémoire des processus. En effet, ces régions de la mémoire du processus sont analysées par des outils de sécurité afin de vérifier les paramètres d'autorisation de la mémoire du processus et le contenu attendu. Cela inclut notamment la détection des régions exécutables anormales et des pages qui ne sont pas conformes à leurs signatures de contenu typiques au sein des processus.
Les scanners de mémoire recherchent les écarts par rapport aux binaires de processus d'origine, soit en surveillant les changements dans les structures de mémoire de processus normalement statiques, soit en recherchant des segments de code dynamiques.
Surveillance des appels API
Les séquences suspectes d'appels de manipulation de mémoire sont détectées par la surveillance de l'API Windows. Les outils de sécurité surveillent OpenProcess() pour l'accès aux processus, VirtualAllocEx() pour l'allocation de mémoire et WriteProcessMemory() pour les écritures en mémoire. Si un thread est créé ou manipulé, par exemple CreateRemoteThread(), cela constituera un signe évident d'injection.
Les modifications de l'état des processus et des threads via des API telles que SuspendThread() et SetThreadContext() doivent également être surveillées, car elles sont souvent présentes dans les chaînes d'injection.
Indicateurs comportementaux
La surveillance du comportement des processus permet d'identifier les modèles d'activité inattendus suggérant ces tentatives d'injection. Les systèmes de détection d'intrusion surveillent les threads dans un processus relativement stable et les modifications de la carte mémoire du processus afin de suivre ces processus.
Ces comportements, ainsi que la modification des tables d'adresses d'importation et les opérations de mémoire inter-processus, sont des indicateurs pertinents pour la détection.
Outils de détection
La détection des injections de processus nécessite des outils de sécurité dotés de capacités de surveillance approfondies. L'analyse en temps réel est effectuée par des moniteurs de processus qui surveillent les appels API et les actions du système, tandis que les outils d'analyse de la mémoire effectuent une analyse approfondie des espaces mémoire des processus. Les analyseurs de journaux d'événements permettent aux équipes d'enregistrer l'historique des événements de sécurité au sein du système afin d'avoir une vue d'ensemble du passé.
Les solutions de détection et de réponse d'entreprise (EDR) telles que SentinelOne combine divers moyens de surveillance avec des capacités d'analyse. Il existe des outils d'administration système tels que le moniteur de processus et l'explorateur de processus, qui affichent les processus en détail ainsi que l'allocation de mémoire par processus.
Comment prévenir les attaques par injection de processus ?
La prévention des injections de processus ne peut être assurée par un seul contrôle de sécurité, mais implique des contrôles au niveau du système, des processus et du code. Ces mesures d'atténuation visent à limiter les capacités d'injection de processus et à rendre les processus cibles potentiels plus difficiles à injecter.
Prévention au niveau du système
Les mesures préventives au niveau du système commencent par une gestion correcte des accès et des privilèges. Les systèmes doivent disposer de droits de création et de manipulation de processus configurés de manière à restreindre les utilisateurs non administratifs, afin qu'ils ne puissent ouvrir que des descripteurs vers des processus sensibles sur les systèmes. Ces restrictions sont appliquées par le contrôle des comptes utilisateurs (UAC) et les politiques AppLocker afin de gérer les processus pouvant être exécutés et leur niveau de privilège.
Signature de code
Une autre couche de prévention importante est l'application de la signature de code. Les modules doivent être chargés après vérification de leur signature numérique, et les codes mal signés ou non signés doivent être rejetés par les systèmes. Les stratégies Windows Defender Application Control (WDAC) appliquent les exigences d'intégrité du code et désactivent le chargement des DLL et des exécutables non signés.
Protection de la mémoire
Les mécanismes de protection de la mémoire constituent un élément important de la défense. La prévention de l'exécution des données (DEP) protège contre l'exécution de code à partir des pages de données, tandis que la randomisation de l'espace d'adressage (ASLR) rend difficile le ciblage d'une mémoire spécifique.
Les mesures de protection moyennes des processus comprennent le contrôle du flux d'exécution (CFG), qui vérifie les cibles pour les appels indirects, et la protection légère des processus (PPL), qui limite la capacité des processus à ouvrir ceux qui existent déjà en fonction des niveaux de signature des membres.
Renforcement des applications
Même pour le renforcement des applications, l'équipe de sécurité doit également suivre des pratiques de codage sécurisées et des options de compilation. Les développeurs doivent configurer des fonctionnalités de sécurité, telles que /DYNAMICBASE et /NXCOMPAT, mettre en œuvre la gestion des exceptions et valider les opérations de mémoire dans le processus de débogage de l'application.
Cybersécurité alimentée par l'IA
Améliorez votre posture de sécurité grâce à la détection en temps réel, à une réponse à la vitesse de la machine et à une visibilité totale de l'ensemble de votre environnement numérique.
Obtenir une démonstrationConclusion
L'injection de processus injecte du code malveillant dans les espaces mémoire parallèlement à d'autres processus en cours. L'attaquant force les processus cibles à exécuter du code arbitraire, puis écrit son propre code dans les espaces d'adressage. La raison pour laquelle cette technique est si dangereuse est qu'elle permet de contourner les techniques traditionnelles de détection des menaces. Pour la détecter, vous devez utiliser des solutions de sécurité avancées et des stratégies de prévention.
Il s'agit notamment de la protection de la mémoire, des contrôles comportementaux, des contrôles d'accès et d'autres éléments. Comprendre le fonctionnement des techniques d'injection de processus permet aux organisations de renforcer leurs systèmes de manière appropriée et de déployer des contrôles de sécurité plus efficaces.
"FAQ sur l'injection de processus
L'injection de processus est une attaque dans laquelle le pirate copie et exécute un code dans la mémoire d'un processus. Cela permet à un acteur malveillant d'exécuter son propre code dans le processus cible, ce qui lui permet de contourner les mesures de sécurité.
L'injection de processus est une technique principalement utilisée pour dissimuler une activité et assurer la persistance, ainsi que pour exécuter du code avec des privilèges plus élevés. Si la DLL Windows est injectée dans un autre processus par le biais de processus normaux, le code exécuté effectuera des opérations avec le même niveau de confiance que le processus cible et disposera des mêmes droits d'accès, ce qui rendra plus difficile la détection des comportements malveillants par les outils de sécurité.
La détection de l'injection de processus nécessite la surveillance de la mémoire, de l'API et des comportements des processus. Les analyseurs de programmes statiques signalent ces tentatives d'injection en recherchant des modèles tels que des allocations de mémoire anormales, des créations de threads et des séquences API de manipulation de processus anormales.
L'injection de processus est principalement utilisée par les logiciels malveillants, mais dans certains cas, cette technique peut être utilisée à des fins légitimes, par exemple pour le débogage, l'analyse de logiciels malveillants, les techniques de surveillance et pour étendre les fonctionnalités d'une application.
Dans les campagnes de type APT (menaces persistantes avancées), l'injection de processus joue un rôle essentiel pour assurer la persistance et éviter la détection. Les acteurs APT utilisent des techniques d'injection avancées pour obtenir un accès permanent aux systèmes infectés et garantir qu'ils ne seront jamais découverts pendant une opération prolongée.
