
Rilevamento delle attività di occultamento dei file dei rootkit tramite l'analisi degli spostamenti nei tempi di esecuzione delle funzioni del kernel.
Questo repository contiene codice per raccogliere misurazioni temporali di funzioni del kernel manipolate dai rootkit quando nascondono file, nonché un metodo di rilevamento semi-supervisionato che analizza gli spostamenti dei tempi di esecuzione delle funzioni del kernel. Questa implementazione si basa sul rootkit open-source CARAXES, che avvolge la funzione filldir per manipolare i risultati delle enumerazioni di file, ad esempio durante l'esecuzione del comando ls. Le misurazioni temporali vengono effettuate su diverse funzioni della chiamata di sistema getdents (inclusa filldir) utilizzando sonde eBPF. Per il rilevamento applichiamo un semplice modello di machine learning basato su test statistici. Per spiegazioni dettagliate sulla raccolta dati e sui meccanismi di rilevamento delle anomalie, rimandiamo alla seguente pubblicazione. Se utilizzi una qualsiasi delle risorse fornite in questo repository, ti preghiamo di citare la seguente pubblicazione:
I passaggi seguenti configurano il rootkit e spiegano come raccogliere misurazioni temporali dalle funzioni del kernel. Se sei interessato solo al rilevamento delle anomalie e vuoi utilizzare i nostri set di dati pubblici, puoi saltare questa sezione.
Il rootkit e la sonda sono stati testati su kernel Linux 5.15-6.11 e Python 3.10. Per eseguire gli strumenti, scarica questo repository e installa le seguenti dipendenze necessarie per eseguire il rootkit e il meccanismo di probing.
ubuntu@ubuntu:~$ git clone https://github.com/ait-aecid/rootkit-detection-ebpf-time-trace.git
ubuntu@ubuntu:~$ cd rootkit-detection-ebpf-time-trace
ubuntu@ubuntu:~/rootkit-detection-ebpf-time-trace$ sudo apt update
ubuntu@ubuntu:~/rootkit-detection-ebpf-time-trace$ sudo apt install python3-bpfcc make gcc flex bison python3-pip linux-headers-$(uname -r)
ubuntu@ubuntu:~/rootkit-detection-ebpf-time-trace$ pip install -r requirements.txt
Alcuni scenari richiedono risorse aggiuntive. In particolare, lo scenario ls-basic richiede la compilazione dello script ls-basic e lo scenario system load richiede l'installazione di stress-ng. Se non vuoi utilizzare questi scenari, puoi saltare le seguenti dipendenze.
ubuntu@ubuntu:~/rootkit-detection-ebpf-time-trace$ gcc -o ls-basic ls-basic.c
ubuntu@ubuntu:~/rootkit-detection-ebpf-time-trace$ sudo apt install stress-ng
I seguenti comandi sono obbligatori, perché il rootkit manipola di default la chiamata di sistema getdents, ma attualmente per il probing è supportata solo la manipolazione di filldir. Scarica il rootkit, sostituisci hooks.h con il file fornito in questo repository (questo garantisce che filldir venga agganciato invece di getdents) e compila il rootkit.
ubuntu@ubuntu:~/rootkit-detection-ebpf-time-trace$ cd ..
ubuntu@ubuntu:~$ git clone https://github.com/ait-aecid/caraxes.git
ubuntu@ubuntu:~$ cd caraxes/
ubuntu@ubuntu:~/caraxes$ cp ../rootkit-detection-ebpf-time-trace/hooks.h .
ubuntu@ubuntu:~/caraxes$ sudo make
Se hai problemi nell'installazione del rootkit o vuoi verificare che funzioni come previsto, consulta il ReadMe sulla pagina GitHub di CARAXES.
Successivamente, torna a questo repository e apri linux.py per modificare la variabile KERNEL_OBJECT_PATH in modo che punti alla cartella caraxes appena clonata; il percorso predefinito è "/home/ubuntu/caraxes/".
ubuntu@ubuntu:~/caraxes$ cd ../rootkit-detection-ebpf-time-trace
ubuntu@ubuntu:~/rootkit-detection-ebpf-time-trace$ vim linux.py
Ora sei pronto per eseguire il meccanismo di probing che inietterà automaticamente le sonde nel kernel, avvierà il rootkit, salverà i dati di misurazione temporale in un file e fermerà il rootkit. Per attivare le chiamate di sistema, lo script crea una directory con file da nascondere ed esegue ls 100 volte (modificabile con il flag -i) mentre interroga le sonde. Lo script consente di raccogliere misurazioni con il rootkit (flag --rootkit), senza rootkit (flag --normal), o entrambi, e supporta diversi scenari. Esegui lo scenario predefinito con il seguente comando:
ubuntu@ubuntu:~/rootkit-detection-ebpf-time-trace$ sudo python3 probing.py --normal --rootkit
compiling eBPF probes...
probes compiled!
attached bpf probes:
iterate_dir-enter
iterate_dir-return
dcache_readdir-enter
dcache_readdir-return
filldir64-enter
filldir64-return
verify_dirent_name-enter
verify_dirent_name-return
touch_atime-enter
touch_atime-return
Running experiment with ls for 100 times.
Iteration 0...
detection_PID: 70133
Iteration 1...
detection_PID: 70134
...
Iteration 99...
detection_PID: 70338
polled 40 times!
done with the "rootkit version"
Experiment finished, saving output.
Saved data to events/events_2025-01-17T09:59:52.183801_rootkit.json.gz
412K events/events_2025-01-17T09:59:52.183801_rootkit.json.gz
Le misurazioni sono memorizzate nella directory events. Visita la pagina di aiuto con python3 probing.py -h per conoscere altri parametri che consentono di impostare la raccolta dati in altri scenari (ad esempio usando ls-basic invece di ls o simulando il carico di sistema) e assegnare nomi a diverse esecuzioni (--description). Dai un'occhiata a repeat_seq.sh per alcuni comandi parametrizzati; infatti, abbiamo usato questo script per raccogliere i nostri set di dati pubblici. Nota che consideriamo solo alcune delle funzioni del kernel disponibili dalla chiamata di sistema getdents. Per specificare a quali funzioni il meccanismo di probing deve collegare le sonde, apri probing.py e aggiungi o rimuovi i nomi delle funzioni nella lista probe_points all'inizio del file.
Eseguire l'algoritmo di rilevamento delle anomalie richiede solo l'installazione delle dipendenze Python. Se non lo hai già fatto nel passaggio precedente, esegui il seguente comando per installare i requisiti con pip.
ubuntu@ubuntu:~$ git clone https://github.com/ait-aecid/rootkit-detection-ebpf-time-trace.git
ubuntu@ubuntu:~$ cd rootkit-detection-ebpf-time-trace
ubuntu@ubuntu:~/rootkit-detection-ebpf-time-trace$ pip install -r requirements.txt
Quindi, scarica ed estrai il set di dati che forniamo su Zenodo. Se hai generato i tuoi dati nel passaggio precedente e vuoi utilizzarli, salta questo passaggio.
ubuntu@ubuntu:~/rootkit-detection-ebpf-time-trace$ wget https://zenodo.org/records/14679675/files/events.zip
ubuntu@ubuntu:~/rootkit-detection-ebpf-time-trace$ unzip events.zip
Ora sei pronto per eseguire il rilevamento delle anomalie come segue. Specifica la directory contenente i dati di misurazione (-d), la frazione di dati normali usati per l'addestramento (-t), la modalità operativa (-m) e la funzione di raggruppamento (-g). Lo script caricherà tutti i file dalla directory specificata, li dividerà in dati di addestramento e test (riassunti nell'output), calcolerà e stamperà le metriche di rilevamento e traccerà una matrice di confusione.
ubuntu@ubuntu:~/rootkit-detection-ebpf-time-trace$ python3 evaluate.py -d events -t 0.333 -m offline -g fun
100%|█████████████████████████████████████████████| 1250/1250 [02:47<00:00, 7.45it/s]
Processed all files from events
Normal batches: 750
Normal batches for training: 250
default: 50
file_count: 50
system_load: 50
ls_basic: 50
filename_length: 50
Normal batches for testing: 500
default: 100
file_count: 100
system_load: 100
ls_basic: 100
filename_length: 100
Anomalous batches: 500
default: 100
file_count: 100
system_load: 100
ls_basic: 100
filename_length: 100
Results (Run 1)
Threshold=3.5111917342151415e-16
Time=0.0027740001678466797
TP=499
FP=9
TN=491
FN=1
TPR=R=0.998
FPR=0.018
TNR=0.982
P=0.9822834645669292
F1=0.9900793650793651
ACC=0.99
MCC=0.9801254640896192
Confusion Matrix (Run 1)
Predicted
default file_count system_load ls_basic filename_length
Pos Neg Pos Neg Pos Neg Pos Neg Pos Neg
100 0 100 0 100 0 100 0 100 0 Pos - Actual default
3 97 100 0 99 1 100 0 2 98 Neg - Actual default
100 0 100 0 100 0 100 0 100 0 Pos - Actual file_count
100 0 0 100 100 0 100 0 100 0 Neg - Actual file_count
100 0 100 0 100 0 100 0 100 0 Pos - Actual system_load
100 0 100 0 4 96 100 0 100 0 Neg - Actual system_load
100 0 100 0 100 0 99 1 100 0 Pos - Actual ls_basic
100 0 100 0 100 0 2 98 100 0 Neg - Actual ls_basic
99 1 100 0 100 0 100 0 100 0 Pos - Actual filename_length
3 97 100 0 99 1 100 0 0 100 Neg - Actual filename_length
Consulta il manuale usando python3 evaluate.py -h per saperne di più sui parametri disponibili di questo script. Dai anche un'occhiata a demo.sh per vedere i comandi parametrizzati che abbiamo usato per la valutazione nel nostro articolo.
Se utilizzi una qualsiasi delle risorse fornite in questo repository, ti preghiamo di citare la seguente pubblicazione: