このリポジトリには、ルートキットがファイルを隠す際に操作されるカーネル関数の時間測定値を収集するコードと、カーネル関数の実行時間のシフトを分析する半教師あり検出手法が含まれています。この実装は、オープンソースのルートキットCARAXESに依存しており、lsコマンドの実行時などにファイル列挙の結果を操作するためにfilldir関数をラップします。時間測定は、eBPFプローブを使用してgetdentsシステムコール内のいくつかの関数(filldirを含む)から取得されます。検出には、統計的検定に基づくシンプルな機械学習モデルを適用します。データ収集と異常検出メカニズムの詳細な説明については、以下の出版物を参照してください。このリポジトリで提供されるリソースを使用する場合は、以下の出版物を引用してください。
以下の手順でルートキットをセットアップし、カーネル関数から時間測定値を収集する方法を説明します。異常の検出のみに関心があり、公開データセットを使用したい場合は、このセクションをスキップしてください。
ルートキットとプロービングは、Linuxカーネル5.15-6.11およびPython 3.10でテストされています。ツールを実行するには、このリポジトリをダウンロードし、ルートキットとプロービングメカニズムの実行に必要な以下の依存関係をインストールしてください。
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
一部のシナリオでは追加のリソースが必要です。具体的には、ls-basicシナリオではls-basicスクリプトのコンパイルが必要であり、システム負荷シナリオではstress-ngのインストールが必要です。これらのシナリオを使用しない場合は、以下の依存関係をスキップできます。
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
以下のコマンドは必須です。ルートキットはデフォルトでgetdentsシステムコールを操作しますが、現在プロービングでサポートされているのはfilldirの操作のみです。ルートキットをダウンロードし、hooks.hをこのリポジトリで提供されているファイルで置き換え(これによりgetdentsではなくfilldirがフックされるようになります)、ルートキットをコンパイルしてください。
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
ルートキットのインストールで問題が発生した場合や、期待通りに動作するかテストしたい場合は、CARAXES GitHubページのReadMeを参照してください。
その後、このリポジトリに戻り、linux.pyを開いて変数KERNEL_OBJECT_PATHを編集し、先ほどクローンしたcaraxesフォルダを指すようにします。デフォルトのパスは"/home/ubuntu/caraxes/"です。
ubuntu@ubuntu:~/caraxes$ cd ../rootkit-detection-ebpf-time-trace
ubuntu@ubuntu:~/rootkit-detection-ebpf-time-trace$ vim linux.py
これで、カーネルにプローブを自動的に注入し、ルートキットを起動し、時間測定データをファイルに保存し、ルートキットを停止するプロービングメカニズムを実行する準備が整いました。システムコールをトリガーするために、スクリプトは隠すファイルを含むディレクトリを作成し、プローブをポーリングしながらlsを100回実行します(-iフラグで変更可能)。このスクリプトは、ルートキットあり(--rootkitフラグ)、ルートキットなし(--normalフラグ)、またはその両方で測定を収集でき、いくつかのシナリオをサポートしています。以下のコマンドでデフォルトのシナリオを実行してください。
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
測定結果はeventsディレクトリに保存されます。python3 probing.py -hでヘルプページを確認し、他のシナリオ(例:lsの代わりにls-basicを使用したり、システム負荷をシミュレートするなど)でデータ収集を設定したり、異なる実行に名前を割り当てる(--description)ためのパラメーターを確認してください。パラメータ化されたコマンドについてはrepeat_seq.shを参照してください。実際、私たちはこのスクリプトを使用して公開データセットを収集しました。なお、getdentsシステムコールから利用可能なカーネル関数の一部のみを考慮しています。プロービングメカニズムがプローブをアタッチする関数を指定するには、probing.pyを開き、ファイル先頭のprobe_pointsリストに関数名を追加または削除してください。
異常検出アルゴリズムを実行するには、Pythonの依存関係をインストールするだけです。前のステップでまだ行っていない場合は、以下のコマンドを実行して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
次に、Zenodoで提供しているデータセットをダウンロードして展開します。前のステップで独自のデータを生成し、それを使用したい場合は、このステップをスキップしてください。
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
これで、以下のように異常検出を実行する準備が整いました。測定データを含むディレクトリ(-d)、トレーニングに使用する正常データの割合(-t)、動作モード(-m)、グループ化関数(-g)を指定します。スクリプトは指定されたディレクトリからすべてのファイルを読み込み、トレーニングデータとテストデータに分割し(出力に要約)、検出メトリクスを計算して出力し、混同行列をプロットします。
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
python3 evaluate.py -hでマニュアルを確認し、このスクリプトの利用可能なパラメーターについて詳しく学んでください。また、demo.shを参照して、論文の評価で使用したパラメータ化されたコマンドを確認してください。
このリポジトリで提供されるリソースを使用する場合は、以下の出版物を引用してください。