IDAとAPT28についての考察

By The Cylance Threat Research Team

本ブログ記事は、2019年7月10日に米国で公開された抄訳版です。原文はこちらからご覧頂けます。

IDAとAPT28についての考察

このドキュメントでは、最近公開されたAPT28のサンプルを事前解析する一環として作成する、Hex-RaysのInteractive Disassembler(IDA)シグネチャの開発に用いる方法を明らかにします。公開されたサンプルの内部関数、機能、動作については触れません。IDA逆アセンブラのシグネチャ生成に使用するIDA Flairにアクセスするには、有効なHex-Raysサブスクリプションが必要です。

5月17日、the U.S. CyberCom Cyber National Mission Force (CNMF) は、APT28の新しいマルウェアサンプルへのVirusTotalリンクをツイートしました。 このサンプルやその発見に付随する状況については、情報が提供されていません。  

公開されたサンプルのSHA256ハッシュは、以下のとおりです。  
b40909ac0b70b7bd82465dfc7761a6b4e0df55b894dd42290e3f72cb4280fa44 

研究者たちの意見を総合すると、このサンプルはXトンネル(別名XAPS)であると思われます。APT28はこのツールを使用して、ファイアウォールの内側にある侵害されたホストをトラフィックプロキシとして機能させます。これにより、外部のホストから発信された、攻撃者が制御するトラフィックを他の内部標的に中継することができます。この内部標的は、境界のトラフィックポリシーのために通常はアクセスできないものです。 

実際に使われているXトンネルが初めて発見されたのは2013年5月であり、米国の民主党全国委員会(DNC)に対する2016年のハッキングなど、過去のセキュリティ侵害で使用されたものと思われます。  

その他の実際に発見された(In-the-Wild: ITW)Xトンネルのビルドを解析すると、Xトンネルの機能が明らかになります。その例として、リモートコマンドの実行、UDPトンネリング、TLS暗号化、プロキシサポート、HTTP Keep-Aliveヘッダー経由のパーシスタントHTTPなどが挙げられます。

以前のバージョンでは、サイズが約1~2MBでした。2015年に発見されたコードが難読化されているバージョンでは、規模が拡大する傾向が見られました。CNMFがアップロードしたサンプルは3.2MBに達していました。 

このようなファイルサイズは、コードの難読化/仮想化や静的リンク、組み込みリソースを示唆しています。静的リンクによって構造が自己完結型となり、この自己完結性は、被害者のネットワーク内で活動する脅威アクターにとって優先度の高いものです。コードの難読化は解析の試みを妨げますが、アンチウイルス(AV)ソフトウェアから見ると、不審なサンプルである可能性がより高まることになります。  

サンプル内の証拠は、これがMicrosoft Visual C++で作成されたことを示しています。標的のコンピューターに対する感染計画を立てるとき、2つの選択肢が作成者に与えられます。すなわち、対応する(必要な)Visual C++再頒布可能パッケージがインストールされていることを前提とする方法と、必要な実行可能コードをファイル自体にすべて組み込む(リンクさせる)方法です。後者の静的リンクの方法を採るとファイルのサイズが増加しますが、実行が成功する確率も高くなります。

サンプルのXトンネルバイナリがMicrosoft Visual C++で作成されたことを示唆する要因を、以下にいくつか示します。 

1.     例外データのディレクトリを含む.pdataセクションの存在。コンパイラは、PE32+/64ビットバイナリの例外処理メタデータをこのセクションに格納します。このセクションは、最も単純なC/C++ Hello World アプリケーションにも存在します(Microsoft Visual C++ランタイムにリンクしている場合)。 

2.     特にC++では、マングルされた関数名の存在と、文字列出力内の標準テンプレートライブラリ namespaces/containers/classes (std, vector, ios) への参照の存在 

3.     PE Rich header ヘッダーの解析出力

Visual C++ PEの動的リンクの代替案として、よく見られるのがmscvpXXX.dllのインポートです。XXXはVisual Studioのリリース番号に対応しています(120はVisual Studio 2013、140はVisual Studio 2015、など)。 

IDAを使用したサンプルの逆アセンブリにより、膨大な量の実行可能コードが明らかになっています。どのようなアプローチをとれば、この扱いにくいファイルの解析に対処し、その設計と機能にすばやく迫ることができるのでしょうか。 

