はじめに
この投稿は、kosen14s読書会用の記事です。kosen14s読書会
kosen14s読書会では、何人かのメンバーが自由なジャンルの本を紹介します。私は他にブログらしきものを持っていないことと、ちょうど技術的な内容の本を紹介する予定だったので、ここに投稿しました。
Practical Malware Analysis
本記事で紹介するのは、Michael SikorskiさんとAndrew Honigさんの著書「Practical Malware Analysis: The Hands-On Guide to Dissecting Malicious Software」です。
Practical Malware Analysis
宇宙人が解剖されかけているという一見不思議な表紙ですが、これは「中身の分からないものを調査する」ということを暗示しているのだと思います。
さて、この本ではマルウェア(端的に言うとウイルス)を解析するために必要な知識を1から100まで記載した技術書で、内容がとにかく充実しています。私は自分の読みたいところだけを読む人なので、本当はこの本の内容を全て読んだ訳ではありません。しかし、さらっと読んだだけでも有用な情報が数多く書かれていたので、その中でも特に面白かったものについてのみここで取り上げようと思います。
この本との出会い
この本を初めて知ったのは高校1年生の冬、北海道で開かれたセキュリティミニキャンプという勉強会でした。その勉強会は私がコンピュータセキュリティを勉強するきっかけにもなったのですが、そのため当時は会場一の初心者でした。勉強会を通して活躍が見られた人にはこの本が貰えるとのことだったのですが、もちろん本はプロ達の手に渡っていきました。そこで、「プロが良本を手に入れるとよりプロになる」というプロサイクルを見出しました。これではいかんと思い、それから1年後にネット通販でこの本を買うことにしたのです。おしまい。逆アセンブルとは
まず説明する前に、逆アセンブルということについて説明します。逆アセンブルとは、実行ファイルなどの機械語を、アセンブリ言語という多少人間が読みやすい形式に変換する作業を指します。
機械語はintelやらARMやらといったプロセッサにより異なりますが、アセンブリ形式はどの種類でもある程度似ているので、普通の人がマルウェアを解析するとき、逆アセンブルされたものを読みます。この記事では、intel形式のアセンブリ言語(NASM)で書きたいと思います。
例えば
b8 77 00 00 00 50
という機械語列はさっぱり意味が分かりませんが、これを逆アセンブルして
mov eax, 0x77 push eax
にすると、あら不思議。分かりやすい。
さて、みなさんが普段使っているソフトウェアは、例えばWindowsならexeなどの実行ファイルになっていることが多いです。これが実行できるということは、このファイルの中に一連の動作を表す機械語が書かれています。マルウェアに限らず、実行ファイルを解析するときはこの機械語を逆アセンブルするのです。そして、逆アセンブルするためのツールはたくさん用意されています。個人的に代表的なのは次のツールです。
静的解析:IDA Pro, radare2
動的解析:OllyDbg, x64dbg
静的解析のツールは、先に説明したように、ただ機械語を逆アセンブルした結果を表示するツールです。ただ、こういったツールの良いところは、逆アセンブルした結果をフローチャートのようにするなど、できるだけ人間に分かりやすく整理して表示してくれるのです。動的解析のツールは、逆アセンブルをすると共に、そのプログラムを実行します。しかし、マルウェアは実行したら危ないので、今回はやりませんでした。
ANTI-DISASSEMBLY
解析を困難にする技術には大別して「ANTI-DISASSEMBLY」「ANTI-DEBUGGING」「ANTI-VIRTUAL MACHINE TECHNIQUES」「PACKERS」の4つがあります。特に3つ目の「ANTI-VIRTUAL MACHINE TECHNIQUES」 はマルウェア特有の技術ですし、「PACKERS」に関しては「ANTI-DISASSEMBLY」に含まれてもおかしくありません。ということで、個人 的には「ANTI-DISASSEMBLY」および「ANTI-DEBUGGING」に分かれるのですが、ANTI-DEBUGGINGの方は前から触ったことがあったので、そこまで驚きの技術ではありませんでした。ということで、解析防止技術の中でも特に面白かったものが逆アセンブル自体を困難にする技術です。
そもそもなぜこんな面倒なことをするかと言うと、例えばC言語でゲームを作ったとしても、配布する時点では機械語の入った実行ファイルを公開します。そしてそれを逆アセンブルされると、理論的にはどんなプログラムでもソースコード(アセンブリ)が見られてしまいます。しかし、開発者としてはできればやめてほしいことも多いです。ゲームのストーリーからセーブデータの保存アルゴリズムまで見られてしまうのですから。ましてやパスワードやライセンスキーを要求するソフトウェアなどは解析されたらたまったものではありません。(実際に有名なソフトウェアでも解析されて構造がバレてしまうことが多々あります。)
そこで、頭の良い先人たちは、逆アセンブルを防ぐ技術(Anti-Disassembly)をいくつも考案してきました。とは言え、逆アセンブル自体は防げないので、逆アセンブルにより出力されたソースコード(アセンブリ)を、いかにツールに解析されにくく、そして人間にとって見にくくするかがポイントです。これを難読化といいます。
次のアセンブリを見てください。これは逆アセンブル結果ではなく、開発者が書くコードです。単純にSleep関数を実行するだけなのですが、これがバレたくない開発者は、コードに難読化を施します。
jmp short obfuscation db 0xE8 obfuscation: push 0x2A call Sleep
このコードの説明は次のような感じです。
1行目:ラベル"obfuscation"にジャンプ(そこを実行)
2行目:機械語にしたときに、ちょうどここに0xE8という1バイトのデータを埋め込む
3行目:"obfuscation"というラベルを作る
4行目:メモリに0x2Aというデータを入れておく
5行目:Sleep関数を呼び出す。(引数は上の0x2Aとなる)
つまり実行すると、
「obfuscationにジャンプ」 -> 「Sleep(0x2A)を実行」
となるだけのコードです。
このコードを機械語にし、さらに逆アセンブルすると次のようになります。(あくまでも出力例)
jmp short near ptr loc_2+1 loc_2: call near ptr 0x15ff2a71 or [ecx], dl inc eax db 0
本来なら前に書いたコードがそのまま結果として出力されてほしいのですが、見たところ全く違うものが出てきました。もう一度オリジナルのコードを書きます。
jmp short obfuscation db 0xE8 obfuscation: push 0x2A call Sleep
全然違いますね。ここで重要となるのは「db 0xE8」です。0xE8はintelのx86アーキテクチャの機械語において、call命令の最初のバイトです。したがって、逆アセンブルツール(逆アセンブラ)が機械語を解析する際、この0xE8をcall命令として読んでしまい、さらに次の機械語まで巻き込んでしまいます。
つまり本来なら次のように区切って解析してほしいのですが、
| 0xEB 0x01 (jmp) | 0xE8 (db) | 0x6A 0x2A (push) | 0xE8 ... (call) | ...
逐次的に解析するツールは次のように区切ってしまいます。
| 0xEB 0x01 (jmp) | 0xEB 0x6A 0x2A 0xE8 ... (call) | ... (or) | ... (inc) | ...
これだけの説明ではちょっと分かりにくいですが、このようにゴミデータを入れることによって、単純に上から解析するタイプのツールから、ある程度コードを守ることができます。(このように上から解析する逆アセンブリを"Linear Disassembly"と呼んでいます。)
今回紹介した本では、上述のような逆アセンブル防止技術だけでも、他にも様々な種類の技術が詳しく記載されています。
さいごに
この本の分かりやすいところは、たいてい実例を示して詳細に書かれていることです。それでいて必要なポイントだけがまとめられているので、この本一冊からたくさんの情報を得ることができます。
それから、マルウェアについての解析を中心としているので、各種技術が身に付くとともに、マルウェアの仕組みについても分かります。
残念ならが、調べた限りでは日本語版はありませんが、マルウェア解析技術の本としては海外でも非常に評価の高い一冊です。さらに、kosen14s所属の古月くんもこの本の電子書籍版を持っており、いかにこの本が凄いかを証明しています。
表紙の上で解剖されんとする宇宙人を見た際には、是非一度手にとって読んでみてください。