Уроки форензики. Реверсим шифровальщика
В этой статье мы исследуем вредоносный файл на примере лабораторной работы Ransomed с ресурса CyberDefenders. Мы научимся вручную распаковывать код, определим технику внедрения вредоносной программы в процесс и ответим на ряд вопросов.
Нам предложен такой сценарий: организацию взломали, команда SOC обнаружила загруженный исполняемый файл. Наша задача — исследовать его и разработать индикаторы компрометации для последующего детектирования.
INFO
Исследование вредоносного файла необходимо проводить в изолированной среде. Как создать лабораторию для анализа вредоносов, подробно рассказано в статье «Код под надзором. Создаем виртуальную лабораторию для анализа малвари».
Итак, загружаем вредонос и начинаем его исследовать. По результатам решения кейса необходимо ответить на несколько вопросов, но я покажу, только как его решать, и не буду приводить ответы. Лучше повтори весь процесс самостоятельно, чтобы разобраться и закрепить материал.
ИНСТРУМЕНТАРИЙ
Для исследования вредоносного файла воспользуемся следующим софтом.
- DIE — программа для определения типов файлов.
 - PeStudio — программа для поиска артефактов исполняемых файлов.
 - IDA Pro — интерактивный дизассемблер, используемый для реверс‑инжиниринга.
 - Wireshark — инструмент для анализа сетевого трафика.
 - Burp Suite — используется в качестве прозрачного прокси‑сервера с целью анализа взаимодействия вредоносного файла по протоколу HTTPS.
 - Loki Scanner — сканер IOCs.
 - YaraEditor — программа для тестирования и создания правил YARA.
 - ApiLoger — утилита для анализа вызываемых WinAPI-функций исследуемого вредоноса.
 - x64dbg — отладчик с открытым исходным кодом для Windows, предназначенный для анализа вредоносных программ.
 
Анализировать вредоносный модуль мы будем в четыре этапа:
- Статический анализ.
 - Поведенческий анализ.
 - Динамический анализ.
 - Создание индикаторов компрометации.
 
