
Injection de shellcode utilisant l'API de débogage Windows
DbgNexum est une preuve de concept pour injecter un shellcode en utilisant l'API de débogage Windows et la mémoire partagée (File Mapping). Elle évite d'écrire et de lire directement la mémoire distante, utilisant plutôt la manipulation du contexte pour forcer le processus cible à charger et exécuter la charge utile elle-même.
L'injecteur s'attache à un processus cible et crée un thread suspendu. Grâce à une boucle de débogage, il définit un point d'arrêt matériel pour piéger l'exécution à une adresse de retour spécifique. À chaque piège, l'injecteur modifie les registres du CPU pour imiter des appels de fonction, orchestrant une séquence d'appels à des fonctions API Windows à l'intérieur du processus cible.
Au moment de la rédaction de ce README, j'ai testé la technique contre MDE et Elastic, dont aucun ne l'a détectée.
WriteProcessMemory / VirtualAllocEx : La charge utile est transférée via CreateFileMapping et MapViewOfFile.ReadProcessMemory : L'approche obtient toutes les informations clés à partir du contexte du thread.Le PoC utilise un shellcode XORé de msfvenom qui lance « calc.exe ». Mais veuillez utiliser votre propre shellcode !
shellcode.hDbgNexum.exe <PID>
Exemple de sortie :
[i] Section 'MZ' created and shellcode copied
[+] Bait thread created. Setting HWBP on FileTimeToSystemTime
[i] Execution Redirected:
|-> [0] Preparation & anchoring stack
|-> [1] Setting HWBP & buffer alloc
|-> [2] Copying File-Mapping name
|-> [3] Zeroing stack slot
|-> [4] Opening handle to named file mapping
|-> [5] Mapping payload into mem. with exec. perm.
|-> [6] Cleanup & shellcode execution
[+] Successfully detached from process 19256
[i] Orchestration complete.
Le flux d'exécution est un va-et-vient constant entre la boucle de débogage de l'injecteur et le processus cible.
Étapes d'injection
La fonction DebugLoop contient la logique principale d'injection et orchestre la « machine à états » :
0. Préparation :
ret immédiat.1. Allocation :
LocalAlloc pour (évidemment) allouer un petit tampon.2. Configuration des données :
memcpy pour copier la chaîne MZ dans le tampon précédemment alloué.3. Préparation de la pile :
memset pour mettre à zéro un emplacement de pile. Ceci en préparation de l'étape 5, qui appellera MapViewOfFile. Comme la fonction utilisera plus de 4 arguments, le 5ème argument est passé via la pile (que nous définissons ici).4. Ouverture du mappage :
OpenFileMappingA en utilisant le nom MZ, « créé » dans les étapes 2 & 3.5. Mappage de la charge utile :
MapViewOfFile. Cela mappe la section de mémoire partagée (contenant le shellcode) dans l'espace d'adressage de la cible avec des permissions EXECUTE.6. Exécution :
RIP vers l'adresse retournée par MapViewOfFile.