Вступление
Высокая гибкость, сложность и машинный код более 10 000 байт. Именно с этим столкнулись исследователи Unit 42 во время анализа кода этого файла. Поведение кода и функции сильно коррелируют с семейством вредоносных программ WaterBear, которое было активным еще с 2009 года. Анализ, проведенный Trend Micro и TeamT5, показал, что WaterBear представляет собой многогранный имплант второго этапа, способный передавать файлы, доступ к оболочке и т. Д. снимок экрана и многое другое. Вредоносное ПО связано с кибершпионажной группой BlackTech, которая, по оценке многих представителей более широкого сообщества исследователей угроз, связана с правительством Китая, и, как полагают, несет ответственность за недавние атаки на несколько правительственных организаций Восточной Азии. Из-за сходства с WaterBear и полиморфной природы кода Unit 42 назвал этот новый китайский шелл-код «BendyBear». Он стоит в собственном классе с точки зрения того, что является одним из самых сложных, хорошо спроектированных и трудно обнаруживаемых образцов шелл-кода, используемых APT.
Образец BendyBear был определен как шелл-код x64 для имплантата нулевой стадии, единственной функцией которого является загрузка более надежного имплантата с сервера управления и контроля (C2). Шелл-код, несмотря на свое название, используется для описания небольшого фрагмента кода, загружаемого в цель сразу после эксплуатации, независимо от того, порождает ли он на самом деле командную оболочку или нет. При размере более 10 000 байт BendyBear заметно больше, чем большинство других, и использует его для реализации расширенных функций и методов антианализа, таких как модифицированное шифрование RC4, проверка блока подписи и полиморфный код.
Образец, проанализированный в этом блоге, был идентифицирован по его связям с вредоносным доменом C2, опубликованным Бюро расследований Министерства юстиции Тайваня в августе 2020 года. Было обнаружено отсутствие дополнительной информации о векторе эксплойта, потенциальных жертвах или предполагаемом использовании.
Новый класс шелл-кода
На макроуровне BendyBear уникален следующим:
- Передает полезные данные в модифицированных фрагментах, зашифрованных RC4. Это усиливает шифрование сетевой связи, поскольку один ключ RC4 не расшифрует всю полезную нагрузку.
- Попытки оставаться скрытыми от анализа кибербезопасности путем явной проверки своей среды на наличие признаков отладки.
- Использует существующий раздел реестра Windows, который включен по умолчанию в Windows 10 для хранения данных конфигурации.
- Очищает кеш DNS хоста каждый раз, когда он пытается подключиться к своему серверу C2, тем самым требуя, чтобы хост каждый раз разрешал текущий IP-адрес для вредоносного домена C2.
- Создает уникальные сеансовые ключи для каждого подключения к серверу C2.
- Скрывает свой протокол подключения, подключаясь к серверу C2 через общий порт (443), тем самым смешиваясь с обычным сетевым трафиком SSL.
- Использует полиморфный код, изменяя его след во время выполнения кода, чтобы помешать анализу памяти и избежать подписания.
- Шифрует или дешифрует функциональные блоки (блоки кода) во время выполнения по мере необходимости, чтобы избежать обнаружения.
- Использует позиционно-независимый код (PIC), чтобы избавиться от инструментов статического анализа.
Технические детали
Выполнение шеллкода
Шелл-код (SHA256: 64CC899EC85F612270FCFB120A4C80D52D78E68B05CAF1014D2FE06522F1E2D0) считается стейджером или загрузчиком, функция которого заключается в загрузке имплантата с сервера C2. Во время выполнения код использует рандомизацию байтов, чтобы скрыть свое поведение. Это достигается за счет использования текущего времени хоста в качестве начального числа для генератора псевдослучайных чисел, а затем выполнения дополнительных операций с этим выводом. Полученные значения используются для перезаписи блоков ранее выполненного кода. Эта манипуляция с байтами - первый метод антианализа, наблюдаемый в коде, поскольку любая попытка сбросить сегмент памяти приведет к незаконным или неправильным операциям. На рисунке 1 показан пример основной точки входа в шелл-код до и во время выполнения.
WaterBear на основе атрибутов, определенных в этом примере. Более подробную информацию об этих загрузчиках можно найти в разделе приложения «Загрузчики x86 WaterBear».
Шелл-код начинается с поиска целевого блока среды процесса (PEB), чтобы проверить, отлаживается ли он в данный момент. Однако код написан таким образом, что он извлекает значения «BeingDebugged» и «BitField» из PEB, что приводит к логике кода, которая делает недействительной проверку отладчика. Из-за этого шелл-код всегда не распознает присоединенный отладчик. Эта процедура выполняется 52 раза в цикле while.
Затем шелл-код просматривает список модулей загрузчика PEB в поисках базового адреса Kernel32.dll. Это типично для шелл-кода, поскольку базовый адрес Kernel32.dll необходим для разрешения любых файлов зависимостей, требуемых шелл-кодом для запуска. С этим адресом шелл-код загружает свои модули зависимостей и разрешает все необходимые вызовы Windows Application Programming Interface (API), используя стандартное хеширование API шелл-кода. Загружены следующие модули:
- Advapi32.dll
- Kernel32.dll
- Msvcrt.dll
- User32.dll
- Ws2_32.dll
HKEY_CURRENT_USER\Console\QuickEditЭтот раздел реестра используется командной строкой Windows для включения режима быстрого редактирования. Режим быстрого редактирования позволяет копировать и вставлять из командной строки в буфер обмена. По умолчанию этот ключ содержит REG_DWORD, 32-битное число: 1 для включения или 0 для выключения. BendyBear считывает это значение, умножает его на 1000 и выполняет следующие вычисления над результатом:
Если результат меньше 1 000 или больше 3 300 000, конфигурация шелл-кода (QuickEdit) равна 4 000 (0xFA0), в противном случае это результат вычисленного значения.
См. Выделенное голубым цветом значение на рисунке 2 Конфигурация шелл-кода.
Эта проверка выполняется каждый раз при выполнении шелл-кода. Одно из объяснений использования этого ключа состоит в том, что значение записывается загрузчиком шелл-кода (в значение, отличное от 0 или 1), и оно используется шелл-кодом для получения параметров конфигурации.
Затем он расшифровывает свою внутреннюю структуру конфигурации, которая составляет 1152 байта. Пример показан на рисунке 2.
Разбивка структуры конфигурации, показанной на Рисунке 2, приведена ниже (сверху вниз):
- Неоново-зеленым цветом выделены два 16-байтовых ключа, используемых для XORing значений во всем шеллкоде.
- 7D 38 BA FD E1 C8 D2 DF B6 EE 33 F9 14 BF 52 96
- 71 17 DF E4 AE 3B A9 F2 D5 3D 75 CC D3 0D 57 72
- олубым цветом выделены два байта, вычисленные на основе ключа быстрого редактирования реестра хоста.
- E8 03
- Оранжевым цветом выделены четыре байта, представляющие версию шеллкода.
- 30 2Э 32 34 (0,24)
- Розовым цветом выделены 17 байтов, составляющих домен C2. Побитовое НЕ (байт без знака) для декодирования значений, включая NULL.
- 88 98 CE D1 96 91 94 9A 8C 93 96 89 9A D1 9C 90 92
- Темно-зеленым выделены 103 байта, которые используются для исключения шаблона. XOR со значениями от 0xFF до NULL.
- FF FF FF FF FF FF FF FF FF FF FF…
- Пурпурным цветом выделены два байта, составляющие целевой порт C2.
- BB 01
- Светло-желтым цветом выделены разрешенные указатели на функции, используемые шеллкодом.
- 92 13 73 33 37 02
- Темно-голубым цветом выделены 112 байтов, которые составляют размеры указателя функции, используемые для шифрования или дешифрования функциональных блоков.
- EE 01
- Темно-красным выделены 289 байтов, которые составляют разрешенные функции Windows API, используемые шеллкодом.
- A0 2E 52 CC FC 7F 00 00…
Перед взаимодействием с сервером C2 шеллкод очищает кеш DNS хоста, выполнив следующие действия:
- Загружает модуль dnsapi.dll
- Вызывает API DnsFlushResolverCache
При вызове этого API все разрешенные домены удаляются из кеша DNS хоста, а не только целевой сервер C2. Это вынуждает хост разрешить текущий IP-адрес, связанный с доменом C2, гарантируя, что связь продолжается, когда сетевая инфраструктура становится скомпрометированной или недоступной. Это также подразумевает, что разработчики владеют доменом и могут обновлять IP.
Стаджер начинает с вычисления 10 байтов данных для отправки на сервер C2. Эти 10 байтов составляют пакет запроса вызова. Стаджер отправляет запрос на вызов на C2 и ожидает ответа на запрос. При получении и правильной расшифровке stager проверяет магические значения или байты подписи при определенных смещениях. Если эта проверка не удалась, сетевое соединение прерывается. Эта проверка обеспечивает надежную связь с предполагаемым сервером C2 и инициирует загрузку полезной нагрузки.
I. Stager генерирует пакет запроса на вызов
Стаджер вычисляет 10-байтовый запрос вызова, содержащий информацию для C2, чтобы включить размер данных (являющихся сеансовыми ключами), которые будут получены следующими. Запрос вызова и сеансовые ключи отправляются на C2 одновременно. Пример запроса:
26BCFCCE738A211F3763II. Сервер C2 расшифровывает пакет запроса на вызов
C2 расшифровывает пакет запроса вызова, используя следующие шаги:
1. Первый байт будет обработан методом XOR со вторым байтом, второй байт - с третьим байтом… до байта 10, за которым следует:
A. Байт 7 обновляется по результату (байт 7 подвергается операции XOR с байтом 3).
Б. Байт 2 обновляется по результату (байт 2 подвергается операции XOR с байтом 0).
C. Байт 8 обновляется по результату (байт 8 подвергается операции XOR с байтом 0).
D. Байт 9 обновляется по результату (байт 9 подвергается операции XOR с байтом 5).
2. Окончательное значение подвергается операции XOR с ключом
0x3FDA5F9AD85D50C77E6A. Запрос на вызов расшифровывается до следующего (представленного в виде шестнадцатеричных байтов):
Последние четыре байта расшифрованного пакета запроса информируют сервер C2 о размере ожидаемого сетевого трафика. Как показано выше, значение равно 0x20 или 32 байта.
Эти 32 байта составляют ключи сеанса, используемые сервером C2 для шифрования ответа сервера на запрос и шифрования полезной нагрузки.
Пример сессионных ключей, полученных сервером C2:
Сеансовый ключ 1–> 8C931D4F764B0661C26D77239EB454CA
Сеансовый ключ 2–> 7A4DD0AA6C3F37CDBDAFA4CBD6B27697
Пакет запроса вызова и сеансовые ключи вычисляются для каждого маяка и, следовательно, всегда будут уникальными.
III. C2 аутентифицируется с помощью Stager
C2 использует ключи сеанса для создания поля состояния RC4 и в качестве ключа XOR для шифрования и дешифрования.
* Следует отметить, что использование сеансового ключа 2 еще не полностью изучено, и, похоже, он не использовался для связи со стейджером.
1. Предсессионный ключ вычисляется с использованием сеансового ключа 1 (первые 16 байтов) следующим образом:
Предсессионный ключ = сеансовый ключ 1 XOR
0X6162636465666768696A6B6C6D6E6F00
2. Используя вычисленный предсессионный ключ из шага 1, сервер C2 строит алгоритм планирования ключей RC4 (KSA). Он рассчитывается следующим образом:
а. Создайте RC4 KSA, используя следующие входные данные для функции ниже:
data = 16-байтовый ключ 0x0C2F65194FF37B2D63D34635C7B205E4
key = 16-байтовый вычисленный предсессионный ключ из шага 1
Пример RC4 (модифицированной) подпрограммы KSA:
Код:
def rc4_KSA (данные, ключ):
x = 0
box = range(258)
box[256] = 0
box[257] = 0
for i in range(256):
x = (x + box[i] + ord(key[i % len(key)])) % 256
box[i], box[x] = box[x], box[i]
return box
* Примечание относительно входного параметра «данные» для процедуры KSA: это результат XOR двух 16-байтовых ключей, показанных неоново-зеленым цветом на рисунке 2. Структура конфигурации шелл-кода.
3. Создайте 10-байтовый заголовок ответа сервера на запрос, используя шестнадцатеричные значения, показанные на рисунке 5.
4. Зашифруйте заголовок ответа на запрос сервера из шага 3:
a. Вызов 10-байтового сервера XOR с ключом 0x33836E6B3FAA6AC464DA и выполнение следующего:
i. Байт 7 обновляется по результату (байт 7 подвергается операции XOR с байтом 3).
ii. Байт 2 обновляется по результату (байт 2 XOR соединен с байтом 0).
iii. Байт 8 обновляется по результату (байт 8 подвергается операции XOR с байтом 0).
iv. Байт 9 обновляется по результату (байт 9 подвергается операции XOR с байтом 5).
b. Заголовок ответа на зашифрованный запрос сервера = результат 4 (а)
5. Вычислить окончательный ключ аутентификации:
a. Выполните XOR для следующих значений:
i. 0x0C2F65194FF37B2D63D34635C7B205E4
ii. Значение, рассчитанное на шаге 1, т.е. ключ перед сеансом.
* 16-байтовое значение в 5.a.i - это тот же входной параметр, который используется в алгоритме KSA на шаге 2. Стаджер ожидает этот ключ от C2, в противном случае сеанс прерывается.
Значения, сгенерированные на шагах 4 и 5, составляют полный ответ на запрос сервера. На этом этапе C2 отправляет ответ на запрос сервера в stager, завершая процесс аутентификации.
IV. C2 шифрует и передает полезную нагрузку
Затем C2 готовится отправить команду на stager. BendyBear поддерживает только один тип команды: загрузка полезной нагрузки.
1. Создайте 10-байтовый заголовок команды, используя шестнадцатеричные значения, показанные на рисунке 6.
Единственное изменение в заголовке - это фиксированное значение подписи с 0x40 до 0x43.
2. Зашифруйте заголовок команды из шага 1:
Ниже приведен пример модифицированной подпрограммы RC4, которую можно использовать. Первый аргумент, box, будет S-Box, вычисленным на шаге III.2, а второй аргумент, data, будет заголовком команды из шага 1.
Код:
def rc4_Mod_Crypt(box, data):
x = box[256]
y = box[257]
c = 0
out = []
for char in data:
x = (x + 1) % 256
y = (y + box[x]) % 256
box[x], box[y] = box[y], box[x]
z = ( (box[x] + box[y] )&0xff ) % 256
al = rol( box[z],4,8 )
out.append( chr( ord( data[c] ) ^ al ) )
box[z] = al
c+=1
box[256] = x
box[257] = y
return ”.join(out)
3. Получите размер полезной нагрузки и зашифруйте это значение, используя тот же алгоритм RC4, что и на шаге 2. Размер полезной нагрузки должен быть общим расшифрованным размером полезной нагрузки.
4. Зашифруйте и отправьте полезную нагрузку на стейджер по частям:
a. Прочтите 4086 байт из полезной нагрузки. Это максимальный размер блока, который может принять stager.
b. Создайте заголовок команды (шаг 1 выше) и обновите следующие поля:
i. Размер заголовка = размер блока полезной нагрузки.
ii. Команда = 1.
c. Отправьте обновленный 10-байтовый заголовок команды в stager.
d. Отправьте зашифрованный фрагмент полезной нагрузки.
е. Повторяйте шаги a - d, пока полезные данные не будут отправлены.
На рисунке 7 показан пример одного блока полезной нагрузки, который отправляется в stager.
После получения каждого фрагмента stager удаляет заголовок команды и расшифровывает фрагмент полезной нагрузки в памяти.
Загрузка полезной нагрузки в память
После того, как полезная нагрузка полностью расшифрована, stager выполняет некоторые базовые проверки, чтобы убедиться, что полезная нагрузка соответствует исполняемому файлу Windows. Он проверяет заголовок DOS и PE, а также то, что полезная нагрузка является DLL. Затем он загружает полезную нагрузку в прямую память и вызывает ее точку входа (AddressOfEntryPoint). Прямая загрузка памяти полезными данными имитирует загрузку Windows PE - LoadLibrary. В результате структуры метаданных PEB LDR_DATA_TABLE_ENTRY не создаются, а PEB для процесса, выполняющего шеллкод, не имеет записи о загрузке DLL, которая может использоваться для обнаружения несанкционированных модулей, работающих на вашем хосте. Это видно в WinDbg, запустившем команду! Адрес в процессе, загрузившем шеллкод. Пример показан на рисунке 8.
Артефакты в памяти:
- Тип - MEM_PRIVATE, что означает, что он является частным для процесса, который его загрузил. На платформах Windows библиотеки DLL обычно загружаются как MEM_IMAGE, чтобы их можно было использовать совместно с разными процессами для экономии места в памяти.
- Защита - PAGE_EXECUTE_READWRITE (RWX), что означает, что область доступна для записи и выполнения с областью памяти, содержащей заголовок MZ. Заголовок MZ - это загруженный в память модуль.
!address WinDbg, Показанный на рисунке 8, обнаруживает аномальную запись. Адрес памяти модуля 0x7ff4c2450000 был результатом выделения частной памяти, установки защиты на RWX и использования, содержащего заголовок MZ.x64 Shellcode Behaviors
В следующей таблице описаны основные функции BendyBear.
BendyBear vs. WaterBear
Заключение
Шелл-код BendyBear содержит расширенные функции, которые обычно не встречаются в шелл-коде. Использование методов антианализа и проверки блока подписи указывает на то, что разработчики заботятся о скрытности и уклонении от обнаружения. Кроме того, использование настраиваемых криптографических процедур и манипуляции с байтами предполагает высокий уровень технической сложности.
Дополнительные ресурсы
Taiwan News – Taiwan urges blocking 11 China-linked phishing domains.
iThome News – The Bureau of Investigation’s recent investigation of several cases of Taiwan Government agencies hacked.
TeamT5 – Evil Hidden in Shellcode: The Evolution of malware DbgPrint.
TrendMicro – WaterBear Returns, Uses API Hooking to Evade Security.
TrendMicro – The Trail of BlackTech’s Cyber Espionage Campaigns.
CryCraft Technology Corp – Taiwan Government Targeted by Multiple Cyberattacks in April 2020 Part 1: Waterbear Malware
JPCERT/CC Eyes – ELF_PLEAD – Linux Malware Used by BlackTech
Приложение
Shellcode PoC
Имитация сервера C2, обслуживающего запрос к stager и отправляющего полезную нагрузку (DLL), которая отображает окно сообщения:
Код:
python.exe U42ETHOS_C2.py -l 8080 -p c:\temp\DLLSample.dll
[+] Started U42ETHOS_C2.py ver 1.0.0 waiting for connection on TCP port 8080
[!] Using payload file c:\temp\DLLSample.dll
[!] Received new connection from: (‘192.168.163.138’, 49918)
[-] Received Encrypted challenge Request Packet–> 40da9a64bf3992d39db6
[-] Decrypted challenge Request packet–> 46401f8c032320000000
[+] Session key 1–> 9816f78b57fff54efb5419202d81a729
[+] Session key 2–> 6ec83a6e4d8bc4e28496cac865878574
[+] Computed PreSessionKey–> f97494ef32999226923e724c40efc829
[+] Challenge command–> a3601149a495d02598b7
[-] Challenge key is–> f55bf1f67d6ae90bf1ed3479875dcdcd
[+] Payload Size is 00920100
[!] Payload sent to stager. Check if executed
На рисунке 9 показан макет C2-сервера Python, созданный модулем 42 для взаимодействия со стейджером. Он настроен на прослушивание TCP-порта 8080, а полезная нагрузка - это тестовая DLL, которая запускает calc.exe и отображает окно сообщения (Hello, Implant). На рисунке 10 показан хост Windows 10, на котором шеллкод запускается в памяти через специальный загрузчик. Шелл-код был настроен для связи с фиктивным сервером C2.
Network Traffic for the Above Payload (truncated):
От ТС
Это перевод материала, взятого отсюда
Если есть предложения, что перевести, вам сюда
Все хэши есть в оригинальной статье
Перевод:
Azrv3l cпециально для xss.pro