Linuxの新型ウイルスの実地テスト

読者の1人による協力のおかげで、NewsForgeは、あちこちで報じられた例のウイルスのコピーを入手した。WindowsとLinuxのいずれにも作用するクロスプラットフォームの「概念実証」ウイルスだ。このウイルスについて各サイトが報じた内容には食い違いがある。WindowsでもLinuxでも自己複製が可能、という報告もあれば、Windowsにしか作用しない、という報告もある。NewsForgeスタッフとHans-Werner Hilse氏によるテスト結果から、この食い違いの原因を解明してみよう。

我々のテストでは、使っているカーネルによってはこのウイルスが両方のプラットフォームに作用する場合がある ― 常にではない ― ことが確認された。もちろん、世の中にあるすべてのバージョンのカーネルをテストするのは不可能だが、これまでの調べによると、どうやら2.6.16より前のバージョンが影響を受けるらしい。少なくとも、それより後のバージョンには影響を受けないものがあった。では、NewsForgeで行ったテストの内容を紹介しよう。

最初のテストに使ったのは、カーネル2.16.15-20-386を搭載する最新のUbuntu Dapper Flight 5 386をインストールしたAMD64マシンだ。WINEとバイナリビューア/エディタのGHexの各パッケージもインストールしてある。ウイルスパッケージ(clt.zip)を空のディレクトリに展開した後、そのサブディレクトリにhelloという小さなELF(実行およびリンクが可能なファイル形式)ファイルを置き、WINEの下でCLT.EXEを実行してテストを行った。アセンブラで書かれたこのELFファイルは、今回のテスト用に我々が作成したものだ。CLT.EXEの実行によって、”dropper” ― このウイルスコードの呼び名だ ― と表示された小さなポップアップウィンドウが現れ、正常に実行が完了したことを確認した。

ところが、ELFファイルhelloをGHexで調べても感染した形跡がない。Linuxで実行された際にウイルス自身に代わって書き込まれるはずのテキストさえ見当たらない。間もなく、このウイルスがLinuxに作用しないわけではなく、単に実行ファイルhelloが小さすぎたことが原因だとわかった。別のNewsForgeスタッフが、もっと大きなELFファイルを用意してVMWareの下でCLT.EXEを実行したところ、確かに感染したからだ。

The 次に、/binの下からmore、data、lsの各プログラムをテストディレクトリにコピーして再びCLT.EXEを実行すると、これらのELFは3つとも感染した。どれも実行前より4,096バイトだけサイズが増えていた。追加されたこの4,096バイトには実際にウイルスのコードが含まれているのだろうか。各ELFファイルは感染後も実行できるのだろうか。こうした疑問に基づいてさらにテストを行った。

今度はWINEの下でCLT.EXEを実行するのではなく、先ほどと同じ3つのプログラムの感染していないものを別のディレクトリに用意し、感染したlsをそこで実行した。CLT.EXE実行時と比べて唯一見られた違いは、ポップアップウィンドウが現れなかったことだ。その他の点は同じで、more、ls、dateはすべて感染し、helloは影響を受けなかった。

その頃、大西洋の向こう側では

Hans-Werner Hilse氏は、このウイルスコードの調査を我々より詳しく行っている。彼は、最初のテストの様子を次のように述べている。

qemu ― PentiumIIのエミュレータ ― で実行中のカーネル2.4.26(私の環境にはDamn Small LinuxのISOがインストールされている)でも感染が起こることを確認できた。

ただ、先にテストしたカーネル2.6(2.6.16.2および2.6.15.4)のものとトレース結果を比較したところ、プログラムフローに違いが見つかった。新しいカーネルではmmapの実行に失敗していたのだ。

(”strace -viqo strace.log ./echo x”というコマンドを実行。この”echo”は感染済みの/bin/echoであり、もう1つの感染していないechoは”E”として感染待ちの状態にある)

