DLL Search Order HijackingとDLL Side-Loadingの違いについてのメモ。
どちらも正規の実行ファイルに悪意のあるDLLを読み込ませるという点は共通しているが、そこに至るまでの原理は厳密には異なる。
両者の違いについて自分なりに調べてまとめてみた。
※ただし、近年では単純にEXEファイルが同一ディレクトリに存在する悪意のあるDLLをロードしていた場合、DLL Side-Loadingと呼称するケースが増えているようである。
DLL Search Order Hijackingとは
WindowsにはKnownDLLs
というレジストリ・キーがある。実行ファイルがDLLを読み込む際、対象のDLL名がKnownDLLs
キーに定義されていた場合、常に特定のフォルダ配下(system32
やsyswow64
)にあるDLLが読み込まれる。KnownDLLs
キーは以下のレジストリ・パスに格納されている:HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
実行ファイルがKnownDLLs
キーで定義されていないDLLを読み込む場合、WindowsはSafeDllSearchMode
の検索順序に基づいて対象のDLL名を検索する。近年のWindowsではSafeDllSearchMode
はデフォルトで有効になっている。無効にしたい場合は以下のレジストリ・キーを作成して、値を0に設定する:HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SafeDllSearchMode
MicrosoftのドキュメントによるとSafeDllSearchMode
が有効の場合と無効の場合のDLL名の検索順序はそれぞれ以下の通り:
SafeDllSearchModeが無効 (0) | SafeDllSearchModeが有効 (1) |
1. 実行ファイルと同じディレクトリ内にあるDLL名を検索する | 1. 実行ファイルと同じディレクトリ内にあるDLL名を検索する |
2. カレント・ディレクトリ内にあるDLL名を検索する | 2. システム・ディレクトリ内にあるDLL名を検索する ( %systemroot%system32 ) |
3. システム・ディレクトリ内にあるDLL名を検索する ( %systemroot%system32 ) | 3. 16ビット・システムのシステム・ディレクトリ内にあるDLL名を検索する |
4. 16ビット・システムのシステム・ディレクトリ内にあるDLL名を検索する | 4. Windows ディレクトリ内にあるDLL名を検索する (%systemroot% ) |
5. Windows ディレクトリ内にあるDLL名を検索する (%systemroot% ) | 5. カレント・ディレクトリ内にあるDLL名を検索する |
6. %PATH% 変数で定義されたディレクトリ内にあるDLL名を検索する | 6. %PATH% 変数で定義されたディレクトリ内にあるDLL名を検索する |
上の表から分かるようにSafeDllSearchMode
が有効の場合も無効の場合も、Windowsはまず最初に実行ファイルと同じディレクトリ内にあるDLL名を検索する。
以下の条件を満たした場合、実行ファイルと同じディレクトリに正規のDLLと同じファイル名を持つ悪意のあるDLLを配置することで、実行ファイルに悪意のあるDLLを読み込ませることが出来る:
- 正規のDLLが
KnownDLLs
で定義されていない - 正規のDLLが実行ファイルと同じディレクトリ内に配置されていない
- 実行ファイルがDLLを読み込む際に、絶対パスでDLLを参照していない
DLL Side-Loadingとは
WindowsにはWindows side-by-side (WinSxS) assembly と呼ばれる仕組みがある。
ざっくり説明すると、DLLの競合・欠落などの問題を解消するための仕組みのこと。詳しくはこちら。WinSxS
ディレクトリ (%systemroot%winsxs
, C:\Windows\winsxs
)には複数のバージョンのDLLが格納されており、Side-by-Sideを利用するアプリケーションはマニフェスト・ファイルに基づいて読み込むべきDLLのバージョンを判断する。WinSxS
のマニフェスト・ファイルはAssembly ManifestsとしてXML形式で実行ファイルに埋め込まれており、アプリケーションが利用するライブラリやDLLの情報が記載されている。
以下はマニフェスト・ファイルの例である (こちらの記事より引用)
<?xml version=”1.0” encoding=”UTF-8” standalone=”yes”?>
<assembly xmlns=”urn:schemas-microsoft-com:asm.v1” manifestVersion=”1.0”>
<assemblyIdentity publicKeyToken=”75e377300ab7b886” type=”win32”
name=”Test4Dir”
version=”1.0.0.0” processorArchitecture=”x86”/>
<file name=”DirComp.dll” hash=”35ca6f27b11ed948ac6e50b75566355f0991d5d9”
hashalg=”SHA1”>
<comClass clsid=”{6C6CC20E-0F85-49C0-A14D-D09102BD7CDC}” progid=”DirComp.
PathInfo”
threadingModel=”apartment”/>
<typelibtlbid=”{AA56D6B8-9ADB-415D-9E10-16DD68447319}” version=”1.0”
helpdir=””/>
</file>
</assembly>
上記の例ではアプリケーションが利用するDLL名と、そのハッシュ値を記載することで、読み込むDLLの真正性を確認している。
もし、マニフェスト・ファイルの記述が不十分だった場合 (DLL名しか記述していない、DLLのバージョンを明記していない、ハッシュ値の確認をしていない、など)、アプリケーションに対して正規のDLLと同じファイル名を持つ悪意のあるDLLを読み込ませることが出来る。
ちなみにAssembly ManifestsはCFF Explorerで確認できる。(Resource Editor -> Configuration Files)
以下はnotepad.exe
のAssembly Manifestsである。
まとめ
DLL Search Order HijackingはKnownDLLs
およびSafeDllSearchMode
の隙を突いて、実行ファイルに悪意のあるDLLを読み込ませる。
DLL Side-LoadingはWindows side-by-side (WinSxS) assembly
のマニフェスト・ファイルの隙を突いて、実行ファイルに悪意のあるDLLを読み込ませる。
参考
DLL Search Order Hijacking
McGraw-Hill Education発行 Incident Response & Computer Forensics Third Edition P.373 - 375
https://www.fireeye.com/blog/threat-research/2010/08/dll-search-order-hijacking-revisited.html
https://www.fireeye.com/blog/threat-research/2010/07/malware-persistence-windows-registry.html
https://attack.mitre.org/techniques/T1574/001/
DLL Side-Loading
https://www.fireeye.com/content/dam/fireeye-www/global/en/current-threats/pdfs/rpt-dll-sideloading.pdf
https://www.fireeye.com/blog/threat-research/2020/01/abusing-dll-misconfigurations.html
https://www.fireeye.com/blog/threat-research/2014/04/dll-side-loading-another-blind-spot-for-anti-virus.html
https://attack.mitre.org/techniques/T1574/002/