СТАТИЧЕСКИЙ АНАЛИЗ
В первую очередь получим MD5-хеш‑сумму исполняемого файла и проверим его на VirusTotal. По MD5 a2f33095ef25b4d5b061eb53a7fe6548 VirusTotal выдает нам первичную информацию об исполняемом файле.
Далее скормим исследуемый файл утилите DIE и выясним, какой компилятор и компоновщик использовался при создании вредоноса, а также определим, упакован он или нет.
Итак, мы узнали, что вредоносный модуль разработан на C/C++ и собран для 32-разрядных операционных систем. DIE определяет упаковщик с помощью загруженных сигнатур, но идентифицировать ручной упаковщик не позволяет. Для этого необходимо посмотреть энтропию файла по секциям.
INFO
Что такое энтропия исполняемого файла, рассказано в статье «Энтропия. Как хаос помогает искать вирусы».
Значение энтропии 7,677, значит, файл упакован. Из рисунка выше видно, что исследуемый файл имеет четыре секции, энтропия секции .text равна 7,844.
Загрузим файл в утилиту PeStudio, чтобы найти всевозможные артефакты. Нам интересны временные метки компиляции файла, загружаемые библиотеки, используемые ресурсы, информация о версии исполняемого файла, характерные строки, а также отладочная информация и файл сборки (Manifest). Все это пригодится нам при создании файловой сигнатуры.
Строка C:\moz\vidaj.pdb нам интересна для создания правила детектирования. На данном этапе мы выяснили, что исполняемый файл упакован, и получили характерные строки.
Прежде чем приступить к динамическому анализу, изучим поведение вредоносного модуля. На этом этапе выявим сетевое взаимодействие с управляющим сервером, а также используемые функции Windows API.
Запустим утилиту INetSim в виртуальной машине Kali Linux. Также запустим Burp Suite для анализа взаимодействия по HTTPS и будем слушать сетевой трафик взаимодействия, используя Wireshark.
Запустим Api Loger, выберем исполняемый файл chalenge.exe и начнем писать логи.
Исполняемый файл использует функцию IsDebbugerPresent с целью антиотладки. Далее запущенный процесс считывается с помощью функции ReadProcessMemory, функция VirtualAllocEx выделяет память и данные записываются в буфер в адресное пространство процесса WriteProcessMemory. Этот механизм похож на технику внедрения в процесс ProcessHollowing.
Теперь давай посмотрим на сетевой трафик.
Как видно из рисунка выше, исполняемый файл взаимодействует со следующими доменами: api.2ip[.]ua, kotob[.]top, tzgl[.]org.
В Burp Suite видно взаимодействие по протоколу HTTPS.
Для определения IP-адреса исполняемый файл делает запрос к https://api.2ip.ua, а далее загружает с ресурса https://tzgl.org/files/1/ исполняемый файл build3.exe.
Как мы помним, в INetSim есть файлы‑заглушки. После запроса к tzgl.org загруженный файл build3.exe запускается.
Поскольку мы собрали лабораторию для анализа вредоносных файлов, в нашем случае загружается файл‑заглушка утилиты INetSim. Также обнаружен HTTP-запрос к ресурсу tzgk.org.
Используя утилиту Process Hacker 2, рассмотрим поведение запущенного файла.
Как видно из рисунка, процесс challenge.exe запускает дочерние процессы build2.exeи build3.exe, которые, в свою очередь, запускают conhost.exe.
Далее происходит шифрование всех файлов, которым назначается расширение .shgv. В конце каждого зашифрованного файла хранится одинаковая структура, в которой записаны идентификатор и данные в формате base64.
На данном этапе мы выявили сетевое взаимодействие вредоносного файла, а также обнаружили технику внедрения в процесс Process Hollowing.
Авторы вредоноса часто используют функции Windows API для выделения памяти, чтобы дальше загрузить в это место полезную нагрузку, которая будет распаковывать исполняемый код. Значит, наша задача — обнаружить этот участок кода и выяснить, какие привилегии ему выдавались. Далее мы будем шаг за шагом идти по коду в поисках функции распаковки.
После загрузки файла нажимаем F9 и попадаем в точку входа исполняемого файла.
Нас интересует функция VirtualAlloc, основная задача которой — выделение памяти в адресном пространстве процесса.
Для этого нажимаем Ctrl + G, набираем VirtualAlloc и переходим в этот участок кода.
Ставим точку останова на входе в данную функцию (клавиша F2).
Спускаемся пошагово ниже (F8), находим участок выхода из данной функции и попадаем на следующий участок кода.
После выхода из функции VirtualAlloc в регистре EAX 029E0000 хранится адрес выделенной памяти. Затем функция call 2836512 записывает код в выделенное адресное пространство, инструкция jmp dword ptr ss:[ebp-4] используется для передачи выполнения в шелл‑код. Остановимся на этой инструкции, щелкнем правой кнопки мыши, выберем переход к карте памяти и посмотрим, какие права используются для выделенной памяти по адресу ss:[ebp-4].
Как видно из рисунка выше, в выделенной памяти установлены права ERW на чтение, запись и выполнение. Далее мы попадаем в участок исполняемого кода по адресу, выделенному с помощью функции Windows API VirtualAlloc.
Здесь вредоносный код получает адреса функций в библиотеках user32.dll, kernel32.dll, ntdll.dll.
Если пролистать ниже, то из библиотеки kernel32 загружается 16 функций: WinExec, CreateFile, WriteFile, CloseHandle, CreateProcessA, GetThreadContext, VirtualAlloc, VirtualAllocEx, VirtualFree, ReadProcessMemory, WriteProcessMemory, SetThreadContext, ResumeThread, WaitForSingleObject, GetModuleFileNameA, GetCommandLineA.
Давай поговорим о методе, который вредонос использует, чтобы скрывать строки от исследователя, — Stack Strings. Основная идея этого метода заключается в перемещении строки в стек по одному символу. Обычно для этого выделяется блок памяти, далее с помощью инструкции MOV символ помещается в выделенную область.
После этого вредонос вызывает функцию RegisterClassExA, а затем запутывает две строки — saodkfnosa9uin и mfoaskdfnoa. Спустись ниже в коде, и увидишь описанный процесс.
Во время поведенческого анализа мы обнаружили, что после запуска файла создается дочерний процесс, в который передается выполнение, а также из библиотеки kernel32.dllзагружаются функции CreateProcessA, VirtualAllocEx, GetThreadContext, WriteProcessMemory, SetThreadContext и ResumeThread. Значит, вредоносный модуль использует технику Process Hollowing.
Так называется один из популярных методов внедрения вредоносного кода в память процесса. Чтобы добиться результата, вредоносное ПО удаляет легитимный код из памяти целевого процесса и перезаписывает это пространство памяти своим исполняемым файлом.
Сначала вредоносная программа создает новый процесс в приостановленном режиме CreateProces с флагом CREATE_SUSPENDED (0x00000004) и CREATE_NO_WINDOW (0x08000000). Основной поток нового процесса находится в приостановленном состоянии и ждет, пока будет вызвана функция ResumeThread. Затем память целевого процесса отключают с использованием ZwUnmapViewOfSection либо NtUnmapViewOfSection и содержимое легитимного файла заменяется вредоносной полезной нагрузкой.
Теперь, когда память отключена, загрузчик выделяет новую память для вредоносного кода с помощью VirtualAllocEx и использует WriteProcessMemory для записи каждого из разделов вредоноса в пространство целевого процесса. Далее вредоносный модуль вызывает SetThreadContext, чтобы указать точке входа новый раздел кода, который он записал. В конце вредоносная программа возобновляет приостановленный поток, вызывая ResumeThread, чтобы вывести процесс из приостановленного состояния.
Спускаемся ниже по коду, используя клавишу F8, и попадаем к следующему участку кода.
В регистре ECX содержится адрес функции CreateProcessA, которая выполняется с параметром dwCreationFlags, равным 0x08000004.
Далее происходит выделение памяти с помощью функции VirtualAlloc.
Память выделяется по адресу 001F0000. Перейдем к дампу и увидим, что он пока пуст.
Следующим этапом вызывается функция GetThreadContext с целью получить контекст потока.
Вызывается функция ReadProcessMemory для получения дескриптора процесса.
Происходит вызов функции ZmUnmapViewOfSection, которая отключает память целевого процесса.
И наконец, выполняется вызов функции VirtualAllocEx, чтобы выделить память для вредоносного модуля.
Вызываемая функция имеет пять аргументов, что мы и видим в стеке: дескриптор процесса, указатель на адрес области кода, размер выделяемой области, тип выделения памяти и защита памяти для выделенной области. Как видно из стека, параметр 0x00003000 означает MEM_COMMIT (0x00001000) | MEM_RESERVE (0x00002000). Значение 0x00000040 (PAGE_EXECUTE_READWRITE) говорит нам о том, что в выделенной области разрешен доступ на выполнение, запись и чтение.
Адрес 0x00400000 указывает на адрес, где будет располагаться вредоносный код. Далее вызывается функция NtWriteVirtualMemory.
Вызов происходит со следующими параметрами, представленными в стеке.
Значение 0x00000270 — это дескриптор процесса, 0x00400000 — базовый адрес для записи в указанном процессе, 0x29915A0 — адрес буфера, который содержит содержимое для записи в адресное пространство процесса, 0x00000400 — размер для записи в процесс.
Здесь вредоносный код записывает каждый сегмент исполняемого файла в новое адресное пространство. Ниже представлено содержимое стека при каждом вызове функции NtWriteVirtualMemory.
Спускаемся ниже и видим выполнение функции WriteProcessMemory, которая используется для записи из буфера в адресное пространство процесса.
Стек содержит следующие данные.
Значение 0x029016EC — это адрес, который содержит данные для записи.
После этого вызывается функция SetThreadContext, которая создает контекст для указанного потока, и функция ResumeThread для возобновления работы нового исполняемого файла.
Перед выполнением функции ResumeThread мы получим дамп созданного процесса. Для этого воспользуемся плагином ScyllaHide. Нажми на вкладку «Модули → Scylla».
Следующим этапом можно анализировать распакованный код в IDA Pro, которая имеет удобный плагин HexRays для декомпиляции кода. Необходимо найти код генерации ключа для шифрования файлов и алгоритм шифрования, но такое исследование выходит за рамки нашей статьи.
На текущем этапе нам удалось распаковать вредоносный модуль, мы разобрались с техникой Process Hollowing в коде. Теперь нужно разработать индикаторы компрометации.
Создадим простое YARA-правило для детектирования вредоноса. При создании сигнатур для этого семейства шифровальщиков необходимо проанализировать множество файлов, найти общие участки кода и строки. А для этого может пригодиться полезный плагин mkYARA в IDA Pro.
rule detect_ransomware 
{  
    meta:   
         description = "Detect malware ransomware"  
         autor = "rayhunt454"  
    strings:   
         $s = "gdi32.dll" nocase   
         $s1 = "moz\\vidaj.pdb" nocase   
         $s3 = "<!<-<C<O<X<^<g<s<|<"  
    condition:   
         uint16(0) == 0x5A4D and all of them 
}Выпишем также индикаторы компрометации (IOCs), которые можно загрузить в Loki Scanner и Suricata.
- MD5: a2f33095ef25b4d5b061eb53a7fe6548
 - SHA1: b38a8cb06507adb966dfdb809403f8f7f64ca534
 - URLs: https://api[.]2ip[.]ua
,https://tzgl[.]org/files/1/build3.exe,http://tzgl[.]org/fhsgtsspen6/get[.]php?pid=AD4334DBE387EF198B77CC7408B38C8F&first=false` - Domains: 
api.2ip.ua,kotob.top,tzgl.org 
ЗАКЛЮЧЕНИЕ
В этой лабораторной работе мы распаковали вредоносный файл, исследовали его поведение. При динамическом анализе разобрали технику внедрения в процесс Process Hollowing, разработали собственные индикаторы компрометации. Мы выяснили, что вредоносный файл относится к шифровальщикам, главная задача которых — зашифровать важные данные, чтобы затем потребовать выкуп.
Один хакер может причинить столько же вреда, сколько 10 000 солдат! Подпишись на наш Телеграм канал, чтобы узнать первым, как выжить в цифровом кошмаре!