Emdiviが持つ暗号化された文字列の復号(2015-10-28)
こんにちは、中津留です。JPCERT/CCは、CODE BLUE 2015で「日本の組織をターゲットにした攻撃キャンペーンの詳細」と題して、日本国内で発生している攻撃キャンペーンの分析結果について発表しました。
今回は、CODE BLUE 2015での発表でも名前が出た、遠隔操作マルウェアEmdiviを分析するためにJPCERT/CCが作成したIDAPythonスクリプト「emdivi_string_decryptor.py」についてより詳細に紹介したいと思います。ソフトウエア開発プロジェクトのための共有ウェブサービスのGitHubで既に公開しているコード等と併せてご利用ください。
JPCERTCC/aa-tools・GitHub
https://github.com/JPCERTCC/aa-tools
Emdivi内の暗号化された文字列
Emdiviは、接続先URLなどの文字列を暗号化して自身の中に格納しています。暗号化された文字列は、検体によって、図 1のようにBase64エンコードして格納されているものもあれば、暗号化されたままのバイナリ形式で格納されているものもあります。
インシデント対応のための調査では、このEmdivi内に存在する暗号化された文字列を復号し、接続先URLなどの各種情報を得ることが求められます。emdivi_string_decryptor.pyはこの目的で作成したツールです。
Emdiviの文字列復号処理の分析
Emdiviは、内部に存在する暗号化された文字列を復号するために、次のような処理をしています。
まず、起動された直後に、次の2つの文字列情報から、復号に使用する鍵を算出します。
- 検体のバージョン文字列
例: t17.08.26..3340.4444 - 検体内部に含まれる、ランダムな長い文字列
例: jp5cQEhSR7xMEdv1JOjh5eKGsMxSCAE5M57CijC8VgN1KMbBvP9(以下省略)
これらの文字列に、Base64エンコードやMD5ハッシュ値計算などを組み合わせて施し、図 2のような復号鍵を算出します。Emdiviのバージョンによっては、足し算などの演算処理も組み合わせて算出する場合もあります。
ここで算出された復号鍵を使用して、文字列を使用する直前に復号処理を行います。暗号に関わる処理はクラスとして実装されており、図 3はその情報を表示したものです。
多くのEmdiviは図3のようにXxTEAを使用していますが、一部のバージョンではAESを使用していることも確認しています。また、暗号化処理と復号処理を入れ替えているバージョンが存在しており、復号時にXxTEA暗号化処理を用いているものがありました。
様々なEmdiviを分析した結果、復号鍵の算出と復号処理を表1のようにまとめることができました。復号鍵生成処理の詳細は、emdivi_string_decryptor.pyのコードをご参照ください。
表1: Emdiviのバージョン毎の文字列復号処理
t17 | t19およびt20中期 | t20初期または後期 | |
復号処理 | XxTEA 復号 | XxTEA 暗号化 | AES 暗号化 |
復号鍵の算出方法 | MD5( MD5(base64(ver)) + MD5(key_string)) |
scanf( "%x%x%x%x", Inc_Add(ver17_key) ) |
Inc_Add(ver17_key)[:24] |
emdivi_string_decryptor.pyを使用する前に
emdivi_string_decryptor.pyは、IDAPythonスクリプトなので、実行には逆アセンブラ、IDAが必要です。また、文字列を復号するには、復号鍵を算出する際に使用するバージョン文字列が必要です。
まずツールを使用する前にバージョン文字列を取得します。バージョン文字列は、メモリまたは通信データから取得します。
メモリから取得する場合、分析環境でEmdiviを動作させた後、デバッガなどを用いてメモリ上に存在する文字列を検索します。この際、仮想環境検知などを気にする必要はありません。バージョン文字列はそれらの処理の前に生成されるからです。
通信データから取得する場合には、通信データをデコードする必要があります。デコードには、emdivi_string_decryptor.pyと一緒に公開しているemdivi_postdata_decoder.pyを使用することができます。以下はemdivi_postdata_decoder.pyの引数にデコードしたいデータを与えて実行した様子です。
> python emdivi_postdata_decoder.py "r13ftV=C%5DZ%03k%07%06%7Edkgd%05%19%7Dq%05%05%1E%0D%02%0C;yhmsuRvo=%00;date=-b%27f.4%60%25%23%3A%24%2C%3A%26%22%3A%3A%27%27%20%24%3A%20%20%20%20%1Dh%1DZ%40.4%22%3A%25%3A%23%22%24%25%1DO%7Eu9%5EDI%1Dh%1DYQY.4%26%24%20%2CY%1Dh%1DSY%40%3C-%3D" [*] 3 field(s) found in postdata "r13ftV" -> "win7_32JP_SP1-IE11*968" "yhmsuRvo" -> "1" "date" -> "9v3r: t17.08.26..3340.4444 | NT: 6.1.7601 [ja-JP] | MEM: 2048M | GMT(9)"
なお、この通信データに含まれるバージョン文字列は、復号に必要となるバージョン文字列とは異なる場合があるため、メモリから取得する方法を用いることをお勧めします。
emdivi_string_decryptor.pyの実行
バージョン文字列が入手できれば、準備は完了です。IDAに文字列復号対象となるEmdiviをロードし、emdivi_string_decryptor.pyを実行します。emdivi_string_decryptor.pyは以下の流れで処理を行います。
1. バージョン文字列の入力
2. 復号鍵の算出
3. 暗号化された文字列の探索
4. 文字列の復号
5. 結果の出力および該当箇所へのコメント挿入
まずemdivi_string_decryptor.pyを実行すると、図4のバージョン文字列の入力ダイアログボックスが表示されます。
バージョン文字列を入力すると、図5のように、コンソールに復号できた文字列を表示するとともに、暗号化された文字列が格納されている場所に復号後の文字列をコメントとして挿入します。
これで、接続先URLなどの様々な情報を取得することができます。JPCERT/CCでは、こうして得られた情報などに基づき、Emdiviに関連する一連の攻撃活動で発生したインシデントの調整・対応を行っています。
おわりに
このスクリプトの公開が、日本を標的とした一連の攻撃活動への対応に役立つとともに、マルウェア分析技術の向上にも貢献するよう望んでいます。
なお、カスペルスキー社のブログ記事(参考URL)にあるとおり、Emdiviには感染ユーザのSIDを使用するバージョンがわずかながら存在します。残念ながら現状のemdivi_string_decryptor.pyは、SIDの入力には対応できていません。また、今後別の暗号方式を使用したバージョンが登場する可能性も考えられます。GitHub上での皆様からのプルリクエストもお待ちしております。
分析センター 中津留 勇
参考URL
APT「ブルーターマイト」:新たな手口で感染拡大 | Kaspersky Daily - カスペルスキー公式ブログ
https://blog.kaspersky.co.jp/blue-termite-apt-targeting-japan/8412/