LKM(Linux Kernel Module) 結構簡単かも
STATUS: 故障中
LinuxUsers-MLで、unlinkを改造したいという投稿([linux-users:101834])がありまして、それに対しシステムコールをフックすればいいのではという回答([linux-users:101835])がありました。
なんか簡単そうなことがかかれているので、興味を持ち調べてみました。
まずこのサイトを見つけました。
● Linux Kernel Hacking
・システムコールの追加
・LKMによるシステムコールのフック
LKMというのを作って insmodコマンドで読み込むと適用すればいいのですね。
説明もかなり短くてこれでいいのかなと思うくらいでした。
このページにある、システムコールの追加の方法も参考になりました。
次のこのサイトを見つけました。
● 〜rootkitを検出するために〜
連載:インシデントレスポンスはじめの一歩
第3回 侵入者の不利な情報を隠すLKM rootkitの仕組み
こっちは KVMを使ってシステムコールをフックするタイプのrootkitの危険性を説く内容なのですが、そのなかで実際にLKMを作ってインストールしてみるという記事がありました。
ここでは、unameシステムコールをフックして、システム名「Linux」と返すところを「Windows」と上書きするというコードの例がのってました。(コードは最初のリンクのページとほとんど同じ書き方なので、これが標準的な書き方なのでしょう)
ソースとコンパイル手順(って「gcc -c -O3 hook_uname.c」ってだけ。)が載っていてそのまま試せそうでしたので、早速やってみました。
(1) ソースをコピペして ( hook_uname.c )
(2) コンパイル ( gcc -c hook_uname.c )
(3) あっさりコンパイルが通って、hook_uname.o が出来ました。
(4) rootになって、いよいよ組み込み ( insmod hook_uname.o )
…おっとここでエラーがでました。
#insmod hook_uname.o
hook_uname.o: kernel-module version mismatch
hook_uname.o was compiled for kernel version 2.4.4
while this kernel is version 2.4.19.
カーネルのバージョンが違うと文句をいっているようです。
エラーメッセージでぐぐってみると、同じことで困っているひとがいました。
件名:同一カーネルでコンパイルしたのにkernel version mismatch
どうやらコンパイル時とおなじバージョンのシステムでないと組み込み出来ないようです。
が、2.4.4のソースなんてHDD検索しても見つからないけどなあ。いまのカーネルmakeしなおしたときのソースが /usr/src/linux-2.4.19/arch/i386/ 以下に入っているのでこいると使えばいいのだろうけど、gccへの設定のしかたがわからないや。
もうちょっとググって見ると、-f オプションという禁断のパラメータがあるようなので、これで試してみました。
#insmod hook_uname.o
Warning: kernel-module version mismatch
hook_uname.o was compiled for kernel version 2.4.4
while this kernel is version 2.4.19
Warningが出ましたが実行できたようです。
(5) ここで uname を実行してみると
#uname -a
Windows www 2.4.19 #10 Sun Oct 20 23:20:41 JST 2002 i686 unknown
システムはWindowsだとおもいっきり騙されてます。面白い
(6) 組み込み済みのモジュール一覧を表示してみます
#lsmod
Module Size Used by
hook_uname 496 0 (unused)
msdos 5008 0 (unused)
fat 31808 0 [msdos]
このなかの、「hook_uname」が今回組み込んだモジュールですね。
(7) モジュールの解除はこんな感じ
#rmmod -f hook_uname.o
基本的に記事に書いてあるとおりやってみただけですが、意外と簡単なものだとわかりました。
Windowsでこんな処理やろうとしたらどんな苦労をするか想像もつきません。
先に進むといろいろ難しいことも出てくるのでしょうが、少なくとも入り口はシンプルでわかりやすいものでした。
何か自作のLKM作ってみたくなりますね。
【その他参考ページ】
☆Linux カーネルの仕組みを勉強するスレ☆
【メモ】
システムコール呼び出しの例。2つとも同じ結果になる。
(a) execve#include "unistd.h"
int main() {
int n;
n = execve( "/bin/date" , NULL , NULL );
printf("*result:%d\n",n);
return 0;
}
(2) syscall#include "sys/syscall.h"
#include "unistd.h"
int main() {
int n;
n = syscall(SYS_execve , "/bin/date" , NULL , NULL );
printf("*result:%d\n",n);
return 0;
}
※ 不等号がかけないので、includeのところは " に置き換えた コメント