
하드웨어 브레이크포인트(DR0-DR7) 기반 패치리스 유저 모드 후킹 및 텔레메트리 계측 엔진(AMSI, WLDP 및 ETW PoC).
전통적인 인메모리 코드 패치의 대안으로서 하드웨어 브레이크포인트(CPU 디버그 레지스터) 기반 함수 후킹을 시연하는 보안 연구용 개념 증명(POC)입니다.
목적 및 범위
이 저장소는 Windows 내부 구조에 대한 방어적 보안 연구, 레드팀/퍼플팀 교육, 탐지 엔지니어링, 그리고 학술 연구를 목적으로만 공개됩니다. 이는 공격자가 프로세서 디버그 레지스터를 악용하여 사용자 모드 보안 텔레메트리를 무력화할 수 있는 방법과, 그에 못지않게 중요한 방어자가 이러한 기법을 탐지하기 위해 무엇을 모니터링해야 하는지를 보여줍니다. 저자는 이 코드의 어떠한 오용에 대해서도 책임지지 않습니다. 명시적 승인 없이 시스템에 이 기법을 사용하는 것은 불법이며, 대부분의 관할권에서 관련 컴퓨터 사기 및 남용 법률을 위반합니다. 소유하지 않았거나 테스트에 대한 명시적 서면 허가를 받지 않은 환경에서는 절대 배포하지 마십시오.
mora_hwbp.c는 대상 프로세스(예: PowerShell 호스트)에 로드/주입되면, 프로세스 내 모든 스레드의 아키텍처 디버그 레지스터(DR0–DR7)에 저장된 CPU 하드웨어 브레이크포인트만을 통해 네 개의 사용자 모드 함수를 후킹하는 DLL을 구현합니다:
| 레지스터 | 후킹된 함수 | 모듈 | 목적 |
|---|---|---|---|
DR0 | AmsiScanBuffer | amsi.dll | AMSI 콘텐츠 검사 무력화 |
DR1 | WldpQueryDynamicCodeTrust | wldp.dll | WLDP 동적 코드 신뢰 강제 (Device Guard / WDAC) |
DR2 | WldpIsClassInApprovedList | wldp.dll | WLDP 클래스 승인 강제 (Device Guard / WDAC) |
DR3 | NtTraceEvent | ntdll.dll | 전체 사용자 모드 ETW 스트림 차단 |
프로세스별 벡터 예외 처리기(VEH) 가 디버그 레지스터에 의해 발생한 EXCEPTION_SINGLE_STEP (0x80000004) 폴트를 수신하고, 예외 컨텍스트를 재작성하여 원래 함수의 성공적인 반환 경로를 시뮬레이션한 후 실행을 재개합니다 — 이 모든 과정이 실행 가능한 메모리의 단 한 바이트도 수정하지 않고 이루어집니다.
이로 인해 이 기법은 공격과 방어 양측 관점에서 특히 흥미롭습니다:
.text 섹션(고전적인 인라인 후킹, EAT/IAT 패치, 또는 Etwp* 스터빙)을 탐지하는 EDR/HIPS 무결성 검사를 우회합니다.GetThreadContext/SetThreadContext 시스템 호출 패턴)를 남깁니다.전통적인 사용자 모드 후킹 접근 방식 — 인라인 디투어(5–14바이트 덮어쓰기), 가져오기 주소 테이블(IAT) 후킹, 내보내기 주소 테이블(EAT) 후킹 — 은 공통된 약점을 공유합니다: 무결성 스캐너와 ETW가 관찰할 수 있는 메모리를 수정한다는 점입니다.
최신 AV/EDR 제품은 다음을 구현합니다:
pageguard/guard-page 트릭, PAGE_EXECUTE_READWRITE로의 VirtualProtect 전환, 섹션 해시 불일치를 탐지하는 커널 콜백 및 사용자 모드 무결성 검사.하드웨어 브레이크포인트는 이 모든 것을 우회한다:
.text에서 스캔할 대상이 없다.SetThreadContext를 통해 스레드별로 설정되며, 이는 무결성 스캐너가 사용하는 고전적인 "메모리 수정됨" 신호를 트리거하지 않는다.이 POC는 현대 Windows 보안 스택에서 가장 널리 의존되는 세 가지 사용자 모드 보안 프리미티브인 AMSI (Antimalware Scan Interface), WLDP (Windows Lockdown Policy), ETW (Event Tracing for Windows) 를 대상으로 이 기법의 효용성과 탐지 가능성을 탐구한다.
AMSI는 애플리케이션(PowerShell, Office, VBScript, .NET 호스트 등)이 등록된 악성코드 방지 공급자에게 콘텐츠 스캔을 요청할 수 있게 해주는 Windows 플랫폼 통합 지점이다. 주요 관심 진입점은 다음과 같다:
AmsiScanBuffer(HANDLE hamsiContext, PVOID buffer, ULONG length, LPCWSTR contentName, HANDLE hamsiSession, AMSI_RESULT *pResult)반환되는 AMSI_RESULT를 AMSI_RESULT_CLEAN (0)으로 강제하면, 스크립트 엔진은 해당 콘텐츠가 검사되었고 무해한 것으로 판정되었다고 믿으므로 실행이 중단 없이 계속된다.
WLDP는 Windows Defender Application Control (WDAC / Device Guard)을 위한 정책 평가를 구현한다. 이 POC는 두 개의 WLDP 진입점을 후킹한다:
WldpIsClassInApprovedList는 주어진 COM 클래스(GUID로 식별됨)가 현재 정책에서 허용되는지 여부를 응답한다. AMSI는 내부적으로 WLDP에 문의하여 특정 스크립트/콘텐츠 클래스가 "신뢰"되는지(승인 목록에 있는지)를 결정한다. 함수가 해당 클래스를 승인된 것으로 보고하면, AMSI는 해당 콘텐츠 유형에 대한 추가 검사를 건너뛸 수 있다.WldpQueryDynamicCodeTrust는 주어진 동적 생성 코드(예: .NET JIT 출력 또는 기타 생성된 실행 가능 메모리)가 현재 잠금 정책에서 신뢰되는지 여부를 응답한다.이 DLL은 WldpIsClassInApprovedList의 isApproved 출력 매개변수(RDX)를 TRUE로 설정하고 S_OK를 반환하며, WldpQueryDynamicCodeTrust가 S_OK (0)을 반환하도록 강제한다 — 즉, 평가된 콘텐츠 클래스와 조회된 동적 코드 모두 신뢰되는 것으로 보이게 만든다.
ntdll.dll의 NtTraceEvent는 ETW 하위 시스템으로 들어가는 가장 낮은 수준의 사용자 모드 진입점이다 — 사실상 모든 ETW 이벤트 방출이 이를 통해 이루어진다(EtwEventWrite 및 상위 수준의 Etw* API 포함). 따라서 이를 후킹하면 사용자 모드에서 전체 ETW 스트림이 차단되며, 보안 모니터링과 관련된 광범위한 부작용이 발생한다:
Microsoft-Windows-DotNETRuntime)이 DLL은 실제 함수를 실행하지 않고 단순히 STATUS_SUCCESS (0)을 반환한다.
┌──────────────────────────────────────────────────────────────────────────┐
│ Target Process (e.g. powershell.exe) │
│ │
│ ┌──────────────────────────┐ ┌──────────────────────────────────┐│
│ │ mora_hwbp.dll │ │ CPU / Windows ││
│ │ │ │ ││
│ │ DllMain / InstallHook │ │ Thread A Thread B ││
│ │ │ │ │ ┌────────┐ ┌────────┐ ││
│ │ ▼ │ │ │ DR0..3 │ │ DR0..3 │ ││
│ │ Resolve exports │ │ └────────┘ └────────┘ ││
│ │ (amsi/wldp/ntdll) │ │ ││
│ │ │ │ │ #DB (single-step) ││
│ │ ▼ │ │ exception ──► Windows Dispatch ││
│ │ AddVectoredException │ │ │ ││
│ │ Handler(VEH) │ │ ▼ ││
│ │ │ │ │ ┌─────────────────────────────┐ ││
│ │ ▼ │ │ │ VectoredHandler (ours) │ ││
│ │ SetHwbpOnThread(ALL) │ │ │ • match #DB address │ ││
│ │ │ │ │ │ • rewrite context (RIP/RSP)│ ││
│ │ ▼ │ │ │ • spoof return value (RAX) │ ││
│ │ MonitorThread ◄──┐ │ │ │ • continue execution │ ││
│ │ (re-hook every │ │ │ └─────────────────────────────┘ ││
│ │ 500ms) └──────┘ │ ││
│ └──────────────────────────┘ └──────────────────────────────────┘│
└──────────────────────────────────────────────────────────────────────────┘
상위 수준 흐름:
DLL_PROCESS_ATTACH 시점에(또는 내보낸 InstallHook을 통해) 대상 내보내기 함수들이 GetProcAddress로 확인됩니다(선택적으로 LoadLibraryW를 통해 모듈 로드를 강제할 수 있음).AddVectoredExceptionHandler(1, ...)).CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0)를 통해 열거되어 후킹됩니다.#DB 단일 단계 예외를 발생시키고, Windows는 이를 VEH로 디스패치하며, VEH는 무해한 반환을 시뮬레이션하고 실행을 계속합니다.주입 전 — AMSI가 테스트 벡터를 차단합니다:
PS> "AmsiTestSample:7e72c3ce-861b-4339-8740-0ac1484c1386"
This script contains malicious content and has been blocked by your antivirus software.