This post is also available in: English (英語)

概要

Unit 42のリサーチャーは最近、解析対策技術で保護されたシェルコードペイロードを含むGuloaderの亜種を発見しました。これは人間のアナリストやサンドボックスによるサンプル処理の遅延を目的とするものです。こうしたサンプルを迅速に解析できるよう、Guloaderサンプルの難読化を解除する完全なPythonスクリプトを公開しました。

2022年9月上旬、VirusTotalでの検出率が低いGuloaderの亜種が見つかりました。Guloader(別名CloudEye)は、2019年12月初認のマルウェアダウンローダーです。

このGuloaderサンプルが使う制御フローの難読化技術を解析し、リサーチャーが自動で難読化を解除できるよう、IDA プロセッサモジュール拡張スクリプトを作成しました。このスクリプトは、Dridexなど、同様の解析対策技術を用いるマルウェアファミリに対しても使えます。

パロアルトネットワークスのお客様は、WildFire高度な脅威防御などのクラウド配信型セキュリティサービスを有効にした次世代ファイアウォールと、Cortex XDRにより、同様の解析対策技術を使うマルウェアファミリからの保護を受けています。

関連するUnit 42のトピック Malware, anti-analysis

目次

Guloaderの制御フロー難読化技術
攻撃ベクトル化された例外ハンドラ関数の解析
IDAプロセッサモジュール拡張を書く
結論: マルウェアアナリスト対マルウェア作者
IoC
追加リソース

Guloaderの制御フロー難読化技術

懸案のGuloaderサンプルは制御フローの難読化技術で自身の機能を隠して検出を回避しており、静的解析と動的解析の両方に支障をきたします。

まずはこの脅威が静的解析を妨害する方法を確認します。ひとことで言えばGuloaderは例外を発生させるCPU命令を使って静的解析時のコードを読めなくしています。

Guloaderサンプルからパッカーのレイヤを剥ぎとると、コードが難読化されていることがわかります。IDA Proなどの静的解析ツールを用いると、このサンプルは全体に0xCCバイト(あるいはint3命令)をばらまいてあることがわかります(図1参照)。

0xCCバイトに続くのはジャンク命令(解析妨害を意図した意味のない命令)です。これらのバイトを追加することで、静的解析ツールの逆アセンブルプロセスを混乱させ、間違った逆アセンブルリストを生成させています。

難読化されたコードをスクロールしたところ。全体に0xCCバイトが散らばめてある
図1. 難読化されたコードブロック

0xCCバイトは例外EXCEPTION_BREAKPOINT(0x80000003)を発生させてプロセスの実行を一時停止させるCPU命令です。CPUは制御フローをハンドラ関数に渡してから実行を継続します。ハンドラ関数は、命令ポインタを正しいアドレスに移動させる役割を担っています。

これら0xCCバイトの存在が原因で、動的解析中にデバッガを使用するとGuloaderのサンプルがクラッシュしてしまいます。デバッガは0xCCバイトをソフトウェアブレークポイントとして挿入してサンプルの実行を停止させます。デバッガがハンドラ関数のかわりに例外を処理します。

ハンドラ関数に何が起こっているのかを理解するには、まずそのアドレスを確認する必要があります。

GuloaderはAddVectoredExceptionHandler関数を使ってハンドラ関数を登録します(図2参照)。AddVectoredExceptionHandler関数の第2引数には、ハンドラ関数のアドレスが指定されます。

ハンドラ関数の登録に使用されるAddVectoredExceptionHandlerの関数プロトタイプ。
図2. AddVectoredExceptionHandlerの関数プロトタイプ

デバッガを使って(図3参照)、Guloaderサンプルが登録したハンドラ関数のアドレスを特定します。このアドレス情報があればそれに対応するコードを調べられます。ここで注目したいのが、このExceptionHandlerが順序1で登録されているということです。これはすなわち、これが最初に呼び出されるハンドラであることを意味しています。

Guloaderのサンプルが登録したAddVectoredExceptionHandler関数のアドレスをデバッガで検索したところ
図3. Guloaderサンプル内でAddVectoredExceptionHandler関数の呼び出しをデバッグ

攻撃ベクトル化された例外ハンドラ関数の解析

ハンドラ関数の解析は、その型情報の適用から始めます(図4参照)。

ハンドラ関数のデータ型情報を表示したところ
図4. ハンドラ関数のデータ型の情報

次に、ハンドラ関数が使う3つのWindowsデータ構造体(図5)の型情報を適用します。

ハンドラ関数に適用される3つのWindowsデータ構造体の型情報を表示したところ。
図5. ハンドラ関数に適用される3つのWindowsデータ構造体の型情報

型情報を適用すると、0xCCバイトによる例外を関数がどのように処理したかを調べられます。図6にハンドラ関数(Func_VectoredExceptionHandler)を逆コンパイルしたものをコメント付きで示します。

図6. ハンドラ関数を逆コンパイルした

ハンドラ関数はまずデバッグ対策用のチェックを行い、ハードウェアブレークポイントないしソフトウェアブレークポイントが見つかると実行を終了します。次に0xCCバイトの次のバイトを0xA9とXORしてデコードし、オフセット値を計算します。最後にこのオフセット値を命令ポインタに加算してからコードの実行を再開します。コードの実行は、こうして更新した命令ポインタの指すアドレスで継続されます。

この難読化のしくみを理解すれば、有効な命令を識別して不要な命令を破棄できます(図7参照)。

コードブロックにラベルを付けると有効な命令を識別して不要な命令を破棄できる
図7 ラベル付きコードブロック

Guloaderサンプルの難読化を完全に解除するには、すべての0xCCバイトをJMP short命令(0xEB)に置き換えたうえで、その次のバイトをデコードされたオフセット値に置き換える必要があります。

これらすべてを手作業で行うのは時間がかかるので、次のセクションでは難読化解除処理を自動化するIDA プロセッサモジュール拡張の書きかたを説明します。

IDAプロセッサモジュール拡張を書く

IDAプロセッサモジュール拡張を使うと、IDA Proの逆アセンブルロジックに影響を与えられるようになります。これらの拡張機能はPythonで書かれていて、IDA Proがサンプルの命令をどのように逆アセンブルするかをフィルタリングしたり操作したりできるようになります。

このPythonスクリプトはIDP_Hooksクラスのev_ana_insnメソッドを拡張します。この機能拡張は最初に、現在の命令が0xCCバイトであるかどうかを確認します。次に、0xCCバイトをJMP short命令(0xEB)に置き換えます。最後に、次のバイトをデコードしたオフセット値で置き換えます。

図8はこの難読化の解除処理を実装したPythonスクリプト内の関数です。

サンプルの難読化を解除するため、ev_ana_insn()を拡張したPythonスクリプト内の関数。
図8. ev_ana_insn()を拡張してサンプルの難読化を解除

Pythonスクリプトを適用後はIDA ProでGuloaderサンプルの難読化を自動的に解除できます(図9参照)。

IDA ProがGuloaderサンプルの難読化を自動的に解除したところ。Pythonスクリプト適用前(左)と適用後(右)のコード
図9: 難読化されたコード(左)と難読化を解除したコード(右)。

結論: マルウェアアナリスト対マルウェア作者

マルウェアアナリストが処理するさいに時間やリソースをとられるように、マルウェア作者は自分の「作品」によく難読化技術を使います。そんな場合でも、本稿に解説した手順を用いれば、Guloaderのマルウェアサンプルをはじめ、似たような技術を使うほかのマルウェアファミリのサンプル解析に必要な時間を減らせます。

パロアルトネットワークスのお客様は、WildFire高度な脅威防御などのクラウド配信型セキュリティサービスを有効にした次世代ファイアウォールと、Cortex XDRにより、同様の解析対策技術を使うマルウェアファミリからの保護を受けています。

IoC

SQ21002728.IMG:
SHA256: fb8e52ec2e9d21a30d7b4dee8721d890a4fbec48103a021e9c04dfb897b71060
SQ21002764

SQ21002728.vbs:
SHA256: 56cdfaa44070c2ad164bd1e7f26744a2ffe54487c2d53d3ae318d842c6f56178
SQ21002764

追加リソース

Enlarged Image