Посібник з CobaltStrike. №8 Beacon Object File’и

19 червня 2023 4 хвилин Автор: Lady Liberty

Посібник з CobaltStrike для Beacon Object File’ів та ефективного керування кібератаками

Наш посібник з CobaltStrike пропонує докладну інформацію та керівництво щодо використання Beacon Object File’ів, які є ключовими елементами для розгортання та керування Beacon-агентами в CobaltStrike. Ви дізнаєтеся про основні принципи роботи Beacon Object File’ів, їх роль у комунікації з цільовою системою, а також про способи оптимізації та налаштування для досягнення максимальної ефективності кібератак. У посібнику ми представимо різні варіанти використання Beacon Object File’ів, включаючи створення та налаштування власних файлів, а також використання готових шаблонів. Ми також розглянемо техніки обфускації та захисту Beacon-агентів, що дозволить вам уникнути виявлення та піддатися аналізу з боку захисних механізмів.

Наш посібник з CobaltStrike надає чіткі пояснення, крок за кроком інструкції та практичні поради щодо використання Beacon Object File’ів. Ви отримаєте необхідні знання та навички, щоб ефективно використовувати ці файли для керування кібератаками та забезпечення надійної присутності в цільовій системі. Отримайте доступ до посібника з CobaltStrike вже сьогодні і розкрийте потенціал Beacon Object File’ів для ефективного керування вашими кібератаками в цифровому просторі. В посібнику з CobaltStrike: Beacon Object File’и ми глибоко дослідимо цю ключову функціональність CobaltStrike, що дозволяє створювати та налаштовувати Beacon-агентів для керування та взаємодії з цільовими системами. Ми розкриємо різні аспекти використання Beacon Object File’ів, такі як створення, налаштування і оптимізація, а також принципи комунікації з CobaltStrike сервером. В посібнику ви знайдете практичні поради, крок за кроком інструкції та приклади коду, що допоможуть вам зрозуміти та використовувати Beacon Object File’и на практиці. Ви дізнаєтеся, як створювати налаштовані файли для Beacon-агентів, як забезпечити надійну комунікацію зі своїми агентами, а також як виконувати оптимізацію для підвищення продуктивності та ефективності вашої кібератаки.

Beacon Object File’и

Beacon Object File (BOF) – це скомпільована програма C, написана відповідно до певних угод, які дозволяють їй працювати як частина процесу Beacon та використовувати внутрішні API Beacon. BOF – це спосіб швидко розширити агент Beacon за допомогою нових функцій після експлуатації.

Які переваги конвертерів?

Однією з ключових ролей платформи командування і управління є забезпечення способів використання зовнішніх функціональних можливостей для постоперації.

Cobalt Strike вже має інструменти для використання бібліотек DLL PowerShell, .NET і Reflective. Ці інструменти покладаються на шаблон fork and run OPSEC, який включає створення та впровадження процесів для кожної післяопераційної діяльності. Конвертери мають простіший спосіб. Вони працюють всередині процесу Beacon, і пам’яттю можна керувати за допомогою профілю Malleable c2 у блоці ін’єкцій процесу.

Конвертери також дуже маленькі. Реалізація відбивної бібліотеки DLL для обходу UAC з ескалацією привілеїв може важити більше 100 КБ. Той самий експлойт, створений як конвертер, має розмір <3 Кб. Це може мати велике значення при використанні схем з обмеженням пропускної здатності, таких як DNS.

Нарешті, конвертерний конвертер легко розробляти. Вам просто потрібен компілятор Win32 C і командний рядок. MinGW і компілятор C від Microsoft можуть створювати конвертерні файли. Вам не доведеться возитися з налаштуваннями проекту, які часом вимагають більше зусиль, ніж сам код.

Як працюють конвертерні конвертери?

З точки зору Beacon, конвертер – це просто блок позиційно-незалежного коду, який отримує вказівники на деякі внутрішні API маяка.

З точки зору Cobalt Strike, конвертер – це об’єктний файл, створений компілятором C. CobaltStrike аналізує цей файл і діє як зв’язувач і завантажувач його вмісту. Такий підхід дозволяє писати позиційно-незалежний код для використання в Beacon без виснажливої роботи з маніпулювання рядками і динамічного виклику API Win32.

Які недоліки конвертерів?

BOF – це однофайлові програми C, які викликають API Win32 та обмежені API маяка. Не очікуйте підключення інших функціональних можливостей або створення великих проектів за допомогою цього механізму.

Cobalt Strike не пов’язує ваш BOF з libc. Це означає, що ви обмежені інтриксиканами компіляторів  (наприклад, stosb у Visual Studio для memset), відкритими внутрішніми API маяків, API Win32 та функціями, які ви пишете. Очікуйте, що багато розподілених функцій (наприклад, strlen, stcmp тощо) не будуть доступні для вас через BOF.

Конвертер виконується всередині вашого маяка. Якщо конвертер вийде з ладу, ви або ваш друг втратите доступ. Уважно пишіть свої кисневі.

Cobalt Strike очікує, що ваші конвертери будуть однопотоковими програмами, які працюють протягом короткого періоду часу. BOF блокуватимуть виконання інших завдань та функцій маяка. Не існує шаблону конвертера для асинхронних або тривалих завдань. Якщо ви хочете зробити можливим довгострокову роботу, розгляньте рефлективну бібліотеку DLL, яка працює всередині процесу жертви.

Як створити конвертер?

Це легко. Відкрийте текстовий редактор і почніть писати програму на мові С. Нижче представлена програма Hello World для BOF:

#include <windows.h> #include "beacon.h"
void go(char * args, int alen) {
BeaconPrintf(CALLBACK_OUTPUT, "Hello World: %s", args);
}

Завантажте beacon.h.

Щоб скомпілювати його за допомогою Visual Studio:

cl.exe /c /GS- hello.c /Fohello.o

Щоб скомпілювати його за допомогою x86 MinGW:

i686-w64-mingw32-gcc -c hello.c -o hello.o

Щоб скомпілювати його за допомогою x64 MinGW:

x86_64-w64-mingw32-gcc -c hello.c -o hello.o

Наведені вище команди створюють файл hello.o. Використовуйте inline-execute в Маяк для запуску конвертера.

маяк> inline-execute /путь/до/hello.o аргументи

beacon.h містить визначення для декількох внутрішніх API Beacon. Функція go аналогічна основній в будь-якій іншій програмі на мові C. Це функція, яка викликається з inline-execute і аргументи передаються їй.  BeaconOutput  – це функція API Beacon для відправки виводу оператору. Нічого особливого в цьому немає.

Роздільна здатність динамічної функції

GetProcAddress, LoadLibraryA, GetModuleHandle та FreeLibrary доступні у файлах BOF. У вас є можливість використовувати їх для вирішення функцій API Win32, які ви хочете викликати. Іншим варіантом є використання динамічної роздільної здатності функцій (DFR).

Роздільна здатність динамічних функцій — це умовність оголошення та виклику API Win32 як функції LIBRARY$. Ця угода надає Маяку інформацію, необхідну для явного дозволу певної функції та надання доступу до Вашого файлу конвертера перед його запуском. Якщо цей процес не вдасться, Cobalt Strike відмовиться виконувати конвертер і повідомить, яку функцію йому не вдалося усунути.

Нижче наведено приклад конвертера, який використовує DFR і отримує поточний домен:

#include <windows.h> #include <stdio.h> #include <dsgetdc.h> #include "beacon.h"

DECLSPEC_IMPORT DWORD WINAPI NETAPI32$DsGetDcNameA(LPVOID, LPVOID, LPVOID, LPVOID,
ULONG, LPVOID); DECLSPEC_IMPORT DWORD WINAPI NETAPI32$NetApiBufferFree(LPVOID);

void go(char * args, int alen) { DWORD dwRet;
PDOMAIN_CONTROLLER_INFO pdcInfo;

dwRet = NETAPI32$DsGetDcNameA(NULL, NULL, NULL, NULL, 0, &pdcInfo); if (ERROR_SUCCESS == dwRet) {
BeaconPrintf(CALLBACK_OUTPUT, "%s", pdcInfo->DomainName);
}

NETAPI32$NetApiBufferFree(pdcInfo);
}

Наведений вище код здійснює виклики DFR до DsGetDcNameA та NetApiBufferFree від NETAPI32. Коли ви оголошуєте прототипи функцій для динамічного вирішення функцій, зверніть особливу увагу на декоратори, додані до оголошення функції. Такі ключові слова, як WINAPI та DECLSPEC_ IMPORT, дуже важливі. Ці декоратори надають компілятору необхідні підказки для передачі аргументів і генерації правильної інструкції для виклику.

Сценарій агресора і конвертери

Ймовірно, ви захочете використовувати Aggressor Script для запуску ваших остаточних реалізацій BOF в Cobalt Strike. BOF є хорошим інструментом для реалізації техніки бічного руху, інструменту ескалації привілеїв або нової можливості дослідження. Функція &beacon_inline_execute  є точкою входу сценарію агресора для запуску Киснево-конвертерний файл.

Ось сценарій для запуску простої програми Hello World:

alias hello {
local('$barch $handle $data $args');

# Визначення архітектури цієї сесії
$barch = барч ($1);

# читання з потрібного киснево-конвертерного файлу
$handle = openf(script_resource("привіт. $+ $barch $+ .o"));
$data	= readb($handle, -1);  closef($handle);

# Пакуємо наші аргументи
$args	= bof_pack($1, "zi", "Hello World", 1234);

# Оголошення про те, що ми робимо
btask($1, «Біг Hello BOF»);

# Страта
beacon_inline_execute($1, $data, "демо", $args);
}

По-перше, скрипт визначає архітектуру сеансу. x86 BOF працюватиме лише в сеансі маяка x86. І навпаки, x64 BOF працюватиме лише в сеансі маяка x64. Потім цей сценарій зчитує цільовий BOF у змінну сценарію агресора. Наступним кроком є упакування наших  аргументів. Функція &bof_pack  пакує аргументи таким чином, сумісним із внутрішнім API аналізатора даних Beacon. Цей сценарій використовує функцію normal &btask для  логування дій, які користувач довірив Маяку. A &beacon_inline_execute запускає BOF зі своїми аргументами.

Функція &beacon_inline_execute   приймає ідентифікатор маяка як перший аргумент, рядок, що містить вміст BOF як другий аргумент, точку входу як третій аргумент, а запаковані аргументи як четвертий аргумент. Можливість вибору точки входу існує на випадок, якщо ви вирішите об’єднати подібні функції в один конвертер.

Нижче представлена програма C, що відповідає наведеному вище сценарію:

/*
1.	Компіляція за допомогою:
1.	x86_64-w64-mingw32-gcc -c hello.c -o hello.x64.o
2.	i686-w64-mingw32-gcc -c hello.c -o hello.x86.o
*/
#include <windows.h> #include <stdio.h> #include <tlhelp32.h> #include "beacon.h"
void demo(char * args, int length) { datap parser;
char * str_arg;
int num arg;
BeaconDataParse(&parser, args, length); str_arg = BeaconDataExtract(&parser, NULL); num_arg = BeaconDataInt(&parser);

BeaconPrintf(CALLBACK_OUTPUT, "Message is %s with %d arg", str_arg, num_arg);

Демо-функція є нашою точкою входу. Оголошуємо структуру datap у стеку. Це порожня і неініціалізована структура з інформацією про стан для отримання аргументів, підготовлених за допомогою &bof_pack. BeaconDataParse ініціалізує наш аналізатор. BeaconDataExtract витягує двійковий блок з певною довжиною з наших аргументів. Наша функція упаковки має можливість упакувати бінарні блоки як рядки з термінальним нулем, закодованим у наборі символів сеансу за замовчуванням, рядок із широким символом і нульовим терміналом або двійковий блок без перетворення. BeaconDataInt отримує ціле число, упаковане в наші аргументи. BeaconPrintf – це один із способів форматування виводу та надання його оператору.

BOF C API  аналізатора даних

API аналізатора даних отримує аргументи, упаковані за допомогою  функції &bof_pack сценарію агресора.

  • char * BeaconDataExtract (datap * аналізатор, int * розмір) Отримує бінарний блок з певною довжиною. розмір може бути NULL.

Якщо адреса вказана, розмір буде заповнений кількістю вилучених байтів.

  • int BeaconDataInt (datap * аналізатор) Отримує чотирибайтове ціле число.

  • int BeaconDataLength (datap * аналізатор) Отримує обсяг даних, який ще належить проаналізувати.

  • void BeaconDataParse (datap * аналізатор, char * buffer, int size) Готує аналізатор даних для отримання аргументів із вказаного буфера.

  • короткий BeaconDataShort (datap * парсер) Отримує двобайтове ціле число.

API виведення

API виводу повертає Cobalt Strike.

  •  void BeaconPrintf (int type, char * fmt, …) Форматує і виводить оператора Beacon.

  •  void BeaconOutput (int type, char * data, int len) Надсилає вихідні дані оператору маяка.

Кожна з цих функцій приймає аргумент типу. Цей тип визначає, як Cobalt Strike обробить вихід і в якому вигляді буде його відображати. До видів відносяться:

  • CALLBACK_OUTPUT – це стандартний вихід. Cobalt Strike перетворює цей вихід у UTF-16 (всередині), використовуючи стандартний набір символів.

  • CALLBACK_OUTPUT_OEM – це стандартний вихід. Cobalt Strike перетворює цей вихід у UTF-16 (внутрішньо) з використанням набору символів OEM. Ймовірно, вам це не знадобиться, якщо ви не маєте справу з виводом з cmd.exe.

  • CALLBACK_ERROR є стандартним повідомленням про помилку.

  • CALLBACK_OUTPUT_UTF8 – це стандартний вихід. Cobalt Strike перетворює цей вихід у UTF-16 (всередині) від UTF-8.

API форматування

API форматування використовується для створення великих або повторюваних виводів.

  • void BeaconFormatAlloc (formatp * obj, int maxsz) Виділяє пам’ять для форматування складного або великого виводу.

  •  void BeaconFormatAppend (formatp * obj, char * data, int len) Додає дані до цього об’єкта форматування.

  • void BeaconFormatFree (formatp * obj) Звільняє об’єкт форматування.

  • void BeaconFormatInt (formatp * obj, int val) Додає до цього об’єкта ціле чотирибайтове ціле число (великий кінець).

  • void BeaconFormatPrintf (formatp * obj, char * fmt, …) Додає форматований рядок до цього об’єкта.

  • void BeaconFormatReset (formatp * obj) Повертає об’єкт форматування до стану за промовчанням (перед повторним використанням).

  • char * BeaconFormatToString (formatp * obj, int * size) Отримує відформатовані дані в одному рядку. Заповніть пропущену змінну розміру довжиною цього рядка. Ці параметри підходять для використання з функцією BeaconOutput.

Внутрішні API

Наступні функції керують токеном, який використовується в поточному контексті маяка:

  • BOOL BeaconUseToken (маркер HANDLE) Використовує вказаний маркер як маркер поточного потоку Beacon. Новий токен також буде повідомлений користувачеві. Повертає логічне значення TRUE після успіху. FALSE у разі невдачі.

  • порожнеча BeaconRevertToken () Скидає маркер поточного потоку. Використовуйте цю функцію замість безпосереднього виклику RevertToSelf. Ця функція очищає іншу інформацію про стан токена.

  • BOOL BeaconIsAdmIn () Повертає логічне значення TRUE, якщо маяк має контекст високої цілісності.

Наступні функції надають конкретний доступ до здатності маяка включатися в процес:

 void BeaconGetSpawnTo (BOOL x86, char * buffer, int length) Заповнює вказаний буфер x86 або x64 значенням spawnto, налаштованим для цього сеансу Beacon.

  • BOOL BeaconSpawnTemporaryProcess  (BOOL x86, BOOL ignoreToken, STARTUPINFO * sInfo, PROCESS_INFORMATION * pInfo)   Ця функція породжує перехідний процес на основі параметрів ppid, spawnto та blockdlls. Візьміть за руку PROCESS_INFORMATION, щоб проникнути в цей процес або маніпулювати ним. Повертає значення TRUE після успіху.

  • void BeaconInjectProcess (HANDLE hProc, int pid, char * payload, int payload_len, int payload_ offset, char * arg, int arg_len) Ця функція вводить зазначене корисне навантаження в існуючий процес. Використовуйте payload_offset, щоб вказати зміщення всередині корисного навантаження для початкового виконання. Значення arg призначене для аргументів. arg може бути NULL.

  •  void BeaconInjectTemporaryProcess (PROCESS_INFORMATION * pInfo, char * payload, int payload_len, int payload_offset, char * arg, int arg_len) Ця функція вводить вказане корисне навантаження в тимчасовий процес, який ваш конвертер вибрав для запуску. Використовуйте payload_offset, щоб вказати зміщення всередині корисного навантаження для початкового виконання. Значення arg призначене для аргументів. arg може бути NULL.

  •  void BeaconCleanupProcess (PROCESS_INFORMATION * pInfo) Ця функція очищає деякі дескриптори, про які часто забувають. Викличте його, коли закінчите взаємодію з дескрипторами процесів. Вам не потрібно чекати, поки процес вийде або завершиться.

Ця функція корисна:

  • BOOL toWideChar (char * src, wchar_t * dst, int max) Перетворіть рядок src у рядок із широкими символами у форматі UTF16-LE, Використання кодування за замовчуванням. max – розмір (в байтах!) буфера призначення.

Дякуємо різним посібникам, які знаходяться у різних відкритих джерелах.

Інші статті по темі
Знайшли помилку?
Якщо ви знайшли помилку, зробіть скріншот і надішліть його боту.