IDAの「Navigator」ツールバーを使用すると、サンプルの実行可能コードとデータを視覚的に分解できます。サンプルのロード時にFLIRTシグネチャの自動使用が無効の場合は(「Kernel Options 2」を参照)、単純なPythonワンライナーを使用して関数の数を測定できます。 


Python>len(list(idautils.Functions()))
7533

図1:IDAPythonによる関数のカウント

ここでは64ビットのMicrosoft Visual C++バイナリを扱っているため、IDAに付属する次の適切なデフォルトシグネチャを適用できます(「General」>「Kernel Options 2」で最初に「Use flirt signatures」を再選択します)。 vc64rtf, vc64ucrt。 

シグネチャのサブビューは、約1,600の関数が(無害の)ライブラリコードとして識別されていることを示しています。 


図2:IDAによって提供された1回目のデフォルトシグネチャ  

公開されたXトンネルサンプルの大部分は、OpenSSL TLS/SSLライブラリの同じバージョンにリンクしています。このサンプルの文字列出力は、サンプルが次のスイートであることも示しています。1.0.1e 11 Feb 2013。  

自らこの解析を実践しているアナリストは、文字列出力に繰り返し現れる別の識別子"poco"にも気づいていることでしょう。Googleの検索結果は、これがC++フレームワークであることを示しています。エンドポイントセキュリティの先を行く継続的な取り組みを通じて、作成者たちがフレームワークを使用してXトンネルの改良に努めていることは明らかです。 

カスタムIDA FLIRTシグネチャを活用し、(無害のライブラリコードを識別することで)できるだけ多くの空白を埋めることにより、サンプルの重要な解析結果を得るために要する時間を短縮できます。重要な(興味深い)部分を理解することに重点的に取り組むことで、実用的な脅威インテリジェンスの提供を促進できます。

文字列出力は、Pocoフレームワークのバージョン1.7.3が使用されたことを示しています。この情報に基づき、静的ライブラリ(.lib)を作成してカスタムIDAシグネチャを派生させることができます。  

注:Flairツールのpcf(COFFパーサー)とsigmake(Signature File Maker)を、Hex-RaysのWebサイトからzipダウンロード形式で入手できます(有効なサブスクリプションが必要)。MacとWindowsの両方のバイナリが含まれており、下記の例の代替パスはzipを解凍した場所(およびWindowsを使用している場合はオペレーティングシステム)を示しています。

ライブラリの作成にはVisual Studioのどのバージョンを使用すべきか。これが、私たちが最初に答えるべき質問です。さらに、それは重要なことなのかという好奇心にも応えます(答え:はい、重要です。少なくとも、テストした少数のVisual Studioのデフォルトインストールではそう言えます)。 

PEのRichヘッダーは、バイナリの作成に使用したコンパイラ/リンカーに関するメタデータを保持しています。広く利用されているツールを使用してRichヘッダーを解析した結果を以下に示します。 


図3:サンプル内に埋め込まれたRichヘッダー  

これが偽造でないと仮定すると、最初のビルドの試みにはVisual Studio 2010 RTMを使用することになります。 

注:OpenSSL/Poco静的ライブラリの作成は、作成者の標準のWindows 7 SP1 x86解析環境で行われました。ネイティブx64環境下での作成は、下記の各手順にわずかな変更を加えるだけです。

Pocoフレームワークの1.7.3ソースコードは、Githubから簡単にダウンロードできます。ビルドの手順は容易に実行できます(READMEの"Building on Windows"を参照してください)。唯一気をつけてほしいのは、最初に存在すべきOpenSSLとの依存関係です。私たちはMySQLへの依存を削除するため、ビルドプロセスにわずかな調整を行います。これを行うには、Pocoコンポーネントファイルを編集します。 

OpenSSL .libファイルの作成も簡単です。ドキュメントに記載されているように、ActiveState ActivePerlなど、いくつかの前提条件をインストールする必要があります。その際、perl.exeが%PATH%にあることを確認してください(デフォルト使用時はインストーラによって行われる)。 

ここでのサンプルは64ビットであるため、Visual Studio x64 Cross Toolsコマンドプロンプトを使用します(Windowsの「スタート」メニューで「 Visual Studio Tools)」を参照)。

