
CobaltWhispers is an aggressor script that utilizes a collection of Beacon Object Files (BOF) for Cobalt Strike to perform process injection, persistence and more, leveraging direct syscalls (SysWhispers2) to bypass EDR/AV
작성자: @Cerbersec
CobaltWhispers는 Cobalt Strike용 Beacon Object File 모음을 활용하는 aggressor 스크립트로, 직접 시스템 콜(direct syscalls)을 사용하여 EDR/AV를 우회하면서 프로세스 인젝션, 지속성 등을 수행합니다.
CobaltWhispers는 SysWhispers2와 InlineWhispers2로 구동됩니다.
CobaltWhispers는 StayKit과 Hasherezade 및 Forrest Orr의 작업을 기반으로 합니다.
CobaltWhispers는 NVISO Security의 Red Team 인턴십의 일환으로 제작되었습니다. 관련 블로그 게시물은 여기(process-injection)와 여기(kernel karnage)에서 볼 수 있습니다.
CobaltWhispers를 컴파일하려면 여러 도구가 필요합니다:
apt install mingw-w64apt install make각 프로젝트가 작동하려면 SysWhispers2 / InlineWhispers2가 생성한 3개의 파일이 필요합니다:
이 파일들은 InlineWhispers2 문서에 따라 생성할 수 있습니다. 그러나 이것이 최적의 방법은 아닙니다. 사용되지 않는 코드가 많이 포함되기 때문입니다:
git clone https://github.com/Sh0ckFR/InlineWhispers2 && cd InlineWhispers2
cd SysWhispers2/ && python3 syswhispers.py --preset all -o syscalls_all && cd ..
python3 InlineWhispers2.py
대신 SysWhispers2를 사용하여 필요한 API에 대해서만 출력 파일을 생성한 다음, InlineWhispers2에 수동(또는 스크립트)으로 제공하여 올바른 형식으로 변환하십시오. 추가 정보는 포함된 makefile을 참조하거나 포함된 파일을 사용자는 책임 하에 사용하십시오.
| 페이로드 유형 | 대상 | 신뢰도 (0-5) | 승격 권한 | 비고 |
|---|---|---|---|---|
| - | - | 5 | 아니요 | 부모 프로세스의 권한을 상속 |
Code Integrity Guard(CIG)를 활성화한 상태로 새 일시 중단 프로세스를 생성하여 Microsoft가 서명하지 않은 바이너리를 차단합니다. 지정된 부모 프로세스를 스푸핑합니다. PID가 반환됩니다.
부모 프로세스: 부모로 설정할 프로세스의 이름
실행 파일 위치: 새 프로세스를 생성하는 데 사용할 디스크의 실행 파일 전체 경로
| 페이로드 유형 | 대상 | 신뢰도 (0-5) | 승격 권한 | 비고 |
|---|---|---|---|---|
| 셸코드/원시 | PID | 5 | 아니요 | - |
NtCreateThreadEx를 사용하여 원격 프로세스에 페이로드를 주입합니다.
프로세스 PID: 원격 프로세스의 프로세스 ID
페이로드 위치: 디스크에서 바이너리 형식의 페이로드 위치 (조건부 | 선택 사항)
페이로드 b64: Base64 인코딩 문자열 형식의 원시 셸코드 (조건부 | 선택 사항)
리스너: 페이로드를 생성할 리스너 (조건부)
Beacon 페이로드를 생성하려면 리스너를 지정해야 합니다. 수동 페이로드를 사용하려면 디스크의 원시 바이너리 경로 또는 Base64 인코딩 셸코드로 제공해야 합니다.
| 페이로드 유형 | 대상 | 신뢰도 (0-5) | 승격 권한 | 비고 |
|---|---|---|---|---|
| 셸코드/원시 | PID | 2 | 아니요 | 대상 프로세스가 충돌할 수 있음 |
NtQueueApcThread를 사용하여 원격 프로세스에 페이로드를 주입합니다.
프로세스 PID: 원격 프로세스의 프로세스 ID
스레드: APC 호출을 추가할 스레드 수
페이로드 위치: 디스크에서 바이너리 형식의 페이로드 위치 (조건부 | 선택 사항)
페이로드 b64: Base64 인코딩 문자열 형식의 원시 셸코드 (조건부 | 선택 사항)
리스너: 페이로드를 생성할 리스너 (조건부)
Beacon 페이로드를 생성하려면 리스너를 지정해야 합니다. 수동 페이로드를 사용하려면 디스크의 원시 바이너리 경로 또는 Base64 인코딩 셸코드로 제공해야 합니다.
| 페이로드 유형 | 대상 | 신뢰도 (0-5) | 승격 권한 | 비고 |
|---|---|---|---|---|
| 셸코드/원시 | 대리 프로세스 | 5 | 아니요 | - |
NtMapViewOfSection을 사용하여 대리 프로세스에 페이로드를 주입합니다.
부모 프로세스: 부모로 설정할 프로세스의 이름
실행 파일 위치: 새 프로세스를 생성하는 데 사용할 디스크의 실행 파일 위치
페이로드 위치: 디스크에서 바이너리 형식의 페이로드 위치 (조건부 | 선택 사항)
페이로드 b64: Base64 인코딩 문자열 형식의 원시 셸코드 (조건부 | 선택 사항)
리스너: 페이로드를 생성할 리스너 (조건부)
Beacon 페이로드를 생성하려면 리스너를 지정해야 합니다. 수동 페이로드를 사용하려면 디스크의 원시 바이너리 경로 또는 Base64 인코딩 셸코드로 제공해야 합니다.
| 페이로드 유형 | 대상 | 신뢰도 (0-5) | 승격 권한 | 비고 |
|---|---|---|---|---|
| PE | 대리 프로세스 | 5 | 아니요 | x64 PE 페이로드 필요 |
트랜잭션 섹션(transacted sections)과 매핑된 뷰(mapped views)를 사용하여 대리 프로세스에 페이로드를 주입합니다. 원격 진입점과 PEB가 업데이트되며, 비정상적인 메모리 섹션이나 메모리 권한이 남지 않습니다. 자세한 내용은 여기를 참조하십시오.
부모 프로세스: 부모로 설정할 프로세스의 이름
실행 파일 위치: 새 프로세스를 생성하는 데 사용할 디스크의 실행 파일 위치
페이로드 위치: 디스크에서 x64 PE 페이로드 위치 (조건부 | 선택 사항)
페이로드 b64: Base64 인코딩 문자열 형식의 x64 PE 페이로드 (조건부 | 선택 사항)
리스너: 페이로드를 생성할 리스너 (조건부)
Beacon 페이로드를 생성하려면 리스너를 지정해야 합니다. 수동 페이로드를 사용하려면 디스크의 x64 PE 경로 또는 Base64 인코딩 x64 PE로 제공해야 합니다.
현재 구현되지 않음
| 페이로드 유형 | 대상 | 신뢰도 (0-5) | 승격 권한 | 비고 |
|---|---|---|---|---|
| 위치 독립 셸코드(PIC) | 대리 프로세스 | 5 | 예 | 쓰기 권한으로 시스템 DLL을 열려면 승격된 권한이 필요 |
트랜잭션 섹션을 DLL 하로잉과 결합하여 대리 프로세스에 페이로드를 주입합니다. 자세한 내용은 여기를 참조하십시오.
부모 프로세스: 부모로 설정할 프로세스의 이름
실행 파일 위치: 새 프로세스를 생성하는 데 사용할 디스크의 실행 파일 위치
페이로드 위치: 디스크에서 바이너리 형식의 페이로드 위치 (조건부 | 선택 사항)
페이로드 b64: Base64 인코딩 문자열 형식의 원시 셸코드 (조건부 | 선택 사항)
리스너: 페이로드를 생성할 리스너 (조건부)
Beacon 페이로드를 생성하려면 리스너를 지정해야 합니다. 수동 페이로드를 사용하려면 디스크의 원시 바이너리 경로 또는 Base64 인코딩 셸코드로 제공해야 합니다.
지정된 위치에 레지스트리 키를 생성하거나 수정합니다.
키 이름: 값 이름
명령: 레지스트리가 사용될 때 실행할 명령
레지스트리 키: 레지스트리 키가 생성될 위치
숨김: 키 이름 앞에 null 바이트를 추가하며 regedit에서 오류를 발생시킵니다
정리: 생성된 키를 제거
정리 기능을 사용하려면 키 이름과 레지스트리 키(위치)가 필요합니다.
지정된 위치에 레지스트리 키를 생성하거나 수정합니다.
키 이름: 값 이름
명령: 레지스트리가 사용될 때 실행할 명령
레지스트리 키: 레지스트리 키가 생성될 위치
숨김: 키 이름 앞에 null 바이트를 추가하며 regedit에서 오류를 발생시킵니다
정리: 생성된 키를 제거
정리 기능을 사용하려면 키 이름과 레지스트리 키(위치)가 필요합니다.
UserInit: '키 이름'과 '레지스트리 키'를 자동으로 설정합니다.
지정된 위치에 레지스트리 키를 생성하거나 수정합니다.
키 이름: 값 이름
명령: 레지스트리가 사용될 때 실행할 명령
레지스트리 키: 레지스트리 키가 생성될 위치
숨김: 키 이름 앞에 null 바이트를 추가하며 regedit에서 오류를 발생시킵니다
정리: 생성된 키를 제거
정리 기능을 사용하려면 키 이름과 레지스트리 키(위치)가 필요합니다.
지정된 위치에 레지스트리 키를 생성하거나 수정합니다.
키 이름: 값 이름
명령: 레지스트리가 사용될 때 실행할 명령
레지스트리 키: 레지스트리 키가 생성될 위치
숨김: 키 이름 앞에 null 바이트를 추가하며 regedit에서 오류를 발생시킵니다
정리: 생성된 키를 제거
정리 기능을 사용하려면 키 이름과 레지스트리 키(위치)가 필요합니다.
UserInitMprLogonScript: '키 이름'과 '레지스트리 키'를 자동으로 설정합니다.
예약 작업의 COM 핸들러를 하이재킹합니다. DLL을 가리키는 HKCU:\Software\Classes\CLSID\\InprocServer32에 레지스트리 키를 생성합니다.
클래스 ID: 작업의 COM 핸들러 CLSID에 해당하는 CLSID
DLL 경로: 로드할 DLL의 경로
정리: 생성된 키를 제거
| 신뢰도 (0-5) | 승격 권한 | 비고 |
|---|---|---|
| 4 | 예 | 대상 시스템이 BSOD가 발생할 수 있음 |
임의의 커널 메모리 읽기/쓰기가 가능한 서명된 취약 드라이버(NalDrv/iqvm64.sys)를 로드합니다. ntoskrnl.exe의 g_CiEnabled 또는 CI.dll의 g_CiOptions 플래그를 변경하여 드라이버 서명 적용(DSE)을 비활성화합니다.
서명되지 않은 드라이버(Interceptor/Interceptor.sys)를 로드한 다음 DSE 플래그 값을 복원합니다. 서명된 드라이버와 서명되지 않은 드라이버 모두 디스크에 기록됩니다.
| 드라이버 | MD5 체크섬 |
|---|---|
| iqvm64.sys | 1898ceda3247213c084f43637ef163b3 |
| Interceptor.sys | 508c8943359717cfa0c77b61ebea2118 |
취약 드라이버 위치: 디스크에서 바이너리 형식의 서명된 취약 드라이버 위치
악성 드라이버 위치: 디스크에서 바이너리 형식의 악성 비서명 드라이버 위치
취약 드라이버 이름: 레지스트리 키 '\Registry\Machine\System\CurrentControlSet\Services\'를 생성하는 데 사용되는 이름
취약 드라이버 장치 이름: 드라이버에 접촉하는 데 사용되는 이름 '\DosDevices\'
악성 드라이버 이름: 레지스트리 키 '\Registry\Machine\System\CurrentControlSet\Services\'를 생성하는 데 사용되는 이름
악성 드라이버 장치 이름: 드라이버에 접촉하는 데 사용되는 이름 '\DosDevices\'
대상 경로: 취약 드라이버 및 악성 드라이버 파일을 기록할 임시 경로
| 신뢰도 (0-5) | 승격 권한 | 비고 |
|---|---|---|
| 5 | 예 | - |
제공된 레지스트리 키를 사용하여 대상에서 드라이버를 언로드하고 지정된 경로의 디스크에서 바이너리를 삭제합니다.
드라이버 레지스트리 키: 드라이버를 언로드하는 데 사용되는 레지스트리 키 '\Registry\Machine\System\CurrentControlSet\Services\'
드라이버 설치 경로: 디스크에서 드라이버 위치
| 신뢰도 (0-5) | 승격 권한 | 비고 |
|---|---|---|
| 4 | 아니요 | 대상 시스템이 BSOD가 발생할 수 있음 |
정보(Information): Interceptor 드라이버를 쿼리
후킹(Hook): 대상 드라이버의 주요 함수(IRP)를 후킹
언후킹(Unhook): 대상 드라이버의 주요 함수를 복원
패치(Patch): 대상 커널 콜백을 패치
복원(Restore): 대상 커널 콜백을 복원
공급업체: 지원되는 공급업체 표시
모듈: 로드된 모든 드라이버 쿼리
후킹된 모듈: 후킹된 모든 드라이버 표시
콜백: 등록된 모든 콜백 쿼리
인덱스: 인덱스로 드라이버 후킹 (참조: 정보 - 모듈)
이름: 장치 이름으로 드라이버 후킹 (\Device\Name)
값: 쉼표로 구분된 인덱스 목록 (조건부)
이름: 대상 드라이버의 장치 이름 (조건부)
'인덱스'를 선택하면 값이 필요합니다. '이름'을 선택하면 이름이 필요합니다.
인덱스: 인덱스로 드라이버 언후킹 (참조: 정보 - 후킹된 모듈)
모두: 후킹된 모든 드라이버 언후킹
값: 쉼표로 구분된 인덱스 목록 (조건부)
'인덱스'를 선택하면 값이 필요합니다.
공급업체: 공급업체 모듈과 연결된 모든 콜백 패치
모듈: 모듈과 연결된 모든 콜백 패치
프로세스: 프로세스 콜백 패치
스레드: 스레드 콜백 패치
이미지: 이미지 콜백 패치
레지스트리: 레지스트리 콜백 패치
개체 프로세스: 개체 프로세스 콜백 패치
개체 스레드: 개체 스레드 콜백 패치
값: 쉼표로 구분된 인덱스 목록 (참조: 정보 - 콜백) (조건부)
이름: 쉼표로 구분된 모듈 이름 목록 또는 단일 공급업체 이름 (참조: 정보 - 공급업체) (조건부)
'프로세스', '스레드', '이미지', '레지스트리', '개체 프로세스' 또는 '개체 스레드'를 선택하면 값이 필요합니다. '공급업체' 또는 '모듈'을 선택하면 이름이 필요합니다.
공급업체: 공급업체 모듈과 연결된 모든 콜백 복원
모듈: 모듈과 연결된 모든 콜백 복원
프로세스: 프로세스 콜백 복원
스레드: 스레드 콜백 복원
이미지: 이미지 콜백 복원
레지스트리: 레지스트리 콜백 복원
개체 프로세스: 개체 프로세스 콜백 복원
개체 스레드: 개체 스레드 콜백 복원
모두: 모든 콜백 복원
값: 쉼표로 구분된 인덱스 목록 (참조: 정보 - 콜백) (조건부)
이름: 쉼표로 구분된 모듈 이름 목록 또는 단일 공급업체 이름 (참조: 정보 - 공급업체) (조건부)
'프로세스', '스레드', '이미지', '레지스트리', '개체 프로세스' 또는 '개체 스레드'를 선택하면 값이 필요합니다. '공급업체' 또는 '모듈'을 선택하면 이름이 필요합니다.