
KillDefender와 Backstab의 BOF 조합
2022년 6월 28일: Microsoft가 MsMpEng.exe 토큰에 대한 핸들 열기를 차단하는 패치를 배포하여, 이 도구의 KillDefender 부분이 더 이상 작동하지 않습니다. Backstab은 여전히 작동할 것입니다. 패치 ID는 확실하지 않으며, 구형 패치되지 않은 시스템에서는 작동할 수 있습니다. Win10 21H2 및 Win11에서 확인되었습니다.
이것은 Cobalt Strike와 함께 사용하기 위해 Yaxser의 Backstab과 pwn1sher의 KillDefender를 결합한 Beacon Object File 구현입니다.

KDStab은 Windows Defender를 무력화하기 위한 사후 침투 도구입니다(이론적으로 다른 솔루션에도 작동할 수 있지만 테스트되지 않음). 이를 통해 다른 사후 침투 도구가 탐지에 대한 두려움 없이 사용될 수 있습니다. Backstab과 KillDefender를 활용하며, kdstab Cobalt Strike 명령을 통해 적절한 시점에 두 도구가 호출됩니다.
KDStab은 x64 Windows 10, Windows 11 및 Server 2019에서 성공적으로 테스트되었습니다.
KDStab은 관리자 또는 시스템 수준의 액세스가 필요합니다.
주요 기능:
프로세스의 무결성 수준 확인
프로세스의 권한을 제거하고 무결성을 신뢰할 수 없음(Untrusted)으로 설정
PPL 보호 프로세스 종료
PPL 보호 프로세스의 핸들 목록 표시
PPL 보호 프로세스의 특정 핸들 닫기
프로세스의 무결성 수준 확인

프로세스의 권한을 제거하고 토큰을 신뢰할 수 없음(Untrusted)으로 설정

/STRIP 명령 결과

PPL 보호 프로세스 종료

pwn1sher의 KillDefender를 출시 직후 발견하고 매우 훌륭하다고 생각했습니다. MsMpEng.exe(Defender)를 무력화할 뿐만 아니라 프로세스를 계속 실행 상태로 두어 OPSEC 관점에서 바람직해 보입니다(게다가 WinDefend 서비스의 기본 동작은 실패 시 MsMpEng.exe를 다시 시작하는 것인데, 이는 나중에 유용하게 사용됩니다).
Defender를 무력화하는 것은 침투 테스트에 훌륭하지만, 전문가로서 우리는 클라이언트 자산을 원래 상태로 복원할 책임이 있습니다. 또한 Defender를 죽임으로써 시스템을 다른 공격자에게 노출시키고 싶지 않습니다.
문제는 MsMpEng.exe를 작동 상태로 "복원"하기 어렵다는 점입니다. KillDefender는 대상 프로세스의 권한(SeDebugPrivilege 등)을 제거하고 토큰 무결성을 신뢰할 수 없음으로 설정하여 작동합니다. 토큰을 다시 System으로 "상승"시키고 권한을 복원할 수는 없으며, 프로세스를 종료하고 새 인스턴스를 시작해야 합니다. 물론 MsMpEng.exe는 PsProtectedSignerAntimalware-Light 프로세스이므로 System 권한으로도 프로세스를 그냥 종료할 수 없습니다. 좌절스럽게도 최근 MsMpEng.exe에서 TrustedInstaller 그룹이 제거되어(관련 연구가 있을 수 있음) 수년간 사용되던 MsMpEng.exe(또는 WinDefend 서비스)를 실제로 종료하는 기술이 무력화되었습니다. 따라서 유일하게 실행 가능한 옵션은 시스템을 재부팅하는 것인데, 서버나 DC를 다룰 경우 클라이언트에 문제를 일으킬 수 있습니다.
이 문제를 안고 조사하던 중 Yaxser의 Backstab을 빠르게 발견했습니다. Backstab은 ProcExp 드라이버를 활용하여 PPL 보호 프로세스를 종료할 수 있습니다. 이는 sysinternals의 Microsoft 서명 드라이버로 우리에게 유리하게 작용합니다. Backstab은 OPSEC에 안전하지 않은 작업(드라이버를 디스크에 저장하고 레지스트리 키 생성)을 수행합니다. 하지만 Defender가 이미 무력화되어 있다면... :)
저는 이 두 도구를 BOF 형식으로 포팅하여 Cobalt Strike Beacon을 통해 디스크에 저장하지 않고 사용할 수 있도록 하기로 했습니다(원래 Backstab 바이너리는 런타임에 Defender에 의해 차단되었습니다).
저는 C/C++과 BOF 작성 모두 처음이라 과정에서 많은 것을 배웠습니다. 코드에 일관성이 없는 부분이 있을 수 있습니다(예: Backstab_bof는 Linux에서 gcc로 작성 및 컴파일되었고 KillDefender_bof는 Visual Studio에서 작성 및 컴파일됨). 이는 제가 만들면서 배운 결과입니다. 하지만 기능을 보장하기 위해 상당한 테스트를 수행했으며, aggressor 스크립트에 많은 레일을 구축하여 BOF에 대한 올바른 사용과 입력을 보장했습니다. 이 도구가 유용하게 사용되길 바랍니다.
도구 소스 코드에 몇 가지 주목할 만한 변경 사항과 특정 프로그래밍 선택이 있었으며, 여기서 언급하겠습니다:
ProcExp 드라이버는 더 이상 리소스로 저장/로드되지 않고 backstab_src/resource.c에 하드코딩된 바이트 배열로 저장됩니다.
원래 Backstab 코드에 여러 메모리 누수가 있었고 이를 발견하여 해결했습니다.
KillDefender POC는 사용자가 System이 아닐 때 실패합니다. 실행 중인 사용자를 열거하고 필요한 경우 Winlogon의 토큰을 가장하여 시스템 권한을 얻는 코드를 추가했습니다.
KillDefender는 사용자가 대상 프로세스를 지정할 수 있도록 수정되었습니다. 또한 프로세스의 무결성 수준을 열거하는 "Check" 모드가 추가되어 프로세스의 권한과 무결성이 성공적으로 제거되었는지 확인할 수 있습니다.
Backstab은 매우 많은 API와 C 호출을 사용하여 Cobalt Strike가 모든 동적 함수 해석을 처리하지 못했습니다. Trustedsec의 도움을 받아 CS의 동적 함수 해석을 보완하는 자체 구현을 추가하여 필요한 모든 API를 호출할 수 있게 했습니다.
원래 Backstab에는 포팅 중 문제를 일으킨 여러 switch/case 문이 있었으며, 이를 if/else 문으로 대체했습니다. 또한 비슷한 이유로 거의 모든 전역 변수를 제거했습니다.
하나의 도구는 Visual Studio용으로, 다른 하나는 GCC용으로 작성된 것이 이상하다는 점을 알고 있습니다. 이는 포팅에 어려움을 겪고 많은 시행착오를 겪은 결과입니다. 앞으로의 도구는 여기서 배운 많은 교훈을 활용할 수 있기를 바랍니다.
KillDefender_bof와 Backstab_bof는 각각 독립형 저장소로 존재합니다. 참고: 독립형 저장소의 코드와 이 도구의 코드는 다릅니다. 이는 더 유연하게 만들고 단일 패키지에 통합할 수 있도록 하기 위함입니다.
x86용으로 두 도구를 컴파일하려고 시도하지 않았습니다. x86 버전이 정말 필요하다면 직접 알아내시기 바랍니다.
Backstab_bof를 gcc로 컴파일:
x86_64-w64-mingw32-gcc -o backstab.x64.o -Os -c main.c -DBOF -D_UNICODE
mingw를 최신 버전으로 업데이트했는지 확인하십시오! 이전 버전의 헤더 파일이 오래되어 문제가 있었지만, 최신 버전의 헤더 파일은 정확합니다.
KillDefender_bof를 x64 네이티브 명령 프롬프트로 컴파일:
cl.exe /c /GS- /TP killdefender_bof.cpp /FoKillDefender.x64.o
Yaxser와 그의 Backstab 도구: https://github.com/Yaxser/Backstab
pwn1sher와 그의 KillDefender 도구: https://github.com/pwn1sher/KillDefender
Trustedsec의 CS-Situational-Awareness-BOF 저장소는 포팅 과정에서 큰 도움이 되었습니다. 이 프로젝트에서 그의 코드 일부를 사용했으며, BOF 작성에 입문하는 모든 분께 이 저장소를 적극 추천합니다: https://github.com/trustedsec/CS-Situational-Awareness-BOF