OpenSSLのビルドマニュアルに従って、解凍されたソースコードディレクトリで次のコマンドを実行すると、必要なlibeay32.libとssleay32.libの静的ライブラリが作成されます。その結果、Pocoのビルドが可能になり、最終的にIDAシグネチャを生成することができます。 

perl Configure VC-WIN64A
ms\do_win64
anmake -f ms\nt.mak

図4:OpenSSL静的ライブラリの作成

エラーなしでビルドプロセスが完了すると、静的ライブラリがout32フォルダーに作成されます。


図5:OpenSSL x64 1.0.1eの静的ライブラリ

OpenSSLライブラリが利用可能になったので、今度はPoco C++フレームワークのライブラリを作成します。新たに作成したOpenSSLライブラリの場所を示すようにPoco buildwin.cmdファイルを変更し、OpenSSLヘッダーファイルの場所を提供する必要があります。以下に、編集済みのbuildwin.cmdファイルを示します。

rem Change OPENSSL_DIR to match your setup
set OPENSSL_DIR=E:\Code\openssl-1.0.1e.tar\openssl-1.0.1e
set OPENSSL_INCLUDE=%OPENSSL_DIR%\inc32
set OPENSSL_LIB=%OPENSSL_DIR%\out32dll;%OPENSSL_DIR%\lib\VC
set INCLUDE=%INCLUDE%;%OPENSSL_INCLUDE%
set LIB=%LIB%;%OPENSSL_LIB%

図6:Pocoフレームワークbuildwin.cmdの環境変数

OPENSSL_INCLUDE変数にinc32が使用されているのがわかります。1.0.1e tarballには、Windowsホストで正しく解凍できない、includeからinc32へのシンボリックリンクが含まれており、includeフォルダーの.hファイルは0バイトとなっています。

それでは、Visual Studio 2010 x64コマンドプロンプトを使用して、Pocoフレームワークの静的ライブラリを作成します。


buildwin.cmd 100 build static_mt release x64 nosamples notests

図7:Poco静的ライブラリを作成するコマンド

生成されたライブラリはlib64フォルダーにあります。


図8:Pocoフレームワークの静的ライブラリ

PocoとOpenSSLのライブラリファイルは確保したので、今度はIDAシグネチャを生成します。

pcfsigmakeの構文はシンプルです。最初に、Hex-Raysから入手可能なFlair .zipダウンロード内にあるpcfを使用して、ライブラリファイルごとにパターンファイルを派生させます。

以下に、Mac OSのOpenSSLライブラリにおけるpcfの実行例を示します(.libはビルドVMからローカルにコピーされました)。

./flair72/bin/mac/pcf libeay32.lib
libeay32.lib: skipped 98, total 5646

図9:MacでのIDAパターンファイルの生成

Windowsでは、以下のコマンドがこれに相当します。


.\flair72\bin\win\pcf.exe libeay32.lib

図10:WindowsでのIDAパターンファイルの生成

ここでシグネチャファイルを生成し、その結果衝突が起きた場合はこれを解決します。衝突が起きるのは、.libファイル内のオブジェクトファイルから取得された生成済みの命令コードが複数のサブルーチンで重複している場合です。Flairシグネチャ生成プログラムは衝突を解決しません。衝突を手動で解決するか、それとも無視するかはユーザー次第です。

識別された衝突の数と確保できる時間に応じて、衝突しているすべてのサブルーチンに名前を付けずにおくか、.excファイルを調べて名前の解決、割り当てを手動で行うかを選ぶことができます。

シグネチャファイルに名前フィールドを追加すると役立ちます。このフィールドはFLAIR選択ダイアログに表示され、カスタムシグネチャの識別が容易になります。これが特に当てはまるのは、別個のコンパイラフラグを設定した異なるバージョンを多数作成する場合です。

./flair72/bin/mac/sigmake -n"OpenSSL 1.0.1e x64 VS2010 LIBEAY32 Od"
libeay32.pat openssl-101e-x64-vs2010-libeay32.sig
openssl-101e-x64-vs2010-libeay32-Od.sig: modules/leaves: 2971/5438,
COLLISIONS: 114

図11:FLAIRシグネチャ作成のコマンドライン

この例では最も楽な方法を選んですべての衝突を無視し、生成された.excファイルの先頭にある4つのコメント行を削除します。sigmakeを再度実行して、.excファイルのコンテンツが組み込まれるように指示します。出力がない場合は成功です。この手順をssleay32.libに対しても繰り返します。

最後のステップとして、IDAのインストール先にシグネチャをコピーする必要があります。Mac OSのPE/COFFファイルでは次のようになります。


/Applications/IDA XXX YYY/ida.app/Contents/MacOS/sig/pc

図12:MacでのIDAシグネチャファイルの場所

Windowsのインストールでは、以下がデフォルトの場所となります。


Program Files\IDA XXX\sig\pc

図13:WindowsでのIDAシグネチャファイルの場所

シグネチャが適切に配置されたのでサンプルに適用することができます(「File」>「Load File」>「FLIRT Signature File」を選択)。IDAの再起動は不要です。

シグネチャのサブビューは、シグネチャが正しく適用されていることを示しています。


図14:適用済みのPocoフレームワークのシグネチャ

これをOpenSSLシグネチャで補完します。


図15:適用済みのOpenSSLシグネチャ

作業は進んでいますが、OpenSSL関数の多くはまだ捕捉されていません。逆アセンブリによるコードのスキミングでは、依然として標準関数としてフラグが立てられており、OpenSSLコードの文字列アノテーション(コメント)は一目瞭然です。シグネチャ生成の何かが不適切に実行されています。

OpenSSLソースコード(ヒント: grep)を使用してIDAの逆アセンブリ文字列(sub_180097950に存在する“retcode=”など)を相互参照することで、カスタムシグネチャを改善する開始点として機能するルーチンを特定できます。

説明を簡潔にするために、IDAのsub_180097950が./crypto/conf/conf_mod.cにあるOpenSSL関数のmodule_runであるとします。ERR_add_error_data関数の文字列定数は、IDA生成の相互参照コメントに(一意に)マップされます。

libeay32.patを調べると、module_run関数の現行パターンがわかります。


図16:module_runのFLAIRパターン

逆アセンブルすると次のようになります。


図17:Visual Studio 2010の“Ox”を使用してコンパイルされたOpenSSLのmodule_run

これをサンプルのmodule_runと比較します。


図18:sub_180097950命令コード

明らかに、Visual Studio 2010でコンパイルした.libによって、異なる一連の命令コードが生成されています。

.lib内のオブジェクトファイルが異なる命令コードを持つ場合、私たちの派生シグネチャはサンプルのシグネチャと一致しません。「ストック」ビルドの場合と同様に、正当なOpenSSLコードが欠落しています。

.patファイルのmodule_run命令コードの逆アセンブリは、2バイトのホットパッチアラインされた[1]push rbx命令(40 53、x64ではホットパッチは暗黙的)で開始されます。それに続いて、不揮発性レジスタrbx、rsi、rdiの呼び出し先による保存が、x64の呼び出し規則に基づいて行われます。

この同じ関数におけるAPT28の関数プロローグは、r8、r9、rcx、rdxレジスタのスタックでspillまたはhomeスペースが使用されていることを示しています。

Raymond Chen氏のご厚意により、 2011年のブログ記事[2]からコンパイラ出力の差異についての説明を転載させてもらいます。

「コンパイラの最適化を無効にすると、Visual C++ x64コンパイラは、すべてのレジスタパラメータを対応する各スロットに注入します。その結果、デバッグが少し容易になるという良い副作用もありますが、これは単に最適化が無効になっているだけで、コンパイラはシンプルで単純なコードを生成し、賢明に振る舞おうとはしなくなります」

この点を考慮に入れて、最適化されていないOpenSSLバージョンの作成に取り組み、IDAシグネチャのヒット数に改善が見られるかどうかを調べます。

OpenSSLのコンパイルを調整するには、nt.makを変更してCFLAGSステートメントを編集します。コンパイラの最適化を無効にするには、デフォルトのOx(最高速の最適化)からOd(最適化無効)に変更します。

# Set your compiler options
PLATFORM=VC-WIN64A
CC=cl
CFLAGS= /MT /Od -DOPENSSL_THREADS -DDSO_WIN32 -W3 –Gs0 -Gy -nologo
APP_CFLAG= /Zi /Fd$(TMP_D)/app
LIB_FLAG= /Zl /Zi /Fd$(TMP_D)/lib

図19:OxからOdへの変更で無効になった最適化

シグネチャの再コンパイルと再生成、IDAへの再適用を済ませると、カスタムシグネチャのヒット数は適正化されたように思われます。これまで見逃されていたOpenSSLのmodule_run関数も正しく識別されています。


図20:修正されたPoco/OpenSSLシグネチャ

IDAの「Navigator」ツールバーに表示されている最初の分解図(図21)と、カスタムのPocoシグネチャおよび最適化されていないOpenSSLシグネチャ適用後の分解図を比較します(図22)。


図21:最初の分解図


図22:Poco/OpenSSLシグネチャ適用後の分解図

残りの大部分の不明なコードは、C++例外処理、サンク関数(単一のjmp命令)、またはシグネチャ生成時に衝突発生としてマークされた小規模なサブルーチンに関連しています。こうしたケースは、ざっと見直すだけで容易に特定できます。

カスタムシグネチャ開発時の有効な考慮事項として、作成者の開発環境を複製できるかどうかが挙げられます。Visual Studio 2010はかなり古く、MSDNサブスクリプションを保有しているという幸運に恵まれないとマイクロソフトからダウンロードできません。Visual Studio 2019 Community Editionを使用すると、シグネチャの正確さは変わるのでしょうか。

2016年5月にリリースされた、Poco C++フレームワークのバージョン1.7.3は、Visual Studio 2015までしかサポートしていません。そのため、Visual Studio 2019を使用したシグネチャの再作成は試していません。


図23:Visual Studio 2019 Communityで作成されたOpenSSL(最適化無効)

2013年2月にリリースされたOpenSSLフレームワークのv1.0.1eをVisual Studio 2019で作成しようとしましたが、早期の不具合に終わりました。これはiob_funcの未解決シンボルに起因し、Visual Studio 2015でMicrosoft CRTに加えられたStudioの変更がもたらした結果です。幸いにも、このエラーはOpenSSLのテスト用実行可能ファイルの作成時に発生しているため、静的ライブラリはこの時点ですでに(正常に)作成されています。

Visual Studio 2015 Community Editionを使用して、このプロセスを繰り返します。


図24:Visual Studio 2015 Communityで作成されたOpenSSL/Pocoフレームワーク

Visual Studio 2015/2019の場合、OpenSSL/Poco静的ライブラリはデフォルトのインストールに基づいて作成されました。シグネチャのヒット数が減少した原因については調査しませんでした。一つの可能性としては、Visual Studioの新しいバージョンではデフォルトで取り入れられている、セキュリティ/SDLチェックの追加により、プロローグ命令コードと結果のFlairパターンが変更されたことが原因となっていることが考えられます。

Visual Studioの異なるビルド(2010、2015、2019)に応じてIDAがレポートしたシグネチャのヒット数は、最も正確なシグネチャが得られるのは(少なくともx64 PEファイルの分析では)、作成者のビルド環境が複製され、なおかつVisual Studioのデフォルトのインストールを使用しているときであることを示しています。

この例では、PE Richヘッダーが真実を伝えているように思われます。

カスタムシグネチャは適用済みなので、サンプルの分析を開始する準備は整っています。不明なコードの量を減らしたので、分析の取り組みが大幅に簡素化されました。それでは、内部の仕組みについて理解し、このバージョンが以前のITW亜種からどのように進化したのかを本格的に解明することにします。

興味の尽きない仕事がこれから始まります。счастливой охоты!(探求の楽園へ踏み出しましょう!)

Poco/OpenSSLライブラリのLuminaメタデータは、Hex-Raysにプッシュされました。IDA 7.2以降のユーザーは、IDAの内部からLuminaのプルを実行し、このサンプル内で見つかった無害の全ライブラリコードをただちに確認できます。


参考資料:

[1] https://docs.microsoft.com/en-us/cpp/build/reference/hotpatch-create-hotpatchable-image?view=vs-2019
[2] https://devblogs.microsoft.com/oldnewthing/20110302-00/?p=11333

Tags: