今回はサイバーリーズンが調査した、悪名高いrundll32.exeについて説明します。これはMicrosoftが提供している正規ツールであり、これを使うことでユーザーは任意のプログラムをロードして実行できます。このツールは、攻撃者が攻撃オペレーションの際に、悪意あるコードを実行するためによく使用されます。rundll32.exeがどのようなプロセスを通じて悪用されるかを、下記に詳しく説明します。

Rundll32.exeの概要

rundll32.exeは、Microsoftの署名入りのバイナリであり、Windowsでダイナミックリンクライブラリ(DLL)をロードするために使用されます。これはWindowsネイティブなツールであり、32ビット版と64ビット版の両方があります。各バージョンは、それぞれ下記の場所に置かれています。

シグネチャの詳細は次の通りです。


▲図1:Rundll32.exe シグネチャの概要


▲図2:Rundll32.exeシグネチャの詳細

Rundll32.exeはMicrosoftによる署名付きの実行ファイルであり、すべてのWindowsシステムにネイティブに存在します。また、それは、コードをメモリに読み込むための非常に柔軟で効率的なプロキシとして機能します。さらに、Rundll32.exeはある程度の信頼を得ているため、AppLockerおよびソフトウェア制限ポリシー(SRP)のバイパスとなる可能性があります。

さらに、rundll32.exeは、LSASS(Local Security Authority Subsystem Service)のようなプロセスのメモリダンプを行うことで、クレデンシャルを取得するためにも利用できます。

このような理由から、Rundll32.exeは、任意の悪意あるコードのプロキシ実行やLSASSメモリのダンプを行うために、攻撃者が非常に興味深く、頻繁に使用するツールとなっています。この手法は、MITRE ATT&CK™ Enterpriseフレームワークにもマッピングされており、rundll32.exeには下記のような独自のサブカテゴリがあります。

現在、Rundll32.exeを悪用しているのは誰か?

rundll32.exeは、頻繁に利用されるツールであり、その合法的な利用は否定されるべきではありません。しかし、rundll32.exeは、悪意あるコードのプロキシ実行を目的として、国家に関連するグループ(APT)からサイバー犯罪者グループに至るまで、多くの攻撃者により利用されています。

これらの脅威アクターの中には、最も洗練された攻撃者の一人でありながら、その活動においてrundll32.exeに依存している者がいます。ほんの一部を挙げるだけでも、次のような脅威グループが存在しています。

また、Cobalt Strikeのようなツールは、コマンドラインからDLLをロードするためにrundll32.exeを使用できることにも留意する必要があります。このようなツールは他にも多く挙げられますが、ここでは紹介しません。rundll32.exeを利用している上記のグループが持つ重要性、危険性、多様性を簡潔にまとめることの方が大事であり、それを検知するためのメカニズムを理解することの方が重要だからです。

Rundll32.exeの動作

Microsoftはrundll32.exeに関する詳細な情報を提供していませんが、同社はrundll32.exeの構文については下記のように言及しています。


▲図3:Rundll32.exeに関するMicrosoftのドキュメント

この構文は完全ではありません。実際には、ユーザーは下記のように、ダイナミックリンクライブラリ(DLL)へのエントリポイントを指定する必要があります(そうしないと何も起こりません)。


DLLがアクセス可能な共有を通じてホスティングされている場合、はローカルにもリモートにもなりえるため、2番目のシナリオではUNC(Universal Naming Convention)パスが使用されることに注意してください。

エントリポイントが存在しない場合でも、システムは最初にDLL_PROCESS_ATTACH値を指定してDllMain関数を呼び出します。この結果、関連するコードが実行された後に、「エントリポイントが存在していない」という理由でエラーメッセージが表示されます。

実際、rundll32.exeプロセスは、下記に示すように、DllMain(DLLのエントリポイント)を呼び出すLoadLibraryExW関数を使用して、rundll32.exeプロセスの仮想アドレス空間にDLLをロードしていることが分かります。


▲図4:Rundll32.exe はLoadLibraryExW 関数を使用する

スタックを分析すると、LoadLibraryExW呼び出しでは次の値が使われていることに気付きます。

  • DLLパスを含むESIレジスタ (C:\\Code\\RUNDLL32_TEST.dll)
  • エントリポイントを含むEDIレジスタ(BADENTRY)
  • 値8および値0をプッシュ

これらの値をよりよく理解するために、LoadLibraryExW関数の構文(libloaderapi.hに含まれているもの)を見てみましょう。

使用されているパラメータは次の通りです。

  • lpLibFileName:ロードするモジュールのファイル名を指定する文字列です。
  • hFile:このパラメータはNULLに設定されます(将来の使用のために予約されている)。
  • dwFlags: 検索戦略を8個に設定します(LOAD_WITH_ALTERED_SEARCH_PATHに対応)

LoadLibraryExWは理論的にはDLLのDllMain関数を呼び出さずにDLLモジュールをロードできますが、ここではrundll32.exeはdwFlagsを8に設定しているため、そのような動作は行われません。このコードは、次のコードと同等です。

注:Microsoft APIドキュメントによると、rundll32.exeが特定のエントリポイント(DLL_PROCESS_ATTACH 以外の値)でDllMain関数を呼び出した場合、その戻り値は無視されるとのことです。プロセスの初期化時にDllMainが呼び出された際に戻り値がFALSEであった場合、当該プロセスはエラーで終了し、拡張エラー情報を提供するためにGetLastErrorが呼び出されます。

テスト用のDLLの作成

ここでは、RUNDLL32_TEST.dllという簡単な32ビットのC++ DLLを作成します。このDLLは、DLL_PROCESS_ATTACHの値と共にDllMain関数が呼び出されると、calc.exeを実行するものです。また、cmd.exeを実行する特定のエクスポートされたエントリポイントも作成します。さらに、MessageBoxを使用してデバッグ情報を提供します。

注意すべきは、特定のエントリポイント(DLLエクスポート関数)をターゲットにしている場合でも、DLL_PROCESS_ATTACH経由でDllMain 関数内のコードが実行されることです。

注:この動作は以前にも説明しましたが、rundll32.exeからLoadLibraryExWを呼び出す際に、dwFlagsがLOAD_WITH_ALTERED_SEARCH_PATHに設定されることに関連しています(このフラグは制御下にありません)。

我々が作成したDLLでは、SpecificEntryPointを使用した場合、2つのアプリケーション(calc.exeとcmd.exe)が実行されるため、このシナリオでは2つのメッセージボックスが存在することになります。

最後に付け加えておくと、DllMain内でCreateProcessを呼び出すことはお勧めできません。なぜなら、それを行うと、不適切な同期を引き起こし、プロセスの作成時に他のDLLをロードしてしまうため、アプリケーションがデッドロックに陥る可能性があるからです。

作成したDLLを使ってテストを実施

まず、calc.exe(DLL_PROCESS_ATTACH値と、架空ではあるが必須のエントリポイントを引数に持つDllMain関数)を実行してみましょう。

このコマンドは、架空のエントリポイント(存在しないDLLエクスポート関数)をターゲットにしているため、先に述べた理由からcalc.exeが実行されることになります。

注:エントリポイントを指定しない場合、DLLはロードされないため、たとえ架空のものであってもエントリポイントを指定する必要があります(このことは、Microsoftのドキュメントには記載されていません)。

ここで、SpecificEntryPointというDLLエクスポート関数を使って、cmd.exeを実行してみましょう。コマンドは次のようになります。

以前、LoadLibraryExWについて観察したところ、指定されたモジュールが呼び出し側プロセス(rundll32.exe)のアドレス空間にロードされることが分かりました。このため、下記に示すように、我々は、スレッドのスタックを検査することでロードしたモジュールを復元できました。


▲図5:スレッドのスタック概要(提供されたDLLのエントリポイントに到達する)

その結果、存在しない親を持つcmd.exeが生成されたことを確認できました。これは、rundll32.exeプロセス(PID 1844)が終了し、cmd.exeプロセス(PID 10904)が独立した新しいプロセスとして作成されたためです。


▲図6:プロセスの概要(Rundll32は「マップされていない」親を持つ子を生成した)

しかし、Cybereason Defense プラットフォームを利用することで、我々は、履歴、ロードされたすべてのモジュール、およびその他すべての関連情報を調べることができたほか、プロセスツリーを表示することで、rundll32.exeがcmd.exeの親であることに気付くことができました。


▲図7:Cybereasonの調査ダッシュボードでRundll32.exeの実行をハンティングする


▲図 8:CybereasonによるRundll32.exe のプロセスツリーの表示

この例は、それ自体では悪意あるものではないため、この実行に関してMalOp™が生成されることはありません。しかし、すべての関連するコンテキストと情報は保存され、アクセス可能になります。

Rundll32.exeは他に何を実行できたか

これまで、rundll32.exeが、攻撃者が任意の悪意あるコードをプロキシ実行するための強力な資産であることを見てきました。このバイナリは、comsvcs.dll(Microsoftの 署名付きDLL)を利用して、MiniDumpWと呼ばれる関数をエクスポートします。MiniDumpWは、MiniDumpWriteDumpを使ってlsass.exe(Local Security Authority Subsystem Service)プロセスのメモリをダンプすることで、クレデンシャルを取得できます。

MITRE ATT&CKとの対応:この手法は「OSクレデンシャルのダンプ:LSASSメモリ」と名付けられており、そのIDはT1003.001です。

構文は次の通りです。

ここで、はLSASSのプロセスID、は出力先のパス名です。なお、これを実行するには、ローカル管理者権限またはSYSTEM権限が必要です。
例:

▲図9:comsvcs.dllを使用したRundll32.exeによるLSASSプロセスのメモリダンプ

我々は、Microsoftの署名付きバイナリであるrundll32.exeを使うと、任意の悪意あるコードやクレデンシャルのダンプのプロキシ実行が可能となることを実証しました。

rundll32.exeを使って他に何が行えるでしょうか?このバイナリは次のことにも利用できます。

  • JavaScriptの実行
  • VBScriptの実行
  • Alternate Data Stream(ADS)に含まれているコンテンツの実行)
  • COMオブジェクトの操作
  • その他

rundll32.exeの詳細情報や例については、LOLBASプロジェクトのページをご覧ください。

CybereasonによるRundll32.exeの検知

AIを搭載した高度なテクノロジーを通じて、我々は、誤検知を含む大量のアラートを手動でトリアージし調査するようなソリューションに取って代わる、最適な代替ソリューションを提供します。それがCybereasonのMalOpです。MalOpはインタラクティブなグラフィカル表示機能であり、悪意のある操作の全体像を根本原因から明らかにするものです。ユーザーは、攻撃のすべての要素(影響を受けるすべての資産に相互関連付けされたもの)を瞬時に確認できるほか、自動化された(またはワンクリック式の)修正オプションを利用できます。これにより、調査期間を最大93%短縮できるため、防御者は数日ではなく数分で脅威を排除できるようになります。

実際、Cybereasonを使うと、rundll32.exeの無害な利用に関する誤検知を回避できること、そして我々が作成したテスト用のDLLを使うと、システムに害を及ぼさない別のWindowsバイナリを生成できることがすでに分かっています。


▲図 10:Cybereason Defense Platformで表示したRundll32.exe のプロセスツリー(悪質でないもの)

上記のシナリオでは、紹介されている手法は危険ではありません。一方、下記のセクションでは、rundll32.exeがどのように悪用されるかを示します。
注:下記に紹介するテストでは、攻撃を即座にブロックせずに検知能力を実証するために、「防止(prevention)」モードではなく、「検知(detection)」モードでEDRを設定しました。

悪意ある例その1:LSASSのダンプ

もちろん、Cybereasonは、rundll32.exeの悪意ある動作を検知できるほか、関連する場合はアクティブなMalOpsをトリガーします。ここでは、例として、攻撃者がrundll32.exeとcomsvcs.dllを悪用してLSASSメモリをダンプする際の手法を紹介することにします。

防御者は、MalOp™を利用することで、攻撃に関するすべての関連情報を迅速に確認できます。


▲図11:LSASSプロセスのメモリをダンプするRundll32.exeのMalOp(Cybereason Defense Platformでの表示)

その後、防御者は、プロセスツリーを探索することで、不審な活動のハンティングが行えるようになります。


▲図 12:Cybereason Defense Platform で見た Rundll32.exe のプロセスツリー(悪意のあるもの)

悪意ある例その2:Meterpreterペイロード

2つ目の例を示すために、我々は今回、msfvenomを使用して攻撃者が制御するシステムへのリバースシェルを開始するような、悪意あるDLLを作成しました。我々は、ステージングされたReverse TCP Meterpreterペイロードを選択し、それをsample.dllと名付けました。


▲図 13:Msfvenom – Meterpreterペイロードの作成(DLL)

では、rundll32.exeを使ってDLLを実行してみましょう。


このDLLを実行するとMalOpが作成され、そのことが防御者に通知されます。


▲図14:Meterpreterのペイロード(DLL)をロードする際の “Rundll32.exe “のMalOp

注:このDLLは、リフレクティブDLLインジェクション技術を使用して、Meterpreterペイロードをメモリ内にインジェクトしています。このため、MalOp内に“Module Injection”への言及があります。

防御者はアラートを受け取った後、プロセスツリーを探索することでハンティングを続行できます。


▲図15:Meterpreter Payload(DLL)をロードしたときのRundll32.exe のプロセスツリー(Cybereason Defense Platform での表示)

防御者は、プロセスツリーを通じて追加の攻撃者ハンティングを進めることができます。プロセスツリーには、リフレクティブDLLインジェクションのインジケーターであるフローティングモジュールが示されています(Delivering Meterpreter)。


▲図16:Meterpreter – フローティングモジュールの検知

IP 10.160.155.26のマシン(被害者)が、ポートTCP/8080でIP 10.160.201.220の別のマシンに接続していることが分かります。これは、我々が作成し、rundll32.exeを使って実行したReverse Meterpreter(TCP)のペイロード(sample.dll)に対応します。


▲図17:Meterpreter – 攻撃者への接続

悪意ある例その3 – VBScriptの実行

3つ目の例として、VBScriptを実行することでPowerShellプロンプトを生成する手法を紹介します。

powershell.exeが正規のWindowsバイナリであっても、この間接実行は、極めて異常でありかつ疑わしいものとなります。なぜなら、攻撃者がそれを間接的実行手段として使用する可能性があるためです。

当社が提供する振る舞いベースのファイル実行防止(Behavioral Execution Protection、BEP) 機能のおかげで、この実行は正しく「不審」としてマークされます。(これは、先に示したcmd.exeやcalc.exeの実行の場合とは異なっています)。


▲図 18:Cybereason Defense Platform での表示:MalOpで、Rundll32.exeが「悪意あるプロセス」としてマークされる (BEP機能を利用)

2022年下半期セキュリティ予測 〜4つの脅威から紐解く、 2022年上半期の振り返りと下半期のサイバーセキュリティの展望〜

サイバーリーズンは大きな影響を及ぼす4つの脅威を2022年下半期のサイバーセキュリティ予測として取り上げました。

4つの脅威についてそれぞれ2022年上半期の動向を振り返りながら、2022年下半期のサイバーセキュリティ予測について説明します。
https://www.cybereason.co.jp/product-documents/survey-report/8823/