マルウエアの多くには「パッキング(packing)」と呼ばれる処理が施されている。その目的は、プログラムコードの難読化だ。パッキングを施すことによって、セキュリティーソフトによる検知やマルウエア解析者による解析を困難にする。
今回はこのパッキングの仕組みと、パッキングされたマルウエアの解析方法を解説しよう。
マルウエアを圧縮して難読化
パッキングとは、EXEファイルやDLL▼ファイルなどの実行ファイルを、実行可能な状態のまま圧縮する処理を指す。一般的なファイルをZIP形式などで圧縮した場合、拡張子が変わりそのままでは実行できない。圧縮・解凍ソフトなどで解凍(展開)して初めて使用可能になる。
これに対して、パッキングで実行ファイルを圧縮しても拡張子は変わらない。そのままダブルクリックすれば実行される。展開するためのソフトウエアは不要である。
実行ファイルにパッキングを施すソフトウエアを「パッカー(packer)」と呼ぶ。広く知られているパッカーの1つが「UPX▼」だ。このUPXは、マルウエアだけではなく、正規のソフトウエアのパッキングにも使用されている。パッキング前の実行ファイルの構造やUPXの設定によっては、ファイルサイズを半分程度に圧縮できる。
また、パッキングには圧縮だけではなく難読化という効果もある。圧縮することで元のプログラムの構造やデータが変化して、結果的に難読化される。
このためマルウエア開発者の多くは、圧縮ではなく難読化のためにパッカーを使用する。これにより、セキュリティーソフトのシグネチャーを用いた検知や、マルウエア解析者の解析から逃れることをもくろむわけだ。
圧縮よりも難読化を主目的としたソフトウエアは、「クリプター(crypter)」あるいは「オブファスケーター(obfuscator)」などと呼ぶ場合がある。ただし、実行ファイルを圧縮して難読化するソフトウエアは、パッカーと総称するケースが多い。
コードを圧縮して展開処理を追加
次に、パッカーが実行ファイルをパッキングする流れを具体的に見ていこう(図1)。
あるプログラムコードに対してパッカーを使用すると、パッカーは元のプログラムコードを圧縮する。同時にパッカーは圧縮コードを展開するための小さなコード(展開コード)を作成し、パッキング後のEXEファイルに保存する。また、展開コードを呼び出す処理を記述したコードも作成する。この呼び出し処理が、パッキング後のEXEファイルの実行開始地点となる。
プログラムコードが圧縮されているため、パッキング後のEXEファイルは、元のEXEファイルよりもファイルサイズが小さくなることがほとんどである。圧縮されることによってプログラムの構造やデータが変化し、パッキング後のEXEファイルから元のプログラムコードを推測するのが難しくなる。
ただし難読化を主目的としたパッカーの場合、プログラムコードに難読化の処理を埋め込むため、元のEXEファイルよりもファイルサイズが大きくなることもある。