「Waterbear(ウォーターベア)」は、2010 年 10 月から活動が確認されているサイバー攻撃キャンペーン、およびキャンペーンで使用されたマルウェアの呼称です。Waterbearの背後にいるとされる攻撃集団「BlackTech(ブラックテック)」は、台湾をはじめとして日本や香港を含む東アジアのテクノロジー企業と政府機関を対象としたサイバー諜報活動を行い、「PLEAD」や「Shrouded Crossbow」などの悪名高い攻撃キャンペーンにも関与しています。以前に確認されたWaterbearは、「ローダ」コンポーネントを用いることによって、最終的な攻撃を実行する「ペイロード」を読み込み実行するものでした。ペイロードは大抵、遠隔から追加のモジュールを受け取り読み込むことのできるバックドア型マルウェア(以下バックドア)でした。しかし、今回確認されたWaterbearでは、APIフックの手法を採用することによって特定のセキュリティ対策製品から自身のネットワーク動作を隠蔽するという、新しい目的を持つペイロードが発見されました。フックするべきAPIを知っているということは、セキュリティ対策製品がクライアントの端末およびネットワーク上の情報をどのように収集するかを攻撃者が熟知している可能性があります。解析の結果、この特定のセキュリティ対策製品のベンダーはアジア太平洋地域を拠点とすることが確認されました。これはBlackTechの攻撃対象地域と一致します。ただし、このAPIフックのシェルコードは一般的な方法が採用されており、シェルコードを別のセキュリティ対策製品用に応用することも可能です。そのため、今後の攻撃においても同じ手口が使用される可能性があります。
■Waterbearの特徴
Waterbearはそれぞれ役割を担うモジュール型マルウェアを利用します。RC4で暗号化されたモジュールはDLLローダにより復号され、ペイロードを実行します。大抵の場合、ペイロードは、攻撃の第一段階のバックドアで、これが遠隔の攻撃者から他の実行ファイルを受け取り、読み込みます。このような第一段階のバックドアは、2つのタイプに分類することができます。1つは遠隔操作用のサーバ(C&Cサーバ)に接続するもの、2つ目は、特定のポートで外部からの指令をリッスン(待ち受け)するものです。興味深い点として、Windowsのネイティブディレクトリではなく、セキュリティ対策製品やサードパーティのライブラリのファイルパスが、ペイロード内にハードコードされていた事例も確認しています。これは、攻撃対象のPC環境について、攻撃者が事前に情報を入手していることを示唆しています。また、マルウェアが自身のC&Cサーバとして内部IPアドレスを参照している事例も頻繁に確認されています。これはそのマルウェアの活動開始以前に既にネットワーク内に侵入していたことを示しており、二次的ペイロードとして使用されているものと判断することができます。
■典型的なWaterbearの感染経路
Waterbearの感染は、改変されたDLLローダの起動から始まります(図1)。トレンドマイクロは、DLLローダを起動させる2つの手法を確認しました。1つは、正規サーバに元から存在するアプリケーションを改変し、不正なDLLローダをインポートしてロードする手法です。もう1つは、DLLプリロード(DLLハイジャック、DLLサイドローディング攻撃などとも言う)を実行する手法です。Windowsサービスのいくつかは、ブート時に、ハードコードされたDLL名またはパスによって外部のDLLを読み込もうとします。しかし、Windowsのサポートが終了しているレガシーDLLであったり、または、もともとWindowsシステムDLLにはないサードパーティによるDLLであったりした場合、攻撃者は、改変したDLLにハードコードされたDLLの名前を付け、DLLのローディング中に検索されるディレクトリのうちのどれかに配置します。このような手法は特に「Phantom DLLハイジャック」と呼ばれることもあります。読み込まれた不正なDLLは、ロードしたサービスと同じアクセス許可レベルで実行されます。以下、Waterbearで利用される典型的な第一段階のバックドアについて、観察された事例を基に解説します。
■第一段階のバックドア型マルウェア
トレンドマイクロは、環境変数%PATH% のフォルダのうちの1つの中に「ociw32.dll」というファイル名のDLLを読み込むローダを確認しました。 このDLLファイル名は、ブート時にMicrosoft 分散トランザクションコーディネーター(MSDTC)サービスによって読み込まれる「mtxoci.dll」内にハードコードされています。「mtxoci.dll」は、最初にレジストリキー「HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSDTC\MTxOCI」をクエリして、値「OracleOciLib」が存在するかを確認します。存在する場合、内部のデータを取得し、対応するライブラリを読み込みます。値が存在しない場合、「mtxoci.dll」は、代わりに「ociw32.dll」の読み込みを試みます。調査中、感染コンピュータからは値「OracleOciLib」が削除されていることが確認されました(図2)。これにより、「ociw32.dll」がロードされ、実行されるようになります。攻撃者はDLLローダのファイル名を「ociw32.dll」にすることで、感染コンピュータ上で実行させます。
DLLローダが実行されると、ハードコードされたパスを検索し、該当するペイロード、つまり暗号化されたシェルコードの復号を試みます。復号アルゴリズムはRC4であり、ハードコードされたパスを使用して復号キーを形成します。復号されたペイロードが有効であれば、既存のWindowsサービス「svchost.exe」によって実行される「LanmanServer」を選択し、復号されたシェルコードをサービスにインジェクトします。ほとんどの場合ペイロードは第一段階のバックドアであり、主な目的は、第二段階のペイロードの取得です。C&Cサーバに接続するか、ポートを開いて外部接続を待機して受け取った実行ファイルを読み込むことにより、第二段階のペイロードが読み込まれます。
■第一段階のバックドアの構造
Waterbearの第一段階のバックドアには、外部との通信および読み込まれるファイルの実行に必要な情報が含まれています。
- オフセット0x00、サイズ0x10:関数の暗号化・復号キー
- オフセット0x10、サイズ0x04:0x0BB8(予約)
- オフセット0x14、サイズ0x10:バージョン(0.13、0.14、0.16など)
- オフセット0x24、サイズ0x10:Mutexまたは予約バイト
- オフセット0x34、サイズ0x78:キー0xFFでXOR暗号化されるC&Cサーバアドレス。バックドアが特定のポートで待ち受けることを意図している場合、このセクションは0x00で埋められる
- オフセット0xAC、サイズ0x02:ポート
- オフセット0xAE、サイズ0x5A:予約バイト
- テーブル:ペイロードの機能アドレステーブル。ブロックは最初0x00で埋められ、実行時に拡散する
- 表:関数のサイズ
- テーブル:APIアドレステーブル。ブロックは最初0x00で埋められ、実行時に読み込まれたAPIアドレスで埋められる
- 表:動的ロードAPIのAPIハッシュ
- 読み込まれるDLL名とAPIの数の一覧
■ペイロード実行時のメモリスキャン回避機能
ペイロード実行時にメモリをスキャンされないようにするため、不正活動の実行前にすべての関数ブロックが暗号化されます。その後、関数を使用する必要があるときは毎回関数を復号して実行し、再度関数を暗号化しなおします(図4)。その後関数が使用されない場合は、 乱雑化するための関数が利用されます(図6)。この関数は、ランダムな値でバイトを撹拌し、入力ブロックを回復不能にします。これにより、特定のセキュリティ対策製品による検出をさらに回避します。
■異色なWaterbearを確認
調査中、これまでに確認されてきたWaterbearの事例とは異なる特殊な例を確認しました。この例の場合、DLLローダは2つのペイロードを読み込みました。1番目のペイロードは、これまで確認されたことのない機能が含まれていました。特定のセキュリティ対策製品にコードをインジェクトし、セキュリティ対策製品からバックドアを隠蔽するために、APIフックを実行する機能です。一方、2番目のペイロードは、上述した典型的なWaterbearの第一段階のバックドアでした。
どちらのペイロードも暗号化されて感染PCのディスクに格納され、同じサービス(ここではLanmanServer)にインジェクトされました。そして、ローダがファイルからペイロードを読み取って復号し、以下の条件でスレッドインジェクションを実行することを確認しました。
1)1番目のペイロードがディスク上に見つからなかった場合、ローダは2番目のペイロードを読み込まず終了する
2)1番目のペイロードが無事復号され、サービスにインジェクトされると、最初のスレッドに何が起こったとしても、2番目のペイロードもロードされインジェクトされる
3)最初にインジェクトされたスレッドで、必要なセキュリティ対策製品の実行ファイルが見つからなかった場合、他の不正活動を実行せずにスレッドが終了する。スレッドのみが終了するが、サービスは引き続き実行されていることに注意
APIフックが実行されたかどうかに関係なく、ロードが完了すると2番目のペイロードであるバックドアが実行されます。
●APIフックで検出を回避
2番目のペイロードである、第一段階のバックドアの活動を隠蔽するため、1番目のペイロードはAPIフックを利用して特定のセキュリティ対策製品による検出を回避し、実行された関数の結果を置き換えます。 「ZwOpenProcess」と「GetExtendedTcpTable」という2つの異なるAPIをフックして、特定のプロセスを隠蔽します。ペイロードが改変するのは、セキュリティ対策製品のプロセスのメモリ内の関数のみで、元のシステムDLLファイルが変更されることはありません。
ペイロードは、2段階のシェルコードで構成されています。シェルコード1は、ハードコードされた名前を持つ特定のセキュリティ対策製品のプロセスを検出し、そのプロセスにシェルコード2をインジェクトします。 次に、シェルコード2は、標的のプロセス内でAPIフックを実行します。
●プロセス識別子(PID)を隠蔽する
隠蔽するPIDは、共有メモリ「Global \ <computer_name>」に格納されます。共有メモリが存在しない場合は、シェルコード1によって埋め込まれたPIDが使用されます。ここでのコードの意図は、Waterbearのバックドアの活動をセキュリティ対策製品から隠蔽することです。そのため、シェルコード1は、WindowsサービスのPIDにシェルコード1と続くバックドアの両方をインジェクトし、対象プロセスを隠蔽し、そのPIDをシェルコード2に埋め込みます。
●ntdll.dllで「ZwOpenProcess」をフックする
「ZwOpenProcess」をフックする目的は、セキュリティ対策製品によって特定のプロセスへアクセスされないようにするためです。「ZwOpenProcess」が呼び出されるたびに、インジェクトされたコードによって、開かれたプロセスが保護されたプロセスID一覧にあるPIDに該当するかどうかが最初にチェックされます。該当する場合、PIDが改変され、これにより別のWindowsサービスPIDが開かれることになります。
まず、フックされた関数をビルドし、「ntdll.dll」の最後に関数を書き込みます。この関数には、2つの部分が含まれます(図9)。
- PIDチェックを実行。 「ZwOpenProcess」によって開かれるPIDが、保護されたプロセスID一覧に存在するかどうかを繰り返しチェックする。存在する場合、開かれるPIDが、Waterbearのローダによって最初に書き込まれた別のWindowsサービスのPIDに置き換えられる
- PIDチェックの完了後、元の「ZwOpenProcess」を実行し、その結果を返す
次に、元の「ZwOpenProcess」アドレスの先頭に「push <ADDRESS> ret」と書き込みます。これによって、「ZwOpenProcess」が呼び出されると、「ZwOpenProcess」の改変されたバージョンが実行されます。
「ZwOpenProcess」のAPIフックは、「%temp%\ KERNELBASE.dll 」が感染PCに存在する場合にのみ実行されます。このチェックは、セキュリティ対策製品の特長に合わせて設計されている可能性があります。
●iphlpapi.dllの「GetExtendedTcpTable」および「GetRTTAndHopCount」フック
APIフックの次の部分は「GetExtendedTcpTable」をフックします。「GetExtendedTcpTable」は、アプリケーションで使用可能なTCPエンドポイントの一覧表を取得するために使用され、netstatなどのネットワーク関連コマンドで頻繁に使用されます。フックの目的は、特定のPIDのTCPエンドポイントの記録を削除することです。その目的のために、「GetExtendedTcpTable」と「GetRTTAndHopCount」の2つの関数を改変します。2つ目の関数「GetRTTAndHopCount」は、インジェクトされたフックコードを配置する場所として機能します。
「GetExtendedTcpTable」は、関数の先頭にある「GetRTTAndHopCount」へのジャンプのみを書き込みます。改変されるのはAPI「GetExtendedTcpTable」のコードの最初の5バイトのみです(図11)。
ルーチンの残りはすべて「GetRTTAndHopCount」に配置されます。コードの最初の部分では、[“GetRTTAndHopCount” + 0x3E]を戻りアドレスとしてpushし、元の「GetExtendedTcpTable」関数の最初の4つの命令を実行します。ここで 「GetExtendedTcpTable」は図11でジャンプする命令に既に置き換えられています。その後、「GetExtendedTcpTable」にジャンプし、関数を正常に実行し、戻り値を取得します。 このコードを図12に示します。
「GetExtendedTcpTable」が実行され、プロセスがコードの2番目の部分に戻った後、返されたTCPテーブルのすべての記録を繰り返しチェックします。隠蔽を意図するPIDが含まれる記録がある場合、対応する記録を削除し、テーブル内の記録番号を変更し、引き続き残りの記録をチェックします。 最後に、変更されたテーブルを返します。
この2つの関数を直接無効にするのでなく、APIフックを利用する手法によって、どちらの関数も一見正常に機能して値を返すため、ユーザが不審な動作に気付くことが困難になります。この場合影響を受けるプロセスはシェルコード1で指定されていますが、APIフックのロジックは非常に汎用的なものであるため、類似のシェルコードを他のベンダーのセキュリティ対策製品をフックする目的に変更することができます。
■結論
トレンドマイクロがバックドアの活動の隠蔽を試みるWaterbearを確認したのはこれが初めてです。セキュリティ対策製品名がハードコードされているということは、攻撃者が標的のシステム環境と利用されているセキュリティ対策製品を熟知していると推測することができます。攻撃者は、セキュリティ対策製品がクライアントの端末およびネットワークに関する情報を収集する方法に通じており、どのAPIをフックすればよいかも知っていると言えます。 APIフックのシェルコードは非常に汎用的なものが利用されており、将来的には対象セキュリティ対策製品を変更することも予測されるため、Waterbearの攻撃活動が検出しにくくなることが予測されます。
■ 侵入の痕跡(Indicators of Compromise、IoC )
今回の記事に関する侵入の痕跡はこちらを参照してください。
参考記事:
- 「Waterbear is Back, Uses API Hooking to Evade Security Product Detection」
By Vickie Su, Anita Hsieh, and Dove Chiu
翻訳: 室賀 美和(Core Technology Marketing, Trend Micro™ Research)