
적절한 ntdll .text 섹션 언후킹을 네이티브 API를 통해 수행합니다. 다른 언후커들과 달리 2개의 ntdll을 로드하지 않습니다. x86/x64/wow64를 지원합니다.
네이티브 API를 통한 올바른 ntdll .text 섹션 언훅. x86/x64/wow64 지원.
프로그램은 PEB를 탐색하여 ntdll.dll의 기본 주소를 찾고, PE 내보내기 테이블을 수동으로 파싱하여 Import Address Table을 건드리지 않고 NT API 함수를 해석합니다. 그런 다음 NtOpenFile을 사용하여 디스크에서 깨끗한 ntdll.dll을 열고, NtCreateSection으로 섹션 객체를 생성한 후 NtMapViewOfSection으로 프로세스에 매핑하여 LoadLibrary를 통해 두 번째 DLL을 실제로 로드하지 않고 언훅 소스를 얻습니다. 후킹된 .text 섹션은 NtProtectVirtualMemory를 통해 PAGE_EXECUTE_READWRITE로 변경되고, 사용자 정의 memcpy로 깨끗한 .text가 후킹된 섹션 위에 복사된 다음, 보호가 원래 플래그로 복원됩니다. 언훅이 제대로 작동했는지 바이트 단위로 검증한 후, 깨끗한 복사본은 NtUnmapViewOfSection으로 제대로 매핑 해제되어 메모리에 두 번째 ntdll이 남지 않습니다.
대부분의 공개 언훅 코드는 문자 그대로 동일한 쓰레기 소스(ired.team 예제 및 GitHub의 거의 모든 오픈소스 언커)에서 복사되어 붙여넣기 된 것이며, 실제 EDR에 대해 무용지물로 만드는 거대한 문제점들을 가지고 있습니다. 네이티브 API 대신 VirtualProtect를 사용하는데, 이는 후킹된 함수를 호출하여 언훅을 수행하는 것이므로 전체 목적을 무산시킵니다. .text 섹션에 RWX 권한을 설정하는데, 이는 EDR이 즉시 플래그를 지정하는 거대한 IOC입니다. 또한 CloseHandle이 섹션 매핑 메모리를 해제하지 않기 때문에 깨끗한 복사본을 실제로 매핑 해제하지 않습니다. UnmapViewOfFile 또는 NtUnmapViewOfSection이 필요하지만 모두가 이 부분을 잊어버려서 프로세스에 두 개의 ntdll 복사본이 로드된 상태로 남게 되는데, 이는 기본적으로 '나는 악성코드입니다'라고 외치는 거대한 네온사인입니다. 또한 기본 ntdll에 FreeLibrary를 사용하려고 시도하는데, 이는 작동하지 않을 뿐만 아니라 핸들 누수를 일으키고, 보호를 불필요하게 두 번 RWX로 변경하는데, 한 번으로 충분하며 제대로 복원하면 됩니다.
이 구현은 네이티브 API(NtOpenFile, NtCreateSection, NtMapViewOfSection, NtProtectVirtualMemory)를 전체적으로 사용하고, 깨끗한 복사본을 NtUnmapViewOfSection으로 적절히 매핑 해제하여 두 개의 ntdll 복사본이 로드되지 않도록 하고, 기본 ntdll에 FreeLibrary를 사용하지 않으며, 메모리 비교를 통해 성공을 검증함으로써 공개 언훅 코드의 일반적인 버그를 수정합니다. 그러나 최신 EDR이 탐지하는 근본적인 IOC를 피하지는 못합니다. C:\Windows\System32\ntdll.dll에 NtOpenFile을 사용하는 것은 로깅되는 IOC이고, ntdll.dll을 가리키는 SEC_IMAGE로 NtCreateSection을 사용하는 것은 ETW를 통해 추적되며, 네이티브 API를 사용하더라도 ntdll의 .text 섹션의 메모리 보호를 수정하는 것은 큰 적신호이며, .text에 쓰는 것은 메모리 쓰기 콜백을 통해 탐지 가능합니다. 이 기술은 잘 알려져 있으며 CrowdStrike 및 SentinelOne과 같은 최신 EDR은 전체 패턴에 대한 서명을 가지고 있습니다. Microsoft Defender for Endpoint 및 Elastic과 같은 고급 EDR은 더 이상 사용자 모드 후크를 사용하지 않고 커널 콜백과 ETW 원격 분석에 의존하므로, 언훅은 그들에 대해 말 그대로 아무 효과도 없습니다. 이는 인라인 후크만 사용하는 기본 EDR과 오래된 보안 제품에는 효과적이지만, 커널 모드 구성 요소나 행동 분석이 있는 모든 것에는 실패합니다. 더 나은 대안으로는 처음부터 후킹된 함수를 호출하지 않는 직접 시스템 콜, wow64 경계를 넘는 heaven's gate, 런타임에 ntdll .text에서 수동 시스템 콜 추출, 또는 의심스러운 API를 완전히 회피하는 것이 있습니다. 2024/2025년에 언훅은 실제 엔터프라이즈 EDR에 대해 일반적으로 죽은 기술이기 때문입니다.
x64 네이티브 프로세스, x86 네이티브 프로세스 및 wow64 프로세스(x64 Windows의 x86)에서 작동합니다. wow64를 자동으로 감지하여 올바른 시스템 디렉터리(System32 vs SysWOW64)를 사용하므로 신경 쓸 필요가 없습니다.
ntdll.dll의 .text 섹션만 건드립니다. 실제 함수 코드가 모두 존재하고 EDR 후크가 인라인 함수 후크(함수 프롤로그의 jmp 명령)로 배치되는 곳이기 때문입니다. .data 및 .rdata와 같은 다른 섹션은 건드릴 이유가 없고 이익 없이 IOC만 더 생성하므로 그대로 둡니다.
cl /EHsc /std:c++17 main.cpp /Fe:unhook.exe
또는 아무거나, 최신 C++ 컴파일러면 작동합니다. windows.h와 winternl.h가 필요합니다.
컴퓨터 시스템에 대한 무단 접근은 불법입니다. 소유하거나 테스트 권한이 있는 시스템에서 사용하십시오. 연방 교도소는 진짜입니다.
코드는 CONTAINING_RECORD 매크로를 사용하여 LDR 목록을 올바르게 탐색하고, 세그먼트 레지스터(x64에서는 gs, x86에서는 fs)를 통해 PEB에 접근하며, 이름 비교를 통해 하드코딩된 .text 섹션 검색을 수행합니다(더 우아할 수 있지만 작동하면 됩니다). NTSTATUS 코드와 NT_SUCCESS 매크로를 통해 오류를 처리하고, 안전을 위해 메모리 작업을 SEH try/except로 래핑합니다. C++을 읽을 수 없고 PE 형식 내부를 이해하지 못한다면 어차피 이것을 사용하지 않는 것이 좋습니다.