В этой статье я покажу, как с помощью утилиты INetSim эмулировать взаимодействие малвари с управляющим сервером. Также рассмотрим работу загрузчика, распакуем основную нагрузку вредоноса и исследуем схему работы стилера.
Мы будем разбирать задание UnPackMe Blue Team Lab с площадки Cyber Defenders. Уровень задания — сложный. В лабораторной работе тебе потребуется ответить на ряд вопросов по итогам прохождения, однако приводить ответы мы не будем — если ты повторишь прохождение, то без труда ответишь на всё сам.
Исследуемый образец собран для 32-разрядных систем, разработан на языке C/C++ и скомпилирован в Microsoft Visual Studio. Получим энтропию исполняемого файла по секциям. Перейдем на вкладку Entropy и определим его показатель.
Энтропия исследуемого файла — 7,389, в секции .text — самое высокое значение. Значит, исследуемый файл упакован.
Перейдем в данную функцию двойным нажатием и декомпилируем, нажав F5.
В функции WrapGlobalAlloc реализовано получение адреса GlobalAlloc и выделение в куче памяти, равной длине шелл‑кода. Далее в функции WrapVirtualProtect выделенному участку памяти назначаются права на выполнение, чтение и запись (PAGE_EXECUTE_READWRITE) с помощью функции VirtualProtect. Следующим этапом начинается процесс расшифровки шелл‑кода.
Шифрование состоит из преобразования ключа и операции XOR.
Начальное значение ключа — 0xD5AF2F45. Для расшифровки шелл‑кода мы разработаем скрипт для IDA, на вход которого передадим адрес зашифрованного шелл‑кода, его размер, начальное значение ключа и имя файла для сохранения данных.
Расшифровывать будем в режиме отладки. Поставим точку останова на функции WrapDecryptShellcode (горячая клавиша F2) и запустим отладку (F9). Двойным нажатием на переменную shellcode получим адрес исполняемого кода, а его размер узнаем из переменной size_shellcode.
Загрузим разработанный скрипт, для этого зайдем на вкладку File → Script File. В командной строке Python вызовем функцию main.
Мы получили значение расшифрованного исполняемого кода. Загрузим его в IDA и проведем статический анализ. Полученный шелл‑код состоит из функций получения адресов используемых WinAPI и расшифровки основной нагрузки.
Преобразуем декомпилируемый код в читаемый вид. Для этого выберем переменную a1, кликнем правой кнопкой мыши и выберем пункт Create Struct. IDA сформирует структуру. Далее переименовываем каждое значение поля (горячая клавиша N).
Для получения функций WinAPI LoadLibraryA и GetProcAddress из библиотеки kernel32.dll используется хеширование. Из поля InMemoryOrderModuleList структуры PEB процесса считываются имена динамических библиотек. Из каждого имени вычисляется значение хеша и сравнивается со значением 0xd4e88. Такая же процедура производится с именами функций экспорта найденной динамической библиотеки.
Алгоритм хеширования представлен ниже.
Значение 0xd4e88 соответствует kernel32.dll.
Процесс получения основной нагрузки состоит из этапов расшифровки и разархивирования.
Алгоритм расшифровки тот же, а вот алгоритм декомпрессии сильно обфусцирован и содержит множество переходов (goto). Распакуем нашу нагрузку. Для этого в режиме отладки переходим к выполнению шелл‑кода и находим функцию DecryptUnpackShellcode. Далее спускаемся к выполнению функции Unpack, переходим на вкладку Hex View (клавиша G) и вводим адрес, который хранится в переменной data. Размер получаем из значения переменной unpack_size.
Дампим полученный после разархивирования шелл‑код с помощью IDA API. Для этого переходим в командную оболочку Python и вводим следующую команду:
Мы получили основную нагрузку, она представляет собой шелл‑код, задача которого — загрузить методом Process Hollowing исполняемый файл и начать выполнение с его точки входа. Загрузим полученный файл в Hex-редактор, скопируем данные, начиная с сигнатуры MZ, и приступим к его анализу.
На этом этапе мы с тобой распаковали основную нагрузку, которая представляет собой исполняемый файл. Работа загрузчика разделена на несколько этапов: сначала расшифровывается исполняемый код, основная задача которого — расшифровать и распаковать шелл‑код следующего этапа. Шелл‑код следующего этапа загружает в память исполняемый файл и продолжает выполнение с его точки входа.
Основная нагрузка разработана на C/C++, скомпилирована в Microsoft Visual Studio и собрана для 32-разрядных систем. Загрузим файл в IDA и приступим к статическому анализу. Код вредоноса сильно обфусцирован, и граф потока выполнения очень большой.
Все строки, используемые в процессе работы модуля, зашифрованы при помощи XOR с однобайтовым ключом. Давай набросаем скрипт для IDA, который будет расшифровывать строки.
На первом этапе модуль проверяет, запущен ли в системе экземпляр, с помощью функции OpenMutexA.
В командной строке Python запустим функцию расшифровки названия мьютекса:
Имя мьютекса формируется из константного значения uiabfqwfu, сложенного с именем пользователя. Если мьютекс с таким названием существует, модуль прекращает свою работу.
Далее модуль с помощью функции GetLocaleInfoA узнаёт, какие в системе установлены языки. Если присутствует язык из определенного списка (в него входит русский), то модуль прекращает работу.
Следом начинается процесс взаимодействия с управляющим сервером. Адрес C2-сервера зашифрован алгоритмом RC4 и закодирован в Base64.
Расшифруем ключ, который хранится в переменной RC4_KEY.
Ключ шифрования — $Z2s'ten\@bE9vzR для алгоритма RC4.
Расшифруем адрес управляющего сервера, для этого воспользуемся утилитой CyberChef.
Мы получили адрес управляющего сервера:
Основной адрес управляющего сервера зашифрован алгоритмом RC4. Ключ:
При обращении к основному адресу управляющего сервера исследуемый образец получает конфиг, зашифрованный алгоритмом RC4 с ключом $Z2s'ten\@bE9vzR.
Приступим к настройке INetSim. Открываем файл sample.html вот по такому пути:
И добавляем блок div с перечисленными выше атрибутами. Значение
В каталоге
Этот конфиг получен в результате статического анализа кода и нужен для работы образца. Параметр au содержит URL для загрузки библиотеки sqlite3.dll, параметры ip и location — информацию о сетевом адресе зараженной машины, параметр is_screen_enabled необходим для получения снимка рабочего стола, а параметр rm нужен на случай, если потребуется удалить себя после окончания сбора информации.
Также в каталог /var/lib/inetsim/http/fakefiles загрузим файл sqlite3.dll.
В файле
Каждый раз, когда малварь обращается к адресам с подстрокой /config/, загружается файл config.json (конфигурация модуля), а при открытии /config/files/ — библиотека sqlite3.dll.
Перезапустим утилиту INetSim.
Приступим к динамическому анализу исследуемого образца. При динамической отладке не забывай обходить проверку языкового стандарта, если в твоей виртуалке установлен русский язык.
Получив основной адрес управляющего сервера, вредоносный файл начинает устанавливать свое первое соединение.
Значения в POST-запросе сформированы следующим образом:
Параметр b описывает идентификатор зараженной машины, который формируется из имени пользователя системы и значения MachineGuid ключа реестра:
В параметре c указано константное значение. Сформированная строка шифруется по алгоритму RC4 с ключом $Z2s'ten\@bE9vzR. В ответ от сервера управления приходит конфигурация модуля.
Для работы функции сбора данных из браузеров вредоносу необходима динамическая библиотека sqlite3.dll. Параметр au в конфиге указывает на URL, по которому малварь может получить эту библиотеку.
В этот каталог загружаются дополнительные модули, а также собранные файлы из системы.
Функция сбора находится по смещению 454A (в моем случае функция sub_56454A), для перехода к коду необходимо на вкладке Function ввести значение смещения. На этапе сбора данных о системе исследуемый образец формирует файл System Info.txt в рабочей директории.
Содержимое файла System Info.txt:
После захвата экрана растровое изображение сохраняется в рабочую директорию с именем screen.jpeg.
После сбора всей информации с хоста в рабочей директории создается ZIP-архив. Имя файла берется из параметра _id в конфиге, полученном с C2.
Если значение параметра rm — «истина», то вредоносный файл начинает процесс самоудаления. Функция удаления расположена по смещению 5D47.
В переменной cmd формируется команда для удаления следов присутствия малвари в системе. Давай расшифруем значение.
Вот что получилось:
Также при первичном анализе исполняемого файла я нашел полный путь к каталогу сборки на компьютере злоумышленника:
Автор @rayhunt454
Источник xakep.ru
Мы будем разбирать задание UnPackMe Blue Team Lab с площадки Cyber Defenders. Уровень задания — сложный. В лабораторной работе тебе потребуется ответить на ряд вопросов по итогам прохождения, однако приводить ответы мы не будем — если ты повторишь прохождение, то без труда ответишь на всё сам.
Используемые утилиты
- DIE — программа для определения типов файлов.
- PeStudio — программа для поиска артефактов исполняемых файлов.
- IDA Pro — интерактивный дизассемблер, используемый для реверс‑инжиниринга.
- Wireshark — инструмент для анализа сетевого трафика.
- Burp Suite — платформа, которая используется в качестве прозрачного прокси‑сервера для анализа взаимодействия вредоносного файла по протоколу HTTPS.
- x64dbg — опенсорсный отладчик для Windows, предназначенный для анализа вредоносных программ.
- INetSim — эмулятор работы с интернетом.
Первичный анализ
Получим первичную информацию об исследуемом образце. Загрузим файл в DIE и выберем анализатор Nauz File Detector.
Исследуемый образец собран для 32-разрядных систем, разработан на языке C/C++ и скомпилирован в Microsoft Visual Studio. Получим энтропию исполняемого файла по секциям. Перейдем на вкладку Entropy и определим его показатель.
Энтропия исследуемого файла — 7,389, в секции .text — самое высокое значение. Значит, исследуемый файл упакован.
Исследуем загрузчик
Загрузим файл в IDA и приступим к анализу. Точка входа указывает на функцию WinMain, а основной поток выполнения реализован в функции sub_468480.
Перейдем в данную функцию двойным нажатием и декомпилируем, нажав F5.
В функции WrapGlobalAlloc реализовано получение адреса GlobalAlloc и выделение в куче памяти, равной длине шелл‑кода. Далее в функции WrapVirtualProtect выделенному участку памяти назначаются права на выполнение, чтение и запись (PAGE_EXECUTE_READWRITE) с помощью функции VirtualProtect. Следующим этапом начинается процесс расшифровки шелл‑кода.
Шифрование состоит из преобразования ключа и операции XOR.
Начальное значение ключа — 0xD5AF2F45. Для расшифровки шелл‑кода мы разработаем скрипт для IDA, на вход которого передадим адрес зашифрованного шелл‑кода, его размер, начальное значение ключа и имя файла для сохранения данных.
Код:
import struct
import idaapi
HIWORD = lambda x: x >> 16
def GenerateKey(key):
key = (key * 0x343fd) & 0xffffffff
key = (key + 0x269ec3) & 0xffffffff
return key
def DecryptShellcode(data,key):
result = bytearray()
for i in data:
key = GenerateKey(key)
k = HIWORD(key) & 0xFF
result.append(i ^ k)
return result
def main(start,size,key,filename):
w = open(filename,'wb')
b = bytearray()
for i in range(size):
x = idaapi.get_byte(start + i)
b.append(x)
d = DecryptStage(b,key)
w.write(d)
w.close()
Загрузим разработанный скрипт, для этого зайдем на вкладку File → Script File. В командной строке Python вызовем функцию main.
Код:
main(start=0x7B96E8,size=0x4e9d3,key=0xD5AF2F45,filename='stage01')
Преобразуем декомпилируемый код в читаемый вид. Для этого выберем переменную a1, кликнем правой кнопкой мыши и выберем пункт Create Struct. IDA сформирует структуру. Далее переименовываем каждое значение поля (горячая клавиша N).
Для получения функций WinAPI LoadLibraryA и GetProcAddress из библиотеки kernel32.dll используется хеширование. Из поля InMemoryOrderModuleList структуры PEB процесса считываются имена динамических библиотек. Из каждого имени вычисляется значение хеша и сравнивается со значением 0xd4e88. Такая же процедура производится с именами функций экспорта найденной динамической библиотеки.
Алгоритм хеширования представлен ниже.
Код:
def ApiHashing(name_func,hashing):
res = 0
for i in name_func:
v5 = (ord(i) | 0x60) & 0xff
res = (res + v5) * 2
if res == hashing:
return True
return False
Процесс получения основной нагрузки состоит из этапов расшифровки и разархивирования.
Алгоритм расшифровки тот же, а вот алгоритм декомпрессии сильно обфусцирован и содержит множество переходов (goto). Распакуем нашу нагрузку. Для этого в режиме отладки переходим к выполнению шелл‑кода и находим функцию DecryptUnpackShellcode. Далее спускаемся к выполнению функции Unpack, переходим на вкладку Hex View (клавиша G) и вводим адрес, который хранится в переменной data. Размер получаем из значения переменной unpack_size.
Дампим полученный после разархивирования шелл‑код с помощью IDA API. Для этого переходим в командную оболочку Python и вводим следующую команду:
Код:
idc.savefile('path_filename', 0, address_shellcode, unpack_size)
На этом этапе мы с тобой распаковали основную нагрузку, которая представляет собой исполняемый файл. Работа загрузчика разделена на несколько этапов: сначала расшифровывается исполняемый код, основная задача которого — расшифровать и распаковать шелл‑код следующего этапа. Шелл‑код следующего этапа загружает в память исполняемый файл и продолжает выполнение с его точки входа.
Исследуем основную нагрузку
Получим информацию об исполняемом файле, для этого загрузим его в утилиту DIE.
Основная нагрузка разработана на C/C++, скомпилирована в Microsoft Visual Studio и собрана для 32-разрядных систем. Загрузим файл в IDA и приступим к статическому анализу. Код вредоноса сильно обфусцирован, и граф потока выполнения очень большой.
Все строки, используемые в процессе работы модуля, зашифрованы при помощи XOR с однобайтовым ключом. Давай набросаем скрипт для IDA, который будет расшифровывать строки.
Код:
def decrypt_str(data):
result = ''
key = data & 0xff
data = data >> 8
while data > 0:
result += chr(~((data & 0xff) ^ key)&0xff)
data = data >> 8
return result
В командной строке Python запустим функцию расшифровки названия мьютекса:
Код:
decrypt_str(0xBABCABAFACA4B832)
Далее модуль с помощью функции GetLocaleInfoA узнаёт, какие в системе установлены языки. Если присутствует язык из определенного списка (в него входит русский), то модуль прекращает работу.
Следом начинается процесс взаимодействия с управляющим сервером. Адрес C2-сервера зашифрован алгоритмом RC4 и закодирован в Base64.
Расшифруем ключ, который хранится в переменной RC4_KEY.
Код:
decrypt_str(0x9498D7AB8CAEB2808B9A8E9DDCB4CA11)
Расшифруем адрес управляющего сервера, для этого воспользуемся утилитой CyberChef.
Мы получили адрес управляющего сервера:
Код:
https://tttttt.me/ch0koalpengold
Взаимодействие с управляющим сервером
При обращении к управляющему серверу https://tttttt.me/ch0koalpengold исследуемый образец получает адрес основного сервера C2. Адрес расположен в блоке div, содержащем следующие атрибуты.
Основной адрес управляющего сервера зашифрован алгоритмом RC4. Ключ:
Код:
6af7fae138b9752d1d76736dcb534c9d
При обращении к основному адресу управляющего сервера исследуемый образец получает конфиг, зашифрованный алгоритмом RC4 с ключом $Z2s'ten\@bE9vzR.
Приступим к настройке INetSim. Открываем файл sample.html вот по такому пути:
Код:
/var/lib/inetsim/http/fakefiles/sample.html
gzWH3jR7snsUFO5aZbvXyda3vfp8cjiu зашифровано алгоритмом RC4 с ключом 6af7fae138b9752d1d76736dcb534c9d. В зашифрованную строку добавлены символы, которые удаляются в процессе расшифровки.
В каталоге
/var/lib/inetsim/http/fakefiles создадим файл config.json, содержащий зашифрованные настройки.
Код:
{
"_id":"123",
"au":"files/",
"ip":"10.10.10.1",
"location":{"country":"qwe","country_code":"qwe","state":null,"state_code":null,"city":null,"zip":null},
"c":{"m":null,"lu":null},
"lu":null,
"rm":1,
"is_screen_enabled":1,
"is_history_enabled":0,
"depth":3
}
Также в каталог /var/lib/inetsim/http/fakefiles загрузим файл sqlite3.dll.
В файле
/etc/inetsim/inetsim.conf в блоке https_static_fakefile добавим статичные URL.
Каждый раз, когда малварь обращается к адресам с подстрокой /config/, загружается файл config.json (конфигурация модуля), а при открытии /config/files/ — библиотека sqlite3.dll.
Перезапустим утилиту INetSim.
Код:
sudo inetsim
Получив основной адрес управляющего сервера, вредоносный файл начинает устанавливать свое первое соединение.
Значения в POST-запросе сформированы следующим образом:
Код:
b=<MachineGuid>_<User>&c=c021300d0074689fde86c87568e215c582272721&f=json
Код:
HKLM:\SOFTWARE\Microsoft\Cryptography\MachineGuid
Для работы функции сбора данных из браузеров вредоносу необходима динамическая библиотека sqlite3.dll. Параметр au в конфиге указывает на URL, по которому малварь может получить эту библиотеку.
Сбор информации о системе
Рабочий каталог вредоносного файла:
Код:
C:\User\<User>\AppData\LocalLow
Функция сбора находится по смещению 454A (в моем случае функция sub_56454A), для перехода к коду необходимо на вкладке Function ввести значение смещения. На этапе сбора данных о системе исследуемый образец формирует файл System Info.txt в рабочей директории.
Содержимое файла System Info.txt:
- Строка Raccoon | 1.7.3 описывает версию вредоносного файла, это значение зашифровано алгоритмом шифрования строк.
- Build compile date установлена в виде константы и указывает на дату компиляции файла.
- Launched at содержит дату и время запуска.
- В блоке System Information собрана информация об имени хоста, временной зоне, установленном в системе языке, процессоре, объеме оперативной памяти и дисплеях.
- В блоке Installed Apps собрана информация об установленных приложениях, данный список получен из ключа реестра SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall.
После захвата экрана растровое изображение сохраняется в рабочую директорию с именем screen.jpeg.
После сбора всей информации с хоста в рабочей директории создается ZIP-архив. Имя файла берется из параметра _id в конфиге, полученном с C2.
Если значение параметра rm — «истина», то вредоносный файл начинает процесс самоудаления. Функция удаления расположена по смещению 5D47.
В переменной cmd формируется команда для удаления следов присутствия малвари в системе. Давай расшифруем значение.
Код:
decrypt_str(0x8FD1DE98D1DE929BBADED8DE928BB0DEC0DEB5BFBBACBCB1B0D1DECECFDEAAD1DE8A8B919B93978ADEBDD1DE9B869BD09A939D01)
Код:
cmd.exe /C timeout /T 10 /NOBREAK > Nul & Del /f /q
Код:
A:\_Work\rc-build-v1-exe\
Выводы
Эта лаборатория помогла нам научиться эмулировать работу управляющего сервера с помощью утилиты INetSim. Мы разобрали механизм работы стилера, задачей которого была кража криптокошельков, файлов cookie, паролей от браузеров и почтовых серверов и многого другого. Мы изучили работу загрузчика и распаковали основную нагрузку, а также написали скрипты для IDA и потренировались в проведении статического и динамического анализа вредоносных файлов.Автор @rayhunt454
Источник xakep.ru