はじめに
近年のサイバー攻撃はAV/EDR等のセキュリティ製品の品質が向上していることもあり、検知の可能性が高くなる不正なツールを使うのではなく、OSやアプリケーションの標準機能等を使った攻撃(Living Off The Land)が中心になっています。レッドチームとしても、LOTL手法を理解するべくOSや広く普及しているアプリケーション等の仕様習熟は重要なのですが、昔からあるWindows環境への実際のLOTL手法の1つとして、DLLサイドローディングというものがあります。今回は、本仕組みの理解を深めるために簡単な例を実装してみました。
本記事執筆の背景は攻撃者の視点や彼らが好んで用いる手法等を学ぶことで、どう防御していくべきかという観点を養うことが目的となっております。そのため、本記事の内容を悪用しないでください。
本記事で学べること
- DLLサイドローディングの概念
- DLLサイドローディングの具体的な実装例
0. 検証環境
- Windows11 Pro(SentinelOneインストール済み)
- Visual Studio 2022
- mingw64(C++コンパイル環境)
1. 概要
DLLとは
一般的にWindowsやLinuxをはじめ各種OSでは、アプリケーション実行時に動的に必要となるプログラムの部品(ライブラリ)をロードする仕組みになっています。これは各アプリケーションで必要なライブラリを全て用意するとアプリケーション毎に重複することになったり依存関係で正常に処理ができなかったり等で非効率なためです。このアプリケーション実行に向けて動的に読み込まれるプログラム群をWindows環境では、DLL(Dynamic Link Library)と呼んでいます。アプリケーション実行時、ライブラリから関数を呼び出す場合、ライブラリ名(相対パス)を指定し、メモリにロードするようOSに要求します。OSは、あらかじめ指定された順序でDLLが保存されているであろうディレクトリを検索し、対象のDLLをアドレス空間に読み込むことで、アプリケーションを正常に実行することができます。
DLLサイドローディングの仕組み
DLLサイドローディングは多くのAPTで利用されている手法で、永続化(persistence)、権限昇格(privilege escalation)、検知回避(defense evasion)の目的などで用いられます。DLLサイドローディングには、PasssiveとActiveの2つの概念があるようです。前者は、DLLだけでなく実行ファイル自体も攻撃者が作成し、後者は本記事のように実行ファイルはOS等の標準実装を用いて、DLLのみ攻撃者が作成するというものです。いずれにせよ、ファイル実行時に必要な関数利用に向けDLLがメモリ空間にロードされるというWindowsの正常な機構を用いて、正規DLLの代わりに悪性DLLを読み込ませることで、攻撃者が意図した操作を実行します。
・Passive Exploitation –a standalone binary (highly trusted) is uploaded
to a target system and used to sideload a malicious library.
・Active Exploitation – this approach is relying on the pre-installed applications or components
vulnerable to loading a malicious library from an unsafe location.
2. 検証準備
今回、悪性DLLをロードさせるために用いるアプリケーションはWindows標準組み込みのSystemResetPlatform.exeとなります。本アプリケーションは、Windows8から実装されており、用途で用いられており、幾つかDLLを読み込むため、この読み込むDLLを悪性DLLに差し替えることで任意のプログラム実行等が可能か検証していきます。
悪性DLLの生成
今回は、メッセージボックスの表示及び任意のアプリケーション実行(calc)を可能にするDLLを生成してみます。DLL作成にあたっては、Visual StudioでC++のプロジェクトを作り、悪性DLLのソースコードをビルドします。ビルド後は、プロジェクトフォルダの/x64/Debug/配下にDLLが生成されます。
#include <windows.h>
BOOL WINAPI DllMain(HINSTANCE hModule, DWORD Reason, LPVOID lpvReserved) {
switch (Reason) {
case DLL_PROCESS_ATTACH:
char path[] = "\"C:\\WINDOWS\\system32\\calc.exe";
system(path);
MessageBoxW(NULL, L"Hacked !!", L"DLL Sideloading Sample", MB_ICONINFORMATION | MB_OK);
break;
}
return TRUE;
}
悪性DLLの配置
作成したDLLはSystemResetPlatform.exe実行時にロードされるように適切なファイル名/場所に保存します。今回は、"C:\$SysReset\Framework"配下にStackフォルダを作成し、配下にRjvPlatform.dllというファイル名で生成した悪性DLLを保存します。なお、SysResetフォルダは、WindowsPCをrefreshした際に作成されるフォルダであり、Refreshをしたことがない端末の場合、隠しフォルダとして$SysResetの作成が必要となります。なぜ、この位置に保存するのか、については3章に少し示していますが、結論としてはあまり情報がなく今後の調査事項となります。
「リフレッシュ」では、Windows は再インストールされますが、設定情報と個人用ファイルは削除されません。アプリも、PC に付属していたものや Microsoft Store から購入したものは削除されず保持されます。
https://www.microsoft.com/ja-jp/biz/smb/column-windows-pc-reset-refresh-restore.aspx
3. 検証
SystemResetPlatform.exeというWindows標準バイナリを実行することで、先述のディレクトリに保存した悪性DLLがロードされます。実際に、対象バイナリを実行すると、悪性DLLに意図的に埋め込んだ挙動となりました。
では、なぜ悪性RjvPlatform.dllは"C:\$SysReset\Framework\Stack\"配下に保存する必要があるのか?についてです。元々"C:\Windows\System32\SystemResetPlatform"配下には、SystemResetPlatform.exe以外に正規RjvPlatform.dllも保存されています。しかしながら、悪性RjvPlatform.dllを配置していない状態、また正規RjvPlatform.dllを"C:\$SysReset\Framework\Stack\"配下に保存した状態のいずれにおいても、SystemResetPlatform.exeの実行により正規DLLがロードされるように見えません。それどころか、SystemResetPlatform.exeもプロセスとして起動していないように見えます(Process ExplorerやAPI Monitorを通じた確認の結果)。この挙動は非常に不可解ではあるので、もう少し情報が入手できれば後日考察したいと思います。
自作のRjvPlatform.dllを配置した際(=サイドローディング成功の場合)のプロセスの見え方
4. 考察
DLLサイドローディングは成功したが、自作DLLは悪性と判定されるのかを以下の通りVirusTotalを使って調べてみました。正規のRjvPlatform.dllはSystemResetPlatform.exeと同一ディレクトリに保存されておりますが、そのdllと比較をしてみました。
正規のRjvPlatform.dll
自作のRjvPlatform.dll(2023/8/24に判定)
結果は見ての通りで、自作のDLLは悪性と判定されております。余談ですが、念のため悪性DLLを再ビルドして異なるハッシュ値にしてファイル名も正規DLLとは異なるファイル名にしてみましたが、同様の結果(2/68:悪性判定ベンダも同じ)でした。正規のRjvPlatform.dllとハッシュ値が異なるが同一ファイル名といった観点で悪性判定しているかと思ったが、そういうわけでもないようです。
5. 防御手法
対策については、Passiveタイプのサイドローディングに対してはMicrosoftが方針をリリースしてます(少し古いですが)。また、本質的な検知ロジックについて、red canaryのブログにも記載があります。検知ロジックについては、改ざん検知同様、例えばWindows標準実装の実行ファイルがロードするDLLについては、あらかじめハッシュ値を算出しリスト化し、それを定期的に照合するということが記載されています。ただ、現実的な運用を踏まえると検証稼働も含めて、すぐに導入は厳しいのかなという気はします。
6. まとめ
今回はDLL side-loadingを試してみました。今回はWindows標準実装の実行ファイルのDLLロードの仕組みを突いて、簡単に任意の操作を行えることを確認しました。実際の攻撃においては、本仕組みを使える状態にまでどう侵害していくか(外部からの侵入、永続化の検討等)というのは検討の余地が多々あるのですが、DLLサイドローディングのイメージは掴むことが出来ると思います。
余談
4章で記載したVTの悪性判定は2023/8/24に実施した結果なのですが、同様のdll(同一ハッシュ)を9/7にVTで再判定すると、以下の結果の通り悪性判定度合いが増えてます。原因については推測ですが、私と同じく参照に載せているLinkedinの記事をもとに検証する人が多数出て、酷似したDLLだと悪性判定されるケースが増えた、ということだと思います(calc立ち上げるDLLのどこが悪性なのよ、ですからね)。ただ、これは脆弱性が公開され、それを狙った攻撃コード等が普及につれて悪性判定の度合いが増すのを示していると解釈できると思います。
正規のRjvPlatform.dll(2023/9/7に再判定)
参照リンク
https://www.mandiant.com/sites/default/files/2021-09/rpt-dll-sideloading.pdf
https://www.linkedin.com/pulse/how-hackers-evade-program-allowlists-windows-dll-davidson-mizael/
https://www.bitdefender.com/blog/businessinsights/tech-explainer-what-is-dll-sideloading/
https://detection.fyi/sigmahq/sigma/windows/image_load/image_load_side_load_rjvplatform_default_location/
https://processchecker.com/file/SystemResetOSUpdates.exe.html