
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 — это агрессор-скрипт, использующий набор Beacon Object Files для Cobalt Strike с целью выполнения инъекций в процессы, закрепления в системе и других задач, применяя прямые системные вызовы для обхода EDR/AV.
CobaltWhispers работает на основе SysWhispers2 и InlineWhispers2
CobaltWhispers основан на StayKit, а также наработках Hasherezade и Forrest Orr.
CobaltWhispers был создан в рамках стажировки в Red Team компании NVISO Security. Соответствующие статьи в блоге можно найти здесь (process-injection) и здесь (kernel karnage).
Для компиляции CobaltWhispers требуются следующие инструменты:
apt install mingw-w64apt install makeДля работы каждого проекта необходимы 3 файла, сгенерированных SysWhispers2 / InlineWhispers2:
Эти файлы можно сгенерировать в соответствии с документацией 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) | Требуются права администратора | Примечания |
|---|---|---|---|---|
| Shellcode/Raw | PID | 5 | Нет | - |
Внедряет полезную нагрузку в удалённый процесс с помощью NtCreateThreadEx
PID процесса: идентификатор удалённого процесса
Расположение полезной нагрузки: расположение полезной нагрузки в бинарном виде на диске (условно | необязательно)
Полезная нагрузка b64: исходный шеллкод в виде строки в кодировке base64 (условно | необязательно)
Listener: Listener для генерации полезной нагрузки (условно)
Для генерации Beacon-полезной нагрузки следует указать Listener. Если требуется ручная полезная нагрузка, её необходимо указать через путь к бинарному файлу на диске или в виде шеллкода в кодировке Base64.
| Тип полезной нагрузки | Цель | Надёжность (0-5) | Требуются права администратора | Примечания |
|---|---|---|---|---|
| Shellcode/Raw | PID | 2 | Нет | Возможен крах целевого процесса |
Внедряет полезную нагрузку в удалённый процесс с помощью NtQueueApcThread
PID процесса: идентификатор удалённого процесса
Потоки: количество потоков, в которые будет добавлен вызов APC
Расположение полезной нагрузки: расположение полезной нагрузки в бинарном виде на диске (условно | необязательно)
Полезная нагрузка b64: исходный шеллкод в виде строки в кодировке base64 (условно | необязательно)
Listener: Listener для генерации полезной нагрузки (условно)
Для генерации Beacon-полезной нагрузки следует указать Listener. Если требуется ручная полезная нагрузка, её необходимо указать через путь к бинарному файлу на диске или в виде шеллкода в кодировке Base64.
| Тип полезной нагрузки | Цель | Надёжность (0-5) | Требуются права администратора | Примечания |
|---|---|---|---|---|
| Shellcode/Raw | Процесс-заместитель | 5 | Нет | - |
Внедряет полезную нагрузку в процесс-заместитель с помощью NtMapViewOfSection
Родительский процесс: имя процесса, который будет задан как родительский
Расположение исполняемого файла: расположение исполняемого файла на диске, используемого для создания нового процесса
Расположение полезной нагрузки: расположение полезной нагрузки в бинарном виде на диске (условно | необязательно)
Полезная нагрузка b64: исходный шеллкод в виде строки в кодировке base64 (условно | необязательно)
Listener: Listener для генерации полезной нагрузки (условно)
Для генерации Beacon-полезной нагрузки следует указать Listener. Если требуется ручная полезная нагрузка, её необходимо указать через путь к бинарному файлу на диске или в виде шеллкода в кодировке Base64.
| Тип полезной нагрузки | Цель | Надёжность (0-5) | Требуются права администратора | Примечания |
|---|---|---|---|---|
| PE | Процесс-заместитель | 5 | Нет | Требуется полезная нагрузка в формате x64 PE |
Внедряет полезную нагрузку в процесс-заместитель с использованием транзакционных секций и отображаемых представлений. Обновляются удалённая точка входа и PEB, отсутствуют аномальные участки памяти и необычные права доступа к памяти. Дополнительную информацию см. здесь.
Родительский процесс: имя процесса, который будет задан как родительский
Расположение исполняемого файла: расположение исполняемого файла на диске, используемого для создания нового процесса
Расположение полезной нагрузки: расположение полезной нагрузки в формате x64 PE на диске (условно | необязательно)
Полезная нагрузка b64: полезная нагрузка в формате x64 PE в виде строки в кодировке base64 (условно | необязательно)
Listener: Listener для генерации полезной нагрузки (условно)
Для генерации Beacon-полезной нагрузки следует указать Listener. Если требуется ручная полезная нагрузка, её необходимо указать через путь к x64 PE на диске или в виде x64 PE в кодировке Base64.
В НАСТОЯЩЕЕ ВРЕМЯ НЕ РЕАЛИЗОВАНО
| Тип полезной нагрузки | Цель | Надёжность (0-5) | Требуются права администратора | Примечания |
|---|---|---|---|---|
| Position Independent Shellcode (PIC) | Процесс-заместитель | 5 | Да | Для открытия системных DLL с правами на запись требуются повышенные привилегии |
Внедряет полезную нагрузку в процесс-заместитель с использованием транзакционных секций в сочетании с DLL hollowing. Дополнительную информацию см. здесь.
Родительский процесс: имя процесса, который будет задан как родительский
Расположение исполняемого файла: расположение исполняемого файла на диске, используемого для создания нового процесса
Расположение полезной нагрузки: расположение полезной нагрузки в бинарном виде на диске (условно | необязательно)
Полезная нагрузка b64: исходный шеллкод в виде строки в кодировке base64 (условно | необязательно)
Listener: Listener для генерации полезной нагрузки (условно)
Для генерации Beacon-полезной нагрузки следует указать Listener. Если требуется ручная полезная нагрузка, её необходимо указать через путь к бинарному файлу на диске или в виде шеллкода в кодировке Base64.
Создаёт или изменяет ключ реестра в указанном расположении.
Имя ключа: имя значения
Команда: команда, которая будет выполнена при использовании реестра
Ключ реестра: расположение, где будет создан ключ реестра
Скрытый: добавляет нулевой байт в начало имени ключа; вызывает ошибки в regedit
Очистка: удаляет созданный ключ
Для очистки требуются имя ключа и ключ реестра (расположение).
Создаёт или изменяет ключ реестра в указанном расположении.
Имя ключа: имя значения
Команда: команда, которая будет выполнена при использовании реестра
Ключ реестра: расположение, где будет создан ключ реестра
Скрытый: добавляет нулевой байт в начало имени ключа; вызывает ошибки в regedit
Очистка: удаляет созданный ключ
Для очистки требуются имя ключа и ключ реестра (расположение).
UserInit: автоматически задаёт «Имя ключа» и «Ключ реестра».
Создаёт или изменяет ключ реестра в указанном расположении.
Имя ключа: имя значения
Команда: команда, которая будет выполнена при использовании реестра
Ключ реестра: расположение, где будет создан ключ реестра
Скрытый: добавляет нулевой байт в начало имени ключа; вызывает ошибки в regedit
Очистка: удаляет созданный ключ
Для очистки требуются имя ключа и ключ реестра (расположение).
Создаёт или изменяет ключ реестра в указанном расположении.
Имя ключа: имя значения
Команда: команда, которая будет выполнена при использовании реестра
Ключ реестра: расположение, где будет создан ключ реестра
Скрытый: добавляет нулевой байт в начало имени ключа; вызывает ошибки в regedit
Очистка: удаляет созданный ключ
Для очистки требуются имя ключа и ключ реестра (расположение).
UserInitMprLogonScript: автоматически задаёт «Имя ключа» и «Ключ реестра».
Перехватывает COM-обработчик запланированной задачи. Создаёт ключ реестра в HKCU:\Software\Classes\CLSID\\InprocServer32, указывающий на DLL.
Class ID: CLSID, соответствующий CLSID COM-обработчика задачи
Путь к DLL: путь к DLL, которая должна быть загружена
Очистка: удаляет созданный ключ
| Надёжность (0-5) | Требуются права администратора | Примечания |
|---|---|---|
| 4 | Да | Может вызвать BSOD целевой системы |
Загружает уязвимый подписанный драйвер с произвольным чтением/записью памяти ядра (NalDrv/iqvm64.sys). Изменяет флаг g_CiEnabled в ntoskrnl.exe или флаг g_CiOptions в CI.dll для отключения проверки подписи драйверов (Driver Signature Enforcement, 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: патч целевых callback-функций ядра
Restore: восстановление целевых callback-функций ядра
Vendors: показать поддерживаемых производителей
Modules: запросить список всех загруженных драйверов
Hooked modules: показать все перехваченные драйверы
Callbacks: запросить все зарегистрированные callback-функции
Index: перехватить драйвер по индексу (см.: information - modules)
Name: перехватить драйвер по имени устройства (\Device\Name)
Values: список индексов через запятую (условно)
Name: имя устройства целевого драйвера (условно)
Значение Values обязательно при выборе «Index». Значение Name обязательно при выборе «Name».
Index: снять перехват с драйвера по индексу (см.: information - hooked modules)
All: снять перехват со всех перехваченных драйверов
Values: список индексов через запятую (условно)
Значение Values обязательно при выборе «Index».
Vendor: пропатчить все callback-функции, связанные с модулями производителя
Module: пропатчить все callback-функции, связанные с модулями
Process: пропатчить callback-функции процесса
Thread: пропатчить callback-функции потоков
Image: пропатчить callback-функции образов
Registry: пропатчить callback-функции реестра
Object process: пропатчить callback-функции объекта процесса
Object thread: пропатчить callback-функции объекта потока
Values: список индексов через запятую (см.: information - callbacks) (условно)
Name: список имён модулей через запятую или имя одного производителя (см.: information - vendors) (условно)
Значение Values обязательно при выборе «process», «thread», «image», «registry», «object process» или «object thread». Значение Name обязательно при выборе «vendor» или «module».
Vendor: восстановить все callback-функции, связанные с модулями производителя
Module: восстановить все callback-функции, связанные с модулями
Process: восстановить callback-функции процесса
Thread: восстановить callback-функции потоков
Image: восстановить callback-функции образов
Registry: восстановить callback-функции реестра
Object process: восстановить callback-функции объекта процесса
Object thread: восстановить callback-функции объекта потока
All: восстановить все callback-функции
Values: список индексов через запятую (см.: information - callbacks) (условно)
Name: список имён модулей через запятую или имя одного производителя (см.: information - vendors) (условно)
Значение Values обязательно при выборе «process», «thread», «image», «registry», «object process» или «object thread». Значение Name обязательно при выборе «vendor» или «module».