
Freeze는 일시 중단된 프로세스, 직접 시스템 콜 및 대체 실행 방법을 사용하여 EDR을 우회하기 위한 페이로드 툴킷입니다.
Freeze의 최신 버전을 확인하거나 이슈를 제출하려면 https://github.com/Tylous/Freeze를 참조하세요.
이 프레임워크에서 사용된 기술에 대해 더 자세히 알고 싶다면 SourceZero 블로그를 참조하세요.
Freeze는 EDR 보안 제어를 우회하여 쉘코드를 은밀하게 실행하기 위한 페이로드 생성 도구입니다. Freeze는 사용자랜드 EDR 후크를 제거할 뿐만 아니라 다른 엔드포인트 모니터링 제어를 우회하는 방식으로 쉘코드를 실행하기 위해 여러 기술을 활용합니다.
프로세스가 생성될 때 Ntdll.dll이 가장 먼저 로드되는 DLL입니다. 이는 모든 EDR DLL이 로드되기 전에 발생합니다. 즉, EDR이 로드되어 시스템 DLL의 어셈블리를 후킹하고 수정하기 전에 약간의 지연이 있습니다. Ntdll.dll의 Windows 시스템 콜을 살펴보면 아직 아무것도 후킹되지 않은 것을 확인할 수 있습니다. 일시 중단 상태(시간이 멈춘 상태)로 프로세스를 생성하면 Ntdll.dll을 제외한 다른 DLL이 로드되지 않은 것을 볼 수 있습니다. 또한 EDR DLL이 로드되지 않았으므로 Ntdll.dll에 있는 시스템 콜이 수정되지 않았음을 의미합니다.
이 깨끗한 일시 중단된 프로세스를 사용하여 Freeze 로더에서 후크를 제거하려면 프로그래밍 방식으로 깨끗한 일시 중단된 프로세스의 메모리를 찾고 읽는 방법이 필요합니다. 여기서 주소 공간 레이아웃 무작위화(ASLR)가 등장합니다. ASLR은 스택 메모리 손상 기반 취약점을 방지하기 위한 보안 메커니즘입니다. ASLR은 프로세스 내의 주소 공간을 무작위화하여 모든 메모리 매핑된 객체, 스택, 힙, 실행 프로그램 자체가 고유하도록 보장합니다. 여기서 흥미로운 점은 ASLR이 작동하지만 DLL과 같은 위치 독립 코드에는 적용되지 않는다는 것입니다. DLL(특히 알려진 시스템 DLL)의 경우 주소 공간이 부팅 시 한 번 무작위화됩니다. 즉, 원격 프로세스 정보를 열거하여 ntdll.dll의 기본 주소를 찾을 필요가 없습니다. 왜냐하면 우리가 제어하는 프로세스를 포함한 모든 프로세스에서 동일하기 때문입니다. 모든 DLL의 주소는 부팅할 때마다 동일한 위치에 있으므로, 우리는 자신의 프로세스에서 이 정보를 가져올 수 있으며 일시 중단된 프로세스를 열거하여 주소를 찾을 필요가 없습니다.
이 정보를 사용하여 API ReadProcessMemory를 통해 프로세스의 메모리를 읽을 수 있습니다. 이 API 호출은 일반적으로 자격 증명 기반 공격의 일부로 LSASS를 읽는 것과 관련이 있습니다. 그러나 그 자체로는 본질적으로 악의적이지 않으며, 특히 임의의 메모리 섹션을 읽는 경우에는 더욱 그렇습니다. ReadProcessMemory가 의심스러운 것으로 플래그 지정되는 유일한 경우는 읽지 말아야 할 내용(예: LSASS 내용)을 읽는 경우입니다. EDR 제품은 ReadProcessMemory가 호출되었다는 사실 자체를 플래그 지정해서는 안 됩니다. 이 함수에는 합법적인 운영상의 용도가 있으며 많은 오탐지가 발생할 수 있기 때문입니다.
전체 DLL을 읽는 대신 모든 시스템 콜이 저장된 Ntdll.dll의 .text 섹션만 읽음으로써 한 단계 더 나아갈 수 있습니다.
이러한 요소를 결합하여 쉘코드를 실행하기 전에 기존의 후킹된 .text 섹션을 덮어쓰기 위해 Ntdll.dll의 .text 섹션 사본을 프로그래밍 방식으로 얻을 수 있습니다.
ETW는 내장된 시스템 콜을 사용하여 이 원격 측정 정보를 생성합니다. ETW는 또한 Windows에 내장된 기본 기능이므로 보안 제품이 해당 정보에 접근하기 위해 ETW 시스템 콜을 '후킹'할 필요가 없습니다. 결과적으로 ETW를 방지하기 위해 Freeze는 여러 ETW 시스템 콜을 패치하여 레지스터를 비우고 실행 흐름을 다음 명령어로 반환합니다. ETW 패치는 이제 모든 로더에서 기본값입니다.
오직 Ntdll.dll만 복원되므로, 쉘코드를 실행하기 위한 모든 후속 호출은 Ntdll.dll에 있어야 합니다. Go를 사용하면 (다른 언어로도 가능하지만 Go에서는 구현하기가 매우 쉽습니다) 쉘코드를 할당, 쓰기 및 보호하는 데 필요한 NT 시스템 콜을 정의하고 호출하여 kernel32d.dll 및 Kernelbase.dll에 있는 표준 호출을 효과적으로 건너뛸 수 있습니다. 이러한 DLL은 여전히 후킹되어 있을 수 있기 때문입니다.
Freeze는 Golang으로 개발되었습니다.
Freeze를 설치하려면 다음 명령어를 실행하거나 컴파일된 바이너리를 사용하세요:
go build Freeze.go
___________
\_ _____/______ ____ ____ ________ ____
| __) \_ __ \_/ __ \_/ __ \\___ // __ \
| \ | | \/\ ___/\ ___/ / /\ ___/
\___ / |__| \___ >\___ >_____ \\___ >
\/ \/ \/ \/ \/
(@Tyl0us)
그들은 곧 복수는 차갑게 대접하는 것이 가장 좋은 요리라는 것을 알게 될 것입니다...
./Freeze 사용법:
-I string
원시 64비트 쉘코드의 경로.
-O string
출력 파일의 이름 (예: loader.exe 또는 loader.dll). 정의된 파일 확장자에 따라 Freeze가 DLL 또는 EXE를 생성할지 결정됩니다.
-console
바이너리 페이로드 전용 - 페이로드 실행 시 자세한 콘솔 정보를 생성합니다. 이 옵션은 숨겨진 창 기능을 비활성화합니다.
-encrypt
AES 256 암호화를 사용하여 쉘코드를 암호화합니다.
-export string
DLL 로더 전용 - 로더가 가질 특정 내보내기 함수를 지정합니다.
-process string
생성할 프로세스의 이름. 이 프로세스는 C:\Windows\System32\에 존재해야 합니다. 예: 'notepad.exe' (기본값 "notepad.exe")
-sandbox
샌드박스 회피를 활성화합니다. 다음을 확인합니다:
엔드포인트가 도메인에 가입되어 있는가?
엔드포인트에 2개 이상의 CPU가 있는가?
엔드포인트에 4GB 이상의 RAM이 있는가?
-sha256
로더의 SHA256 값을 제공합니다 (추적에 유용함)
Freeze는 .exe 또는 .dll 파일을 생성할 수 있습니다. 이를 지정하려면 -O 명령줄 옵션이 바이너리의 경우 .exe로, DLL의 경우 .dll로 끝나도록 하십시오. 현재 다른 파일 형식은 지원되지 않습니다. DLL 파일의 경우 Freeze는 추가 내보내기 기능을 추가할 수도 있습니다. 이렇게 하려면 -export와 함께 특정 내보내기 함수 이름을 사용하십시오.
Freeze는 먼저 프로세스를 생성한 다음 백그라운드로 이동시키는 기술을 사용합니다. 이는 두 가지 효과를 냅니다. 첫째, 프로세스를 숨기고, 둘째, EDR 제품에 탐지되는 것을 방지합니다. 프로세스를 바로 백그라운드에서 생성하는 것은 매우 의심스러울 수 있으며 악성 행위의 지표가 될 수 있습니다. Freeze는 프로세스가 생성되고 EDR의 후크가 로드된 후 'GetConsoleWindow' 및 'ShowWindow' Windows 함수를 호출한 다음 창 속성을 숨김으로 변경하여 이를 수행합니다. Freeze는 전통적인 -ldflags -H=windowsgui를 사용하는 대신 이러한 API를 사용합니다. 이 플래그는 대부분의 보안 제품에서 침해 지표로 높은 시그니처를 가지며 분류되기 때문입니다.
-console 명령줄 옵션이 선택되면 Freeze는 프로세스를 백그라운드에 숨기지 않습니다. 대신 Freeze는 로더가 수행 중인 작업을 표시하는 여러 디버그 메시지를 추가합니다.