—>2.6.15.4: [08047416] readdir(3, {d_ino=10933298, d_name=””}) = 1
[0804742d] stat(“E”, {st_dev=makedev(3, 7), st_ino=10933298, st_mode=S_IFREG|0755, st_nlink=1, st_uid=1000, st_gid=100, st_blksize=4096, st_blocks=40, st_size=16600, st_atime=2006/04/14-21:31:09, st_mtime=2006/04/14-21:31:09, st_ctime=2006/04/14-21:31:09}) = 0
[0804744d] open(“E”, O_RDWR) = 4
[08047463] ftruncate(4, 24792) = 0
[0804747e] old_mmap(NULL, 28672, PROT_READ|PROT_WRITE, MAP_SHARED, 4, 0) = 0xb7fca000
[0804749c] munmap(0xb7fca000, 24792) = 0
[080474a7] ftruncate(4, 20696) = 0
—>2.6.16.2:
[08047416] readdir(3, {d_ino=722045, d_name=””}) = 1
[0804742d] stat(“E”, {st_dev=makedev(3, 1), st_ino=722045, st_mode=S_IFREG|0755, st_nlink=1, st_uid=1000, st_gid=100, st_blksize=4096, st_blocks=48, st_size=20696, st_atime=2006/04/14-21:31:09, st_mtime=2006/04/14-21:31:31, st_ctime=2006/04/14-21:35:16}) = 0
[0804744d] open(“E”, O_RDWR) = 4
[08047463] ftruncate(4, 28888) = 0
[0804747e] old_mmap(NULL, 32768, PROT_READ|PROT_WRITE, MAP_SHARED, 1, 0) = -1 ENODEV (No such device)
[080474a7] ftruncate(4, 20696) = 0

このように、新しいバージョンのカーネルでは0804747eのmmapが実行できていない。それにしても、このシステムコールの名前が”old_mmap”になっているのが気になる。廃止予定のインターフェイスなのだろうか…。

なぜカーネルによってこのウイルスの影響を受けるものと受けないものがあるのかを探るため、Hilse氏はテストを続けている。以下は、彼からの最新報告だ。

私の予想どおりだったようだ。”ftruncate”をコールした後、確かにebxレジスタが”1″にリセットされている。コールの前後でレジスタのダンプを比較して確かめたところ、 ftruncateシステムコール前のebxは7だが、コール後にブレークポイント#3で割り込みをかけると1になっていた。

ただ、これが正常な動作なのかどうかはわからない。しかし、Web上の数多くの情報によると、Linuxのシステムコールではeax以外のレジスタは変更されない(つまり、カーネルからユーザ空間に戻る次点でリセットされる)ようだ。アセンブラの多くの例ではそうなっている。つまり、このカーネルのこの部分に問題がある可能性がある。

以上のようなテスト結果を知らせるため、我々NewsForgeは、Linus Torvalds氏にメールを送った。以下は、その返信内容だ。

そうは言っても、たまたまWindowsとLinuxの両方に作用し、それ自体としては何の問題もないことを行う(すなわち、ユーザの所有するファイルに書き込みを行う)普通のプログラムのようだ。確かに興味深いプログラムだが、それは「LinuxとWindowsの両方に作用する」からだ。ウイルスの素性が理由ではない。

また我々は、このウイルスの影響がなぜカーネル依存なのかを解明したいカーネルハッカーには「概念実証」コードを提供する、とLinux Kernel Mailing Listに投稿していたのだが、依然として反応はない。カーネルの内部動作に関心はあっても、どうやらこのコードの脅威に対してはアンチウイルスソフトウェア関係者が示すほどの関心もないようだ。

今回のテスト結果に基づき、Linuxユーザは次の2点に注意すべきである。1つは、パーミッションの設定によってはLinuxでもウイルスが自己複製できることだ。この点に疑問の余地はない。だが、Windowsの場合と同じくらい簡単に広まるウイルスをLinuxに対して作れるかどうかは今のところ不明だ。もう1つは、この「概念実証」の例が見事に示しているとおり、rootでのプログラム実行は非常に危険だということだ。

原文