
Минимальный процессор в памяти для агностического создания протоколов на лету
Harald — это крошечный высокоуровневый CPU, работающий в памяти и способный обрабатывать набор инструкций для генерации протоколов прикладного уровня, используемых поверх заданного сетевого протокола (TCP/UDP).
Harald потребляет поток OPCODE и применяет различные преобразования к полезной нагрузке, чтобы она соответствовала определённому протоколу прикладного уровня.
[!TIP] Почему Harald? Возможно, вы знаете Харальда Гормссона, короля Дании, по его прозвищу: Blátǫnn, или, как мы произносим его сегодня, Bluetooth. Технология была названа в честь прозвища Харальда, поскольку он соединил датское и викингское королевства в те времена. Поэтому я назвал это в честь его имени.
Harald ведёт себя как CPU. Он следует набору OPCODE, которые определяют действия. PROTOCOL. Harald выполнит необходимые операции, чтобы создать требуемый протокол на лету.
После того как PROTOCOL задан, Harald будет итерироваться по PAYLOAD, который нужно отправить, проходя весь PROTOCOL один раз для каждого фрагмента. То есть: если полезную нагрузку пришлось разбить на несколько фрагментов, Harald будет использовать один и тот же протокол для каждого фрагмента, выполняя каждое действие, определённое в протоколе, над текущим фрагментом полезной нагрузки.
Harald хранит ряд регистров, которые протокол может использовать для хранения значений. Эти регистры можно использовать для выполнения множества операций, таких как сложение, вычитание, кодирование и декодирование... и т. д.
Harald динамически выделяет массив результатов, в котором протокол может хранить ответы на каждый запрос, выполненный при отправке фрагмента полезной нагрузки.

Harald поддерживает множество опкодов, которые можно задать как протокол. Harald выполняет набор высокоуровневых операций при получении заданного опкода. Каждый опкод ожидает предопределённый набор аргументов с предопределённой длиной.
| OPCODE::Nº | Description | ARGS::Size |
|---|---|---|
| H_F_APPEND::0x01 | Appends the following N Bytes to the end payload | Size::4, NBytes::N |
| H_F_PREPEND::0x02 | Prepends the following N Bytes to the end payload | Size::4, NBytes::N |
| H_F_SPLIT::0x03 | Splits the Payload in fragments of the given size | Size::4 |
| H_F_PAYLOAD_INJECT::0x04 | Injects the Payload fragment into the End Payload | - |
| H_F_SOCK_INIT::0x05 | Initializes the socket connection | IsIPAddress:1, SSL_Enabled::1, TCP/UDP::1, [(HostLen::4,HostName:N)/IPAddress::4], Port::2 |
| H_F_SEND::0x06 | Sends the constructed End Payload | - |
| H_F_RECV::0x07 | Receives up to N Bytes | Size::4 |
| H_F_CLOSE::0x08 | Closes the socket and cleans | - |
| H_F_INJECT::0x09 | Injects the requested registry into the End Payload | Reg::1 |
| H_F_ENCODE_STR::0x0A | Encodes a Payload field to its string representation | IsReg::1, [(Payload::1, Field::1)/Reg::1], Format::1 |
| H_F_DECODE_STR::0xA0 | Decodes the contents of a registry to its numeric representation | Reg::1 |
| H_F_ENCODE_STRB64::0x0B | Encodes a Payload field to its B64string representation | Payload::1, Field::1 |
| H_F_COMPUTE_FRAG_LENGTH::0x0D | Calculates the next fragment to be sent length | - |
| H_F_SEARCH::0x0E | Searches for a given byte pattern of a given N size in a given registry | Reg::1, Size::4, NBytes::N |
| H_F_SEEK::0x0F | Moves the cursor in a given payload by a given number of bytes | Payload::1, Offset::4 |
| H_F_PUSH::0x10 | Pushes a number of bytes or the contents of a registry into another registry | IsReg::1, [Size::4, NBytes::N]/SrcReg::1, DstReg::2 |
| H_F_ADD::0x12 | Adds two registries or a number to a registry | IsReg::1, [Size::4, NBytes::N]/SrcReg::1, DstReg::2 |
Следующий поток опкодов сгенерирует необходимые данные для отправки, чтобы связь была распознана как HTTP. Он инициирует соединение, изменит полезную нагрузку так, чтобы она выглядела как HTTP-трафик, отправит её через SSL/TLS-соединение и закроет соединение в конце.
H_F_SPLIT, 0x00, 0x00, 0x00, 0xFF, // Splits the Payload
H_F_APPEND, 0x00, 0x00, 0x00, 0x46, // Appends...
'P', 'O', 'S', 'T', ' ', '/', ' ', // POST /
'H', 'T', 'T', 'P', '/', '1', '.', '1', '\r', '\n', // HTTP/1.1
'H', 'o', 's', 't', ':', ' ', // Host:
'd', 'o', 'm', 'a', 'i', 'n', '.', 'c', 'o', 'm', '\r', '\n', // domain.com
'C', 'o', 'n', 'n', 'e', 'c', 't', 'i', 'o', 'n', ':', ' ', // Connection:
'c', 'l', 'o', 's', 'e', '\r', '\n', // close
'C', 'o', 'n', 't', 'e', 'n', 't', '-', // Content-
'L', 'e', 'n', 'g', 't', 'h', ':', ' ', // Length:
H_F_COMPUTE_FRAG_LENGTH, // Next Fragment's size
H_F_ENCODE_STR, H_PAY_END_PAYLOAD, H_PAY_FRAGMENT_SIZE, 'u', // FragSize encode
H_F_INJECT, H_REG_RET, // Inject the Fragment Size encoded str
H_F_APPEND, 0x00, 0x00, 0x00, 0x04, '\r', '\n', '\r', '\n', // Append Body begin
H_F_PAYLOAD_INJECT, // Inject the Payload
H_F_SOCK_INIT, 0x01, 0x01, 0x7F, 0x00, 0x00, 0x01, 0x04, 0xD2, // Init Socket
H_F_SEND, // Send the Payload over the socket
H_F_CLOSE // Close the socket and cleanup
Следующий пример повторяет те же процедуры, что и предыдущий. Однако вместо простой отправки полезной нагрузки в качестве тела, протокол даст указание Harald настроить некоторые заголовки и структурировать тело так, чтобы он мог взаимодействовать с GitHub API для публикации комментариев в issue приватного репозитория.
Такая связь может помочь атакующему создать канал связи с C2-сервером, используя доверенный домен, например *.github.com. Этот же пример можно экстраполировать на использование ресурсов AWS (например, очередей SQS под sqs..amazonaws.com), ресурсов Azure (например, blob-хранилищ под <storage_account_name>.blob.core.windows.net) и так далее.
Этот пример является хорошим справочником для тех видов связи, которые требуют STRUCTURED_FORMAT (JSON) + APPLICATION-LAYER_PROTOL (HTTPS) + PROTOCOL (TCP).
H_F_SPLIT, 0x00, 0x00, 0x00, 0xFF,
H_F_APPEND, 0x00, 0x00, 0x01, 0x85, 'P','O','S','T',' ',
'/','r','e','p','o','s','/','YOUR_GH_USER','/','YOUR_GH_REPO',
'/','i','s','s','u','e','s','/','ISSUE_NUMBER',
'/','c','o','m','m','e','n','t','s',' ',
'H','T','T','P','/','1','.','1','\r','\n', 'H','o','s','t',':','
','a','p','i','.','g','i','t','h','u','b','.','c','o','m','\r','\n',
'A','u','t','h','o','r','i','z','a','t','i','o','n',':',' '
,'B','e','a','r','e','r',' ','g','i','t','h','u','b','_','p','a','t','_',
'YOUR_GH_PAT','\r','\n',
'X','-','G','i','t','H','u','b','-',
'A','p','i','-','V','e','r','s','i','o','n',':','
', '2','0','2','2','-','1','1','-','2','8','\r','\n',
'U','s','e','r','-','A','g','e','n','t',':','
','H','a','r','a','l','d','/','0','.','1','b','\r','\n',
'A','c','c','e','p','t',':','
','a','p','p','l','i','c','a','t','i','o','n','/',
'v','n','d','.','g','i','t','h','u','b','+','j','s','o','n','\r','\n',
'C','o','n','t','e','n','t','-','T','y','p','e',':',' ',
'a','p','p','l','i','c','a','t','i','o','n','/',
'x','-','w','w','w','-','f','o','r','m','-',
'u','r','l','e','n','c','o','d','e','d','\r','\n',
'C','o','n','n','e','c','t','i','o','n',':','
','c','l','o','s','e','\r','\n',
'C','o','n','t','e','n','t','-','L','e','n','g','t','h',':',' ',
H_F_COMPUTE_FRAG_LENGTH,
H_F_ADD, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0B, H_REG_RET,
H_F_ENCODE_STR, 0x01, H_REG_RET, 'u',
H_F_INJECT, H_REG_RET,
H_F_APPEND, 0x00, 0x00, 0x00, 0x0D, '\r', '\n', '\r', '\n', '{', '"', 'b',
'o', 'd', 'y', '"', ':', '"',
H_F_PAYLOAD_INJECT,
H_F_APPEND, 0x00, 0x00, 0x00, 0x02, '"', '}',
H_F_SOCK_INIT, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0F,
'a', 'p', 'i', '.',
'g', 'i', 't', 'h', 'u', 'b', '.', 'c', 'o', 'm', '\0', 0x01, 0xBB,
H_F_SEND,
H_F_CLOSE
Вам понадобится компилятор для сборки. Например, GCC, Clang или Microsoft CL. Также есть несколько зависимостей от библиотек:
Установите LibSSL и pkg-config:
sudo apt install libssl-dev pkg-config
Установите OpenSSL через brew или соберите и настройте его самостоятельно.
brew install openssl
Получите OpenSSL у любого из их связанных распространителей или соберите и настройте его самостоятельно.
Репозиторий содержит Makefile для сборки библиотеки и некоторых тестовых бинарников.
Чтобы собрать библиотеку Harald, выполните:
make lib
Это создаст разделяемую библиотеку libharald.so, libharald.dll или
libharald.dylib в зависимости от вашей платформы.
Чтобы собрать тестовые бинарники, выполните:
make test
Это создаст два бинарника: test_harald и test_harald_gh (с соответствующими
расширениями в зависимости от вашей платформы).
Чтобы протестировать функциональность Harald, запустите предоставленные серверы socket_server_test.py и https_server_test.py. Они создадут сокет-сервер и HTTPS-сервер соответственно, которые будут использоваться тестовыми бинарниками.
Примечание: Возможно, вам потребуется установить
LD_LIBRARY_PATHна текущую папку:LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. ./test_harald
Вам потребуется создать SSL/TLS-сертификат для HTTPS-связи (самоподписанный подойдёт). Вы можете создать его с помощью OpenSSL следующей командой:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365
После того как серверы запущены, выполните бинарник test_harald:
./test_harald
Бинарник должен подключиться к предоставленным серверам и отправить предопределённые полезные нагрузки данных, как указано в протоколе.
Чтобы протестировать функциональность GitHub API, перед запуском бинарника
test_harald_gh необходимо выполнить некоторые подготовительные действия.
Создайте репозиторий и issue.
Файл test_harald_gh.c содержит простой пример того, как
использовать Harald для взаимодействия с GitHub API для создания комментариев в issue. Он
требует наличия токена доступа GitHub, который можно получить в настройках вашей
учётной записи GitHub в разделе Developer settings -> Personal access tokens ->
Fine-grained tokens. Рекомендуется ограничить токен так, чтобы он давал доступ
только к недавно созданному репозиторию и разрешения Read access to metadata и
Read and Write access to issues and pull requests.
Для корректной работы вам потребуется изменить значения-заполнители для:
YOUR_GH_USER: Ваше имя пользователя GitHub.ISSUE_NUMBER: Номер issue в репозитории, с которым вы хотите взаимодействовать
(например, "1" для первого issue в репозитории).YOUR_GH_REPO: Имя репозитория, с которым вы хотите взаимодействовать
(например, "harald").YOUR_GH_PAT: Ваш токен доступа GitHub.После этого обязательно обновите размер отправляемой полезной нагрузки в соответствии с вашими нуждами!
В test_harald_gh.c#L9 4-й параметр
опкода H_F_APPEND обозначает размер полезной нагрузки. Вам нужно будет обновить
это значение соответствующим образом при изменении структуры полезной нагрузки.
Соберите тестовые бинарники и запустите этот:
./test_harald_gh
Это создаст комментарий в указанном issue.
Исходный код, содержащийся в этом репозитории, может использоваться для обхода сетевой фильтрации и снижения риска обнаружения средствами безопасности. Перед использованием этого исходного кода убедитесь, что ваше использование соответствует всем применимым законам в вашей юрисдикции.
| H_F_SUBSTRACT::0x13 |
| Substracts two registries or a number to a registry |
| IsReg::1, [Size::4, NBytes::N]/SrcReg::1, DstReg::2 |
| H_F_READ::0x14 | Reads from a given registry up to the length stored in another registry | FromReg::1, SizeReg::1 |
| H_F_STORE::0x15 | Stores a registry value into Harald's Storage | Reg::1 |