一般的なマルウェアと異なり、初期設定ファイルにより感染する新種のエクスプロイトが発見された。しかも攻撃が複数段階に分かれて行われるという珍しいものである。以下では、この独特なエクスプロイトの攻撃メカニズムを解明する。
この記事は、ESETが運営するマルウェアやセキュリティに関する情報サイト
「We Live Security」の記事を基に、日本向けの解説を加えて編集したものです。

ESETの研究者たちは毎日数千単位で新しいマルウェアのサンプルを入手し分析を行っている。そうした中で、とても注意を引いたサンプルが2015年の冒頭に登場した。それは、通常の実行ファイルではなかった。ある特定のプログラムに用いられるような初期設定ファイルだった。分析を進めるうちに突如、実際にこのファイルが不正なものであることが明らかになった。よく調べてみると、脆弱性を突いて不正コードを実行させることができるようになっていたのである。
エクスプロイト攻撃の概要
このエクスプロイト攻撃はバッファ・オーバーフローの脆弱性を利用したもので、「アップローダー!」(Uploader!)のデモ版において発生する。「アップローダー!」はKsoft社が開発したアプリケーションで、ユーザーはこれを使うと、FTP経由でインターネットにファイルをアップロードできるようになる。FTPのホスト名とユーザー名に関する初期設定が「uploadpref.dat」という名称のファイルに書き込まれている。
ESETの研究者たちは、分析を進めるうちにこの初期設定ファイルの正体を突き止めた。それは「アップローダー!」が起動する際にシステムにアクセスするのに用いられていたのである。しかも、2014年3月以降、このエクスプロイト攻撃の実証コードは、オンライン上で利用可能となっていたのだった。
脆弱性
「アップローダー!」の初期設定ファイルは、ユーザー名やファイルをアップロードするサーバーのホスト名といった、数行にまたがる一式のデータ列から構成されている。
アプリケーションは、ディスクから「uploadpref.dat」ファイルを解析するために標準C++のファイル入出力用のストリーム(std::ifstream)を使用する。ファイルからデータ列を読む一方で、全てのフィールドは、「in_stream.get」(buffer, sizeof(buffer), ‘\n’)を使うことにより、サイズを基にして正しくチェックされる。
しかし、暗号化されたパスワードを含んでいる最後のフィールドは、「in_stream >> buffer」(バッファはスタック上にある)というコード列を使う。もしも「in_stream.width(…)」が呼び出されなければ「in_stream >> buffer」は結果的に、空白またはファイルの終端(End Of File)に達するまでスタックに対してファイルの内容をコピーしてしまう。

「暗号化されたパスワード」(encrypted_password)を「ストリーム内」(in_stream)に呼び出す問題点
ESETがこの問題についてKsoft社に連絡を取り問い合わせたところ、わずか24時間以内にKsoft社から「アップローダー!」の新バージョン(3.6)がリリースされることとなった。
コード実行はどのように引き起こされるか
ESETが分析したエクスプロイトの場合、ファイルの内容が80バイトという固定サイズのバッファ変数を超えてスタックへとコピーされるようになっていた。「例外処理」(SEH)が上書きされた上で、最初のシェルコードがコピーされる。そのコピーは、無効なアドレスを書こうと試みる一方でページ違反を起こしつつ、アドレスがスタックの終端に達するという例外によって停止する。
この後、攻撃者によってコントロールされた「例外ハンドラ」が呼び出される。「アップローダー!」のアドレス空間の内部ではコマンドの「pop ecx」が2度、そして、「ret gadget」(retで終わる命令列)が設定されており、最終的には、ガジェットはスタック上で最初のシェルコードの実行を可能にする。


もちろん、SEHベースのエクスプロイト自体、特に新しいわけではない(この点についてさらに詳しく知りたいのであれば、ウェブサイト上にこの主題についての「Corelan Team」の非常に良い記事があるので、そちらを参照していただきたい)。Microsoft社が提供する「SEOH」(例外処理の上書き保護)は、そのようなエクスプロイトの実行を緩和しようとするものだが、「アップローダー!」のアプリケーションでは機能しない。Windowsサーバー上であれば、サーバーを複数ユーザーが管理・運用できるようにすることによって機能させることができる。具体的には、Microsoft社が無償提供している脆弱性緩和ツールであるEMETのユーザーインターフェイスにおいて、この設定は変更可能である。
ここで取り上げるエクスプロイトは、こうした概念実証用コードに基づいている。つまりコードには「178 pop」「pop」「ret gadgets」とあるにもかかわらず、このエクスプロイトは「40bf38」に見いだされるものと全く同じものを使っている。これは、シェルコードや次の段階などの他の部分がマルウェア作成者によって付け加えられたと考えられる。

概念実証用コードから得られた「uploadpref.dat」の冒頭部分

不正な設定ファイルから得られた「uploadpref.dat」の冒頭部分
多段階攻撃
エクスプロイトは、最終的なペイロードが実行されるまでに、複数のステージを経る。以下ではそのステージごとの説明を簡単に行う。
1)ステージ・ゼロ
すでに述べたようにSHEハンドラは「pop ecx」「pop ecx」「ret gadget」を指し、最初のシェルコードに統御フローを渡す。
これらの最初の指示については、「shell_code_1」とここで呼んでいる次のステージのアンパックを行う。つまりそれは、2バイトの語(バイナリ文字列)から1バイトの値(データ)を計算して、同じメモリ空間にその結果を書き込む。この方法を用いて、ステージ1におけるコード化をファイル内の大文字だけにすることを可能にする。

最初のシェルコードのアンパック機能
ステージ1
「ステージ0」の終わりに、「uploadpref.dat」ファイルの全内容がメモリに読み込まれる。最初は何が起こっているのか判然としない。というのは、コードがDLL名と機能のハッシュ値を用いて「プロセス環境ブロック」(PEB)におけるWindowsのAPI機能を探すためである。機能の名前を構成している小文字の個々の16進法の値の合計を計算し、それに2が掛けられる。
プログラミング言語の一つであるパイソン(Python)のハッシュ値のアルゴリズムは、次のようになる。
def hash_name(name):
result = 0
for c in name:
result = 2 * (result + (ord(c) | 0x60))
return result
興味深いことにこのアルゴリズムは、クリス・アンレーとジョン・ヒースマンの『シェルコード屋ハンドブック』というタイトルの本に掲載されている例と、全く同じものが使われている(Chris Anley & John Heasman, The Shellcoder’s Handbook: Discovering and Exploiting Security Holes, 2nd edition, p.145.)。
APIの呼び出しが解決すると、「shell_code_1」は「uploadpref.dat」ファイルと同じサイズの2つのバッファを割り当てる。最初に、ファイルの全内容がコピーされ、次に、そのまま放置される。それから、オフセットの「0x10」にある最初のブロックに飛ばされる。この「0x10」に次のステージが隠されているのである。偽装された「C」の概要は以下となっている。
HANDLE f = CreateFileA(“uploadpref.dat”, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
DWORD uploadpref_size = GetFileSize(f, 0);
char * memblock1 = VirtualAlloc(NULL, uploadpref_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
char * memblock2 = VirtualAlloc(NULL, uploadpref_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
ReadFile(f, memblock1, uploadpref_size);
stage_2 = &memblock1[0x10];
stage_2(&memblock1[0x650], memblock2);
// memblock2 is also pushed so that returning from stage_2 will jump at offset 0 in memblock2
ステージ2
ここでは、「0x650」にあるバッファが解凍されて、いくらか能率が悪いアルゴリズムを伴い以前に割り当てられたバッファ「memblock2」にする機能が作動する。データ量が増え、このバッファの長さは3,632バイトとなる。その後、制御フローは「memblock2」の最初にリダイレクトされる。そして今や、ステージ3へと進んでいることになる。
ステージ3
このステージでは「uploadpref.dat」が再び開かれる。そしてそのファイルに含まれる「PE」実行ファイル(32および64ビットのMicrosoft Windowsで使用される)を解凍する。解凍は、オフセットされた「0x1600」から始まり、新たに割り当てられたバッファが現れる。解凍のアルゴリズムは、ステージ2において使用されているものと同じである。
次に、停止モードにおいて新たなプロセスが作成される。そして、新たな実行ファイルが挿し挟まれ、プログラムの実行が始まる。
「uploadpref.dat」から抽出された「PE」実行ファイルは、長さが56,832バイトあり、不正なリモートアクセス・ツールをダウンロードして、実行する。
不正「uploadpref.dat」ファイル概観
要約すれば、不正な「uploadpref.dat」ファイルの全内容は以下の通り。

15のエントリーのうち、1~15までを示す
不正ペイロード
エクスプロイトの成功の後、新たなプロセスが「uploadpref.dat」ファイルに埋め込まれていた「PE」ファイルとともに作られる。この新しいプロセスは「ステージ・ファイナル」すなわち標的型攻撃でよく用いられる遠隔操作ツール(RAT)である「Gh0st RAT」をダウンロードし実行する。
ステージ1ダウンローダーの永続性
このモジュールは、オリジナルのエクスプロイト・ファイルと「Upload 3.5!.exe」ファイルを「msfeedssync.exe」としてコピーすることによって、ユーザーのアプリケーション・データのディレクトリに永続的に定着させる。そして、スタート・メニューの「スタートアップ」フォルダ内にある実行ファイルに対してショートカットを付加する。再起動すると、エクスプロイトは再びトリガーを引き、全てのステップが繰り返される。
以下のファイルが永続的な定着のためにインストールされる。

3つエントリーされているうちの1~3を示す


感染したコンピューターのスタートアップ・フォルダにインストールされたショートカット
ペイロードのダウンロード
コードの永続化が確かめられると、実行ファイルはHTTPを通じて不正ペイロードを呼び込むだろう。2つのスレッドが30分のインターバルの後に開始される。おのおののスレッドが使用するHTTPユーザー/エージェントに基づいて、最初のスレッドを「Alan_function」と呼び、2つ目のスレッドを「BFunction」と呼ぶ。
おのおののスレッドは、同じドメイン名を用いた異なるURLからペイロードをダウンロードしようと試みる。ダウンロードされたファイルが解凍されると、2つの機能が別々にコードを開始する。
- 「Alan_function」は「PE」実行ファイルを用意し、開始する。
- 「BFunction」は、DLLファイルを用意し、機能をエクスポートする「TestFunction 」をロードし呼び出す。

2つのエントリーのうち、1~2を示す
ESETでは、2015年3月に用いられた最初の攻撃手法のみを解析している。ここで述べているダウンロードされた実行ファイルについては、「TestFunction」と呼ばれるエクスポートされた機能とともにDLLファイルをアンパックすることによって、「ステージ1ダウンローダー」にしっかりとリンクされている。
このDLLファイルは「BFunction」スレッドに運ばれ、同じ結果を直接引き起こす。
最終的なペイロードは、「Gh0st RAT」を基にしたトロイの木馬なのである。
トロイの木馬
最後のステージでは、「Gh0st RAT」に基づいた、遠隔的にスパイ行為を行うマルウェアの亜種を投入する。「Gh0st RAT」は、過去にいろいろな研究者によって完全に分析されて、文書化されている。
「Gh0st RAT」のネットワークプロトコルには5つの文字列が含まれ、これによって実行内容が決まる。「Gh0st RAT」の亜種の場合、コード「A1CEA」が用いられている。A1CEAによる攻撃が特定のある集団にのみ適用されるのかどうかは不明である。A1CEAと関係がありそうな説明は、以下のようにオンライン上にある。
- Sample seen in December 2013 with this campaign code on Malwr
- Snort rule added on March 3rd 2015
- Analysis from Wins in Korea
サンプルにあるC&Cサーバーは「TCPポート2015」 上にある「www.phw2015.com」である。書き込みのときにはドメインが「112.67.10.110」となる。
「Gh0st RAT」ソースに対する他のわずかな変更点は以下の通りである。
- コンピューターの仕様情報を収集する機能の存在
- 不正なコンポーネントをロードする「テスト機能」(TestFunction)の存在
「Gh0st RAT」に必要な関数が全てそろっており、キーロガー機能が可能となっていることが確認されている。
結論
このエクスプロイトが奇妙なのは、「アップローダー!」というアプリケーションが大掛かりな仕組みを持っていないことに起因する。多段階攻撃によっていったい何を引き起こそうとしているのか、その前後関係から理解するのは極めて困難である。場合によっては、このエクスプロイトは、特定の標的を困惑させるのが目的なのかもしれない。最初の攻撃が行われ、その内容を解析した今もなお、十分には理解できていない。作成者(たち)は、設定ファイルをこの「特別な」ファイルと置き換えるようにユーザーを納得させるために、わざわざソーシャル・エンジニアリングの手法を用いたのだろうか。それとも彼らは、マルウェアの永続的な使用を隠すための一手段として、こうした多段階攻撃の技術を利用しただけなのだろうか。
(元の原稿執筆者は、ESETのマルウェア研究者マルク=エティエンヌ・M.レヴェイエ(Marc-Etienne M.Leveille)であり、解析にはヒューゴ・ジェネセ(Hugo Genese)が協力している)