
RefleXXion은 AV/EPP/EDR 등에서 사용하는 사용자 모드 후크를 우회하는 데 도움을 주기 위해 설계된 유틸리티입니다. 사용자 모드 후크를 우회하기 위해 먼저 LdrpThunkSignature 배열에서 발견된 NtOpenFile, NtCreateSection, NtOpenSection 및 NtMapViewOfSection의 syscall 번호를 수집합니다.

RefleXXion은 AV/EPP/EDR 등에서 사용하는 사용자 모드 후크를 우회하는 데 도움을 주는 유틸리티입니다. 사용자 모드 후크를 우회하기 위해 먼저 LdrpThunkSignature 배열에서 NtOpenFile, NtCreateSection, NtOpenSection 및 NtMapViewOfSection의 시스템 콜 번호를 수집합니다. 그런 다음 사용자가 선택할 수 있는 두 가지 기술이 있습니다.
기술-1은 C:\Windows\System32\ntdll.dll에서 NTDLL을 파일로 읽어옵니다. 파싱 후 메모리에 이미 로드된 NTDLL(후크가 수행된 곳)의 .TEXT 섹션을 깨끗한 NTDLL의 .TEXT 섹션으로 교체합니다.
기술-2에서는 NTDLL을 KnownDlls(\KnownDlls\ntdll.dll)에서 섹션으로 읽어옵니다(DLL 파일이 KnownDlls에 섹션으로 캐시되기 때문). 파싱 후 메모리에 이미 로드된 NTDLL(후크가 수행된 곳)의 .TEXT 섹션을 깨끗한 NTDLL의 .TEXT 섹션으로 교체합니다.
방법론 및 모든 기술의 상세 흐름은 아래와 같습니다.

Visual Studio로 프로젝트를 열고 컴파일할 수 있습니다. 전체 프로젝트는 Debug 및 Release 모드 모두에서 x64 아키텍처를 지원합니다.
RefleXXion-EXE 솔루션은 PoC 목적으로 EXE를 생성합니다. 프로젝트가 단계별로 어떻게 작동하는지 이해하려면 이 방법이 더 쉬울 것입니다. Main 함수에는 Technique1 및 Technique2 함수 정의가 포함되어 있습니다. 하나를 주석 처리하고 컴파일하세요. 두 함수를 동시에 사용하지 마십시오.
RefleXXion-DLL 솔루션은 NTDLL에 대한 사용자 모드 후크를 우회하려는 프로세스에 주입할 DLL을 생성합니다. main.cpp 파일의 시작 부분에 사용할 기술에 대한 정의가 있습니다. 원하는 기술을 선택하여 컴파일할 수 있습니다. 모든 값을 동시에 설정하지 말고, 원하는 기술 하나만 설정하세요. 예제 구성은 아래와 같습니다.
// Techniques configuration section
#define FROM_DISK 1 // 1로 설정하면 기술-1이 사용됩니다. 자세한 내용은 https://github.com/hlldz/RefleXXion
#define FROM_KNOWNDLLS 0 // 1로 설정하면 기술-2가 사용됩니다. 자세한 내용은 https://github.com/hlldz/RefleXXion
RefleXXion은 현재 x64 아키텍처만 지원합니다.
RefleXXion은 NTDLL 함수만 언후크(unhook)합니다. 다른 DLL(kernel32.dll, advapi32.dll 등)도 언후크해야 할 수 있습니다. 이를 위해 프로젝트에서 필요한 부분을 쉽게 수정할 수 있습니다.
RefleXXion은 .TEXT 섹션 덮어쓰기 프로세스가 시작될 때만 RWX 메모리 영역을 사용합니다. 이 과정을 위해 새로운 메모리 영역을 생성하지 않고, 기존 메모리 영역(이미 로드된 NTDLL의 TEXT 섹션)을 RWX로 변경한 후 RX로 다시 변경합니다.
ULONG oldProtection;
ntStatus = NtProtectVirtualMemory(NtCurrentProcess(), &lpBaseAddress, &uSize, PAGE_EXECUTE_READWRITE, &oldProtection);
memcpy()...
ntStatus = NtProtectVirtualMemory(NtCurrentProcess(), &lpBaseAddress, &uSize, oldProtection, &oldProtection);
참고: RefleXXion은 깨끗하게 설치된 NTDLL을 통해 NtProtectVirtualMemory API를 호출합니다. 이를 위해 CustomGetProcAddress 함수를 사용하는데, 깨끗한 NTDLL이 메모리에 로드되었음에도 InLoadOrderModuleList에 없기 때문입니다. 따라서 여기(https://stackoverflow.com/questions/6734095/how-to-get-module-handle-from-func-ptr-in-win32)와 같은 방법은 작동하지 않습니다. 그래서 커스텀 GetProcAddress 함수가 존재하며 사용됩니다.
디스크에서 RefleXXion DLL을 대상 프로세스에 로드할 수 있습니다. Red Team 작전과 같은 민감한 작업에서는 이와 같은 실행을 선호하지 않을 수 있습니다. 따라서 sRDI 프로젝트를 사용하여 RefleXXion DLL을 셸코드로 변환하거나 RefleXXion 코드를 자체 로더나 프로젝트에 통합할 수 있습니다.
주입된 프로세스에 NTDLL(파일 또는 섹션으로)을 다시 로드하더라도 로드된 상태로 유지되지 않습니다. RefleXXion은 자체 프로세스를 위해 열린 모든 핸들(파일 및 섹션 핸들)을 닫습니다.