はじめに
JPCERT さんから "LODEINFO" という日本に対する標的型攻撃で使用されるRAT(マルウェア)が報告*1されて早3年が経ちますが、2023年3月現在でも少しずつTTPsを変えながら継続して使用されています。このような背景からインシデントレスポンス対応者への一助として、下記のGithubにて暗号化されている通信を復号するためのツールを公開しました。
本ツールについては JSAC2023*2でも簡単に紹介しましたが、使い方には一切触れなかったのでどのように扱うのが効果的か把握できていない方もいらっしゃるかと思います。本稿ではこれまでわかりにくいREADMEだけ書いて放置していた解析ツールの使い方を簡単に紹介します。LODEINFO 関連のインシデントに対応している方の一助になれれば幸いです。
復号の基本原理
LODEINFO が C2 server との communication で使用するデータフォーマットおよびデータの変換方式は様々な記事、カンファレンスでまとめられているので好きなものを参考にしていただければと思います。今回は JSAC2023 で紹介されたPDFの画像を引用しながら説明します。
まず、LODEINFOマルウェアがC2 serverとやりとりするフォーマットはヘッダー部(前半部分)とデータ(後半部分)の2つのデータがそれぞれ異なる方式で暗号化された後、文字列として連結された状態で送信されています。なので、復号するためには固定長のヘッダーを切り分け、それぞれのデータごとに復号する必要があります。
具体的には、以下のようなロジックで復号を行います
- ヘッダー部分
- vigenere cipher (文字列のインデックスをベースにした換字式暗号)
- 一部の文字列を置換したBase64
- データ部分
これだけだとイメージがわかないと思うので、具体的な通信データのイメージを見せると以下の図のようになります。黄色部分が固定長のヘッダー部分の文字列なので、そこでデータを区切ってそれぞれに上記の復号処理をかけることで中身を見ることができるようになるわけですね。
python を使って通信を復号する
上記の復号ロジックを python のコードにしたものが decode_connection.py となります。同ディレクトリにある requirements.txt から必要なライブラリをインストールするだけで使用できます。*3
ただし、LODEINFO は検体ごとに異なるAESのKeyとIV, vigenere cipher keyを使用します。検体を解析してそれらの情報を取得し、KEY, IV, VIGENERE_KEY の3変数に設定してください。
変数が設定できたら、最後に通信として観測できたデータを SAMPLEDATA 変数へ入れましょう。あとは下記のようにただ decode_connection.py を実行するだけで、データが復号されるはずです。なお、client => C2 server 方向の通信であれば vigenere cipher の key は毎回変わるので、VIGENERE_KEY の変数は使用しません。C2 server => client 方向の通信には検体内部にハードコードされた vigenere cipher key を使用するため、変数に値を入れる必要があります。
# KEY = a2b_hex("20AD7B28FE0D2D223C48A76E35EE0DA3AEA2B1175D69804605EC43EA4687F785") # IV = a2b_hex("8D5291164B7414118D0C8AC7C050FD1E") # VIGENERE_KEY = "zlApZbCgpp_" # SAMPLEDATA = "AB34bTyi5o_=w8VCUPIIRBvPp08lpwxFeug1tuEhYA2BB2MGCvH...(snip)" ❯ python decode_connection.py HEADER(sha512_128=b'e87d884fa9005a7c2963b7a41bca4ad2', payload_size=244) BEACON(data_size=62, random_data_size=24, date=datetime.datetime(2022, 8, 18, 19, 11, 46), ansi='932', mac_addr='000C2932F71A', computer_name='DESKTOP-81OMVP8', xor_key='zlApZbCgpp_', version='v0.6.3', random_data=b'cV4dXd7e5tIKGmK8ZdHBtw..')
直接コードの変数に手を加える必要があるお行儀が悪いコードになっていて申し訳ありません。ゆくゆくは外部のyamlファイルなどに値を書く方式にしたいかなと思っています。ひとまずは、RATが行った通信を簡単に復号するためのPoCとして利用できるかなと思います。
IDAPython を使って暗号化に必要な情報を一括で取得する
前項では 『AES のKeyとIV, vigenere cipher keyを取得する』とサラッと書きましたが、復号に必要な情報を集めるためには LODEINFO 本体の静的解析が必須になります。つまり、アナリストがshellcodeを読み該当の領域を特定する必要があるのですが、リバースエンジニアリングに精通している人でなければこの作業を行うのは少々酷です。そこで、「スクリプトを使うことで復号に必要な情報を簡単に抽出しよう」という思想から作成したツールが下記の triage.py となります。
本ツールは IDAPython コードとなっており、IDA Pro を使える方ならば LODEINFO の暗号化された shellcode (BLOB ファイル)をIDA Proで開き、メニューバーから "File" -> "Script files..." の順にクリックして上記の triage.py を開くだけでOKです。実行後は自動的に復号された shellcode とその .idb ファイルが開かれ、検体のバージョン情報, AESのkeyとiv, vigenere cipher key などが Output 画面に表示されていることでしょう。この文字列をコピペして、先ほど紹介した decode_connection.pyに書き込めば通信が復号できるようになります。
なお、「暗号化されたBLOB ファイルがわからない!」という方は、正規の署名付き実行ファイルとDLLの同ディレクトリにあるPE形式ではないファイルを探してみてください。例えば、LODEINFO v0.6.3 の場合は K7SysMon.Exe.db が該当します。(下記画像参照)
2023年3月現在で観測している最新のバージョンでも動作することは確認していますので、IDA Proが使える方は活用してください。
おわりに
現在も日本で猛威をふるっている標的型検体のトリアージツールについてドキュメントを残しました。
一部のスクリプトはIDAPythonで書かれているため、IDA Proを持っていない人には使えないというのが現状の課題かなと思っています。もし Ghidra script 版や機能追加の希望があれば、Issueを立てていただけると次回ツールを作る際の参考やモチベにさせていただきます。
皆さんのインシデント対応が少しでも楽になりますように。
*1:https://blogs.jpcert.or.jp/ja/2020/02/LODEINFO.html
*2:https://jsac.jpcert.or.jp/archive/2023/pdf/JSAC2023_1_6_minakawa-saika-kubokawa_jp.pdf
*3:python でエラーが出る! という方は、python のバージョンを3.9くらいまであげてください。古いバージョンだとtyping回りでエラーとなります。3.7 もあと数か月でEoLなのでこの機会にあげてしまいましょう!!