Один из самых распространенных векторов атак на организации и простых пользователей — социальная инженерия. Злодеи присылают жертве электронное письмо с вложением, очень часто — документ Microsoft Office с опасным содержимым. В этой статье мы разберемся, как анализировать такие документы и как искать в их недрах вредоносный код.
Согласно матрице MITRE ATT&CK, атака, в которой злоумышленники используют документы Microsoft Office, называется Spearphising Attachment. Чтобы рассказать о методах анализа применяемых в таких атаках файлов, я воспользуюсь двумя заданиями с ресурса CyberDefenders. Первое из них — Obfuscated — позволит нам исследовать вредоносный документ в формате DOC. С помощью второго, под названием Emprisa Maldoc, мы разберем, как злоумышленники используют документ RTF для выполнения шелл‑кода.
Существуют следующие методы выполнения вредоносного кода в документах Microsoft Office.
Итак, приступим к изучению файлов с сайта CyberDefenders. Я не буду приводить ответы на вопросы из заданий — повторив все описанные ниже эксперименты, ты сможешь найти их сам.
Теперь получим информацию о структуре вредоносного документа. Для этого воспользуемся утилитой oleid.
oleid 49b367ac261a722a7c2bbbc328c32545
Информация об объекте исследования
Тулза определила, что это документ Microsoft Office Word и в нем есть VBA-макрос. Его нам предстоит вытащить наружу. Для начала воспользуемся утилитой oledump и посмотрим, в каком потоке
oledump 49b367ac261a722a7c2bbbc328c32545
Потоки исследуемого документа
Макрос спрятался в восьмом потоке данных. Выгрузим его при помощи инструмента olevba с ключом -a.
olevba -a 49b367ac261a722a7c2bbbc328c32545
Результат работы утилиты olevba
В потоке Macros/VBA/Module1 сосредоточена основная функциональность вредоносного скрипта. Из вывода утилиты видно, какие функции он использует. Давай извлечем этот скрипт и начнем исследовать код.
olevba -c 49b367ac261a722a7c2bbbc328c32545
Участок обфусцированного кода вредоносного VBA-макроса
Функция AutoOpen() запускает выполнение скрипта, когда документ открывают. Чтобы усложнить нам работу, злоумышленники обфусцировали код VBA-макроса: имена переменных представлены в формате Base64. Мы будем вручную деобфусцировать код и разберем его функциональность.
Начнем с функции AutoOpen().
Участок кода функции AutoOpen
На картинке ты видишь выделенный фрагмент кода, содержащий несколько очень интересных функций. Функция FileLen(ActiveDocument.FullName) получает размер документа Word и записывает его в переменную N18Eoi6OG6T2rNoVl41W. Функция Open(ActiveDocument.FullName) открывает документ в бинарном формате, затем записывает его содержимое в переменную E2kvpmR17SI и преобразует считанные строки в кодировку Unicode.
Во втором выделенном блоке с использованием объекта vbscript.regexp выполняется поиск такой строки в открытом файле:
MxOH8pcrlepD3SRfF5ffVTy86Xe41L2qLnqTd5d5R7Iq87mWGES55fswgG84hIRdX74dlb1SiFOkR1Hh
В переменной Y5t4Ul7o385qK4YDhr хранится указатель на первый символ найденной строки в исходном документе.
Продолжение участка кода функции AutoOpen
Обфусцированный вредоносный код расположен после обнаруженной нами строки, его размер составляет 16 827 байт.
Начало полезной нагрузки
Из файла считывается информация начиная с байта 0x503c, далее декодируется по алгоритму, который мы разберем ниже, и сохраняется в файл %appdata%\Microsoft\Windows\maintools.js. Затем с помощью WScript.Shell выполняется JS-скрипт maintools.js с параметром EzZETcSXyKAdF_e5I2i1.
Давай разберем алгоритм декодирования и напишем небольшую программу на Python для получения исходного JS-скрипта.
Функция декодирования полезной нагрузки
Для удобства чтения кода я переименовал переменные. Алгоритм декодирования очень прост. С каждым байтом выполняется операция XOR (исключающее «или») с ключом, который хранится в переменной KEY. После каждого преобразования байта изменяется и сам ключ.
Напишем собственный скрипт для декодирования полезной нагрузки, используя Python 3.
import re
def Decode(bVar):
# Алгоритм декодирования полезной нагрузки
result = ""
key = 45
for i in range(0,len(bVar)):
result += chr(bVar ^ key)
key = (key ^ 99) ^ (i % 254)
return result
reg = b"MxOH8pcrlepD3SRfF5ffVTy86Xe41L2qLnqTd5d5R7Iq87mWGES55fswgG84hIRdX74dlb1SiFOkR1Hh"
f = open("49b367ac261a722a7c2bbbc328c32545","rb")
w = open("maintools.js","w") # Файл для записи раскодированной полезной нагрузки
data_read = f.read()
start = re.search(reg,data).span()[1] # Начало полезной нагрузки
stop = start + 16827 # Конец полезной нагрузки
data1 = data_read[start:stop]
w.write(Decode(data))
f.close()
w.close()
Этот скрипт находит строку MxOH8... в исследуемом документе и считывает данные размером 16 827 байт. Далее по алгоритму, реализованному в функции Decode, он расшифровывает полезную нагрузку и сохраняет результат в файл maintools.js.
Итак, с помощью нашей программы мы вытащили расшифрованный JS-сценарий. Посмотрим, что у него внутри?
Основной код вредоносного скрипта до преобразования переменных
В переменную wvy1 сохраняются аргументы командной строки. Функция y3zb() возвращает основную полезную нагрузку, которая преобразуется по определенному алгоритму. Рассмотрим эту функцию повнимательнее.
Участок кода, содержащий полезную нагрузку
В переменной qGxZ хранится основной вредоносный код, который перед выполнением декодируется. Но чтобы понять принцип расшифровки, сначала переименуем название переменных в скрипте — просто ради удобства.
Основной код после преобразования переменных
В функции LXv5 реализован алгоритм декодирования Base64, поэтому переименуем ее в Base64_decode. Функция CpPT содержит алгоритм шифрования RC4, дадим ей имя RC4(). Этой функции в качестве аргумента передается строка EzZETcSXyKAdF_e5I2i1, которая является аргументом командной строки и одновременно ключом для деобфускации полезной нагрузки. А расшифрованный код JavaScript выполняет функция eval.
Участок кода, в котором реализован алгоритм шифрования RC4
В первых двух циклах реализован алгоритм Key-scheduling algorithm, с помощью которого в дальнейшем генерируется ключ. Напишем скрипт на Python 3, расшифровывающий полезную нагрузку из переменной qGxZ функции y3zb().
from Crypto.Cipher import ARC4
import base64
payload = "zAubgpaJRj0tIneNNZL0 ... rbhue4N84o9YPBy/SFieRfjQP5lsrSZWJKNJ5ZSbf06ZO4=";
key = b"EzZETcSXyKAdF_e5I2i1"
rc4 = ARC4.new(key)
decode = rc4.decrypt(base64.b64decode(payload))
w = open('result.js','wb')
w.write(decode)
w.close()
После преобразования полезной нагрузки мы получили еще один код JavaScript, в котором и реализована основная функциональность.
Участок полученного JavaScript-кода
Этот сценарий собирает информацию о скомпрометированной системе и отправляет ее на управляющие серверы.
Заголовок отправляемых данных
Из рисунка выше виден заголовок, который формируется для отправки данных методом POST.
Метод закрепления в системе
После запуска вредоносный скрипт копирует себя в следующую папку:
C:\Users\<Пользователь>\AppData\Local\Microsoft\Windows
А затем создает в планировщике задач Windows новую задачу, которая запускается при входе пользователя в систему. Задача имеет имя Task Manager, описание Windows Task Manager, а сам скрипт запускается из каталога WPD. Найти в системе это задание можно с помощью команды schtasks /query /fo csv /v, а еще можно просто зайти в папку C:\Windows\System32\Tasks и отыскать в ней подкаталог WPD. Весь свой трафик сценарий шифрует алгоритмом RC4 с ключом 2f532d6baec3d0ec7b1f98aed4774843. Для запуска JS-скрипта используется утилита командной строки cscript.exe.
Для начала соберем информацию об объекте исследования с помощью утилиты rtfobj.
rtfobj c39-EmprisaMaldoc.rtf
Вывод работы утилиты rtfobj
Тулза определила, что RTF-документ содержит встроенный объект. Для выполнения вредоносного кода используется уязвимость CVE-2017-11882, эксплуатирующая переполнение буфера в редакторе Microsoft Equation. Проанализируем этот файл с помощью утилиты rtfdump.
rtfdump c39-EmprisaMaldoc.rtf
Объекты, расположенные в исследуемом файле
Как видно из рисунка, в документе спрятан объект с именем Equation.e, magic-байт d0cf11e0. Исследуем поток 7, затем выгрузим из него OLE-объект и сохраним в файл objrtf.
rtfdump c39-EmprisaMaldoc.rtf -s 7 -H -E -d > objrtf
Полученный OLE-объект можно изучить при помощи утилиты oledump.
oledump objrtf
Анализ OLE-объекта
После строки Equation Native в шестнадцатеричном представлении содержится обфусцированный шелл‑код. Сохраним его дамп в файл shell.
oledump objrtf -s 4 -d > shell
Шестнадцатеричное значение шелл‑кода
Чтобы разобраться, как работает этот шелл‑код, нам понадобится утилита scdbg. Запустим ее с параметром /findsc, который эмулирует выполнение шелл‑кода при каждом смещении в файле.
scdbg /f shell findsc
Эмуляция вредоносного шелл‑кода
Функция LoadLibraryA загружает динамическую библиотеку urlmon.dll. Далее с использованием функции URLDownloadToFileA из этой библиотеки с ресурса raw.githubusercontent.com скачивается полезная нагрузка и сохраняется в файл o.exe. Затем выполняется выход из процесса с помощью функции ExitProcess.
Получим полезную нагрузку и посмотрим, что это такое. Адрес следующий:
Полезная нагрузка, сохраненная в файл‑заглушку Inetsim
Вернемся в виртуальную машину с Windows 10, установим Microsoft Office и откроем в нем исследуемый файл c39-EmprisaMaldoc.rtf, чтобы проанализировать его поведение.
Если файл открыть, запустится дочерний процесс EQNEDT32.EXE (компонент MS Office, отвечающий за вставку и редактирование объектов OLE в документы). Уязвимость срабатывает, когда EQNEDT32.EXE пытается скопировать имя шрифта в локально созданный буфер. Размер буфера составляет всего 40 (0x28) байт, однако, если имя шрифта длиннее 40 байт, буфер и регистр EBP переполнятся, а адреса возврата будут перезаписаны. Когда функция завершит выполнение, поток управления доставится по назначенному злоумышленником адресу.
Выполняющийся таким образом шелл‑код загружает полезную нагрузку из виртуальной машины Kali Linux (файл sample.png) и сохраняет по пути C:\o.exe. После запуска этого исполняемого файла появляется модальное окно, содержащее флаг.
Вывод полезной нагрузки
Давай посмотрим, какое имя шрифта загружается процессом, когда открывают вредоносный документ. Для этого запустим Proccess Hacker 2, откроем документ, найдем процесс Winword.exe и перейдем на вкладку Memory. В памяти отыщем обращение к папке C:\Windows\Fonts и увидим, что процесс пытается загрузить шрифт times.ttf. Значит, это шрифт Times New Roman.
Согласно матрице MITRE ATT&CK, атака, в которой злоумышленники используют документы Microsoft Office, называется Spearphising Attachment. Чтобы рассказать о методах анализа применяемых в таких атаках файлов, я воспользуюсь двумя заданиями с ресурса CyberDefenders. Первое из них — Obfuscated — позволит нам исследовать вредоносный документ в формате DOC. С помощью второго, под названием Emprisa Maldoc, мы разберем, как злоумышленники используют документ RTF для выполнения шелл‑кода.
Существуют следующие методы выполнения вредоносного кода в документах Microsoft Office.
- Выполнение кода, встроенного в макрос VBA.
- Выполнение JavaScript в документах Microsoft Office.
- Выполнение полезной нагрузки с использованием уязвимостей в приложениях Microsoft Office.
- oleid — для анализа OLE-файлов;
- olevba — для извлечения и анализа исходного кода макросов VBA из документов MS Office (OLE и OpenXML);
- oledump — для анализа потоков данных OLE-файла;
- rtfdump — для анализа файлов формата RTF;
- rtfobj — для извлечения встроенных объектов из файлов RTF;
- scdbg — для анализа шелл‑кода, утилита построена на основе библиотеки для эмуляции libemu.
INFO
Все необходимые для анализа вредоносных документов утилиты находятся в каталоге FLARE\Office виртуальной машины под управлением Windows 10.Итак, приступим к изучению файлов с сайта CyberDefenders. Я не буду приводить ответы на вопросы из заданий — повторив все описанные ниже эксперименты, ты сможешь найти их сам.
OBFUSCATED
Загрузим с сайта архив с заданием. Первым делом посчитаем хеш MD5 содержащегося в архиве файла (в результате получится значение 49b367ac261a722a7c2bbbc328c32545) и проверим его на VirusTotal.Теперь получим информацию о структуре вредоносного документа. Для этого воспользуемся утилитой oleid.
oleid 49b367ac261a722a7c2bbbc328c32545
Информация об объекте исследования
Тулза определила, что это документ Microsoft Office Word и в нем есть VBA-макрос. Его нам предстоит вытащить наружу. Для начала воспользуемся утилитой oledump и посмотрим, в каком потоке
Для просмотра ссылки необходимо нажать
Вход или Регистрация
содержится VBA-макрос.oledump 49b367ac261a722a7c2bbbc328c32545
Потоки исследуемого документа
Макрос спрятался в восьмом потоке данных. Выгрузим его при помощи инструмента olevba с ключом -a.
olevba -a 49b367ac261a722a7c2bbbc328c32545
Результат работы утилиты olevba
В потоке Macros/VBA/Module1 сосредоточена основная функциональность вредоносного скрипта. Из вывода утилиты видно, какие функции он использует. Давай извлечем этот скрипт и начнем исследовать код.
olevba -c 49b367ac261a722a7c2bbbc328c32545
Участок обфусцированного кода вредоносного VBA-макроса
Функция AutoOpen() запускает выполнение скрипта, когда документ открывают. Чтобы усложнить нам работу, злоумышленники обфусцировали код VBA-макроса: имена переменных представлены в формате Base64. Мы будем вручную деобфусцировать код и разберем его функциональность.
INFO
Для деобфускации VBA-макроса можно воспользоваться утилитой ViperMonkey, которая эмулирует выполнение сценария, но сегодня проведем ручной анализ.Начнем с функции AutoOpen().
Участок кода функции AutoOpen
На картинке ты видишь выделенный фрагмент кода, содержащий несколько очень интересных функций. Функция FileLen(ActiveDocument.FullName) получает размер документа Word и записывает его в переменную N18Eoi6OG6T2rNoVl41W. Функция Open(ActiveDocument.FullName) открывает документ в бинарном формате, затем записывает его содержимое в переменную E2kvpmR17SI и преобразует считанные строки в кодировку Unicode.
Во втором выделенном блоке с использованием объекта vbscript.regexp выполняется поиск такой строки в открытом файле:
MxOH8pcrlepD3SRfF5ffVTy86Xe41L2qLnqTd5d5R7Iq87mWGES55fswgG84hIRdX74dlb1SiFOkR1Hh
В переменной Y5t4Ul7o385qK4YDhr хранится указатель на первый символ найденной строки в исходном документе.
Продолжение участка кода функции AutoOpen
Обфусцированный вредоносный код расположен после обнаруженной нами строки, его размер составляет 16 827 байт.
Начало полезной нагрузки
Из файла считывается информация начиная с байта 0x503c, далее декодируется по алгоритму, который мы разберем ниже, и сохраняется в файл %appdata%\Microsoft\Windows\maintools.js. Затем с помощью WScript.Shell выполняется JS-скрипт maintools.js с параметром EzZETcSXyKAdF_e5I2i1.
Давай разберем алгоритм декодирования и напишем небольшую программу на Python для получения исходного JS-скрипта.
Функция декодирования полезной нагрузки
Для удобства чтения кода я переименовал переменные. Алгоритм декодирования очень прост. С каждым байтом выполняется операция XOR (исключающее «или») с ключом, который хранится в переменной KEY. После каждого преобразования байта изменяется и сам ключ.
Напишем собственный скрипт для декодирования полезной нагрузки, используя Python 3.
import re
def Decode(bVar):
# Алгоритм декодирования полезной нагрузки
result = ""
key = 45
for i in range(0,len(bVar)):
result += chr(bVar ^ key)
key = (key ^ 99) ^ (i % 254)
return result
reg = b"MxOH8pcrlepD3SRfF5ffVTy86Xe41L2qLnqTd5d5R7Iq87mWGES55fswgG84hIRdX74dlb1SiFOkR1Hh"
f = open("49b367ac261a722a7c2bbbc328c32545","rb")
w = open("maintools.js","w") # Файл для записи раскодированной полезной нагрузки
data_read = f.read()
start = re.search(reg,data).span()[1] # Начало полезной нагрузки
stop = start + 16827 # Конец полезной нагрузки
data1 = data_read[start:stop]
w.write(Decode(data))
f.close()
w.close()
Этот скрипт находит строку MxOH8... в исследуемом документе и считывает данные размером 16 827 байт. Далее по алгоритму, реализованному в функции Decode, он расшифровывает полезную нагрузку и сохраняет результат в файл maintools.js.
Итак, с помощью нашей программы мы вытащили расшифрованный JS-сценарий. Посмотрим, что у него внутри?
Основной код вредоносного скрипта до преобразования переменных
В переменную wvy1 сохраняются аргументы командной строки. Функция y3zb() возвращает основную полезную нагрузку, которая преобразуется по определенному алгоритму. Рассмотрим эту функцию повнимательнее.
Участок кода, содержащий полезную нагрузку
В переменной qGxZ хранится основной вредоносный код, который перед выполнением декодируется. Но чтобы понять принцип расшифровки, сначала переименуем название переменных в скрипте — просто ради удобства.
Основной код после преобразования переменных
В функции LXv5 реализован алгоритм декодирования Base64, поэтому переименуем ее в Base64_decode. Функция CpPT содержит алгоритм шифрования RC4, дадим ей имя RC4(). Этой функции в качестве аргумента передается строка EzZETcSXyKAdF_e5I2i1, которая является аргументом командной строки и одновременно ключом для деобфускации полезной нагрузки. А расшифрованный код JavaScript выполняет функция eval.
Участок кода, в котором реализован алгоритм шифрования RC4
В первых двух циклах реализован алгоритм Key-scheduling algorithm, с помощью которого в дальнейшем генерируется ключ. Напишем скрипт на Python 3, расшифровывающий полезную нагрузку из переменной qGxZ функции y3zb().
from Crypto.Cipher import ARC4
import base64
payload = "zAubgpaJRj0tIneNNZL0 ... rbhue4N84o9YPBy/SFieRfjQP5lsrSZWJKNJ5ZSbf06ZO4=";
key = b"EzZETcSXyKAdF_e5I2i1"
rc4 = ARC4.new(key)
decode = rc4.decrypt(base64.b64decode(payload))
w = open('result.js','wb')
w.write(decode)
w.close()
После преобразования полезной нагрузки мы получили еще один код JavaScript, в котором и реализована основная функциональность.
Участок полученного JavaScript-кода
Этот сценарий собирает информацию о скомпрометированной системе и отправляет ее на управляющие серверы.
Заголовок отправляемых данных
Из рисунка выше виден заголовок, который формируется для отправки данных методом POST.
Метод закрепления в системе
После запуска вредоносный скрипт копирует себя в следующую папку:
C:\Users\<Пользователь>\AppData\Local\Microsoft\Windows
А затем создает в планировщике задач Windows новую задачу, которая запускается при входе пользователя в систему. Задача имеет имя Task Manager, описание Windows Task Manager, а сам скрипт запускается из каталога WPD. Найти в системе это задание можно с помощью команды schtasks /query /fo csv /v, а еще можно просто зайти в папку C:\Windows\System32\Tasks и отыскать в ней подкаталог WPD. Весь свой трафик сценарий шифрует алгоритмом RC4 с ключом 2f532d6baec3d0ec7b1f98aed4774843. Для запуска JS-скрипта используется утилита командной строки cscript.exe.
EMPRISA MALDOC
Разберем задание с вредоносным документом в формате Microsoft Rich Text Format (RTF). Такие файлы очень часто используются злоумышленниками при фишинговых атаках и, как правило, содержат эксплоиты.Для начала соберем информацию об объекте исследования с помощью утилиты rtfobj.
rtfobj c39-EmprisaMaldoc.rtf
Вывод работы утилиты rtfobj
Тулза определила, что RTF-документ содержит встроенный объект. Для выполнения вредоносного кода используется уязвимость CVE-2017-11882, эксплуатирующая переполнение буфера в редакторе Microsoft Equation. Проанализируем этот файл с помощью утилиты rtfdump.
rtfdump c39-EmprisaMaldoc.rtf
Объекты, расположенные в исследуемом файле
Как видно из рисунка, в документе спрятан объект с именем Equation.e, magic-байт d0cf11e0. Исследуем поток 7, затем выгрузим из него OLE-объект и сохраним в файл objrtf.
rtfdump c39-EmprisaMaldoc.rtf -s 7 -H -E -d > objrtf
Полученный OLE-объект можно изучить при помощи утилиты oledump.
oledump objrtf
Анализ OLE-объекта
После строки Equation Native в шестнадцатеричном представлении содержится обфусцированный шелл‑код. Сохраним его дамп в файл shell.
oledump objrtf -s 4 -d > shell
Шестнадцатеричное значение шелл‑кода
Чтобы разобраться, как работает этот шелл‑код, нам понадобится утилита scdbg. Запустим ее с параметром /findsc, который эмулирует выполнение шелл‑кода при каждом смещении в файле.
scdbg /f shell findsc
Эмуляция вредоносного шелл‑кода
Функция LoadLibraryA загружает динамическую библиотеку urlmon.dll. Далее с использованием функции URLDownloadToFileA из этой библиотеки с ресурса raw.githubusercontent.com скачивается полезная нагрузка и сохраняется в файл o.exe. Затем выполняется выход из процесса с помощью функции ExitProcess.
Получим полезную нагрузку и посмотрим, что это такое. Адрес следующий:
Для просмотра ссылки необходимо нажать
Вход или Регистрация
Поведенческий анализ вредоносного документа
Зайдем в виртуальную машину Kali Linux, перейдем в каталог /var/lib/inetsim/http/fakefiles и сохраним полезную нагрузку под именем sample.png.Полезная нагрузка, сохраненная в файл‑заглушку Inetsim
Вернемся в виртуальную машину с Windows 10, установим Microsoft Office и откроем в нем исследуемый файл c39-EmprisaMaldoc.rtf, чтобы проанализировать его поведение.
Если файл открыть, запустится дочерний процесс EQNEDT32.EXE (компонент MS Office, отвечающий за вставку и редактирование объектов OLE в документы). Уязвимость срабатывает, когда EQNEDT32.EXE пытается скопировать имя шрифта в локально созданный буфер. Размер буфера составляет всего 40 (0x28) байт, однако, если имя шрифта длиннее 40 байт, буфер и регистр EBP переполнятся, а адреса возврата будут перезаписаны. Когда функция завершит выполнение, поток управления доставится по назначенному злоумышленником адресу.
Выполняющийся таким образом шелл‑код загружает полезную нагрузку из виртуальной машины Kali Linux (файл sample.png) и сохраняет по пути C:\o.exe. После запуска этого исполняемого файла появляется модальное окно, содержащее флаг.
Вывод полезной нагрузки
Давай посмотрим, какое имя шрифта загружается процессом, когда открывают вредоносный документ. Для этого запустим Proccess Hacker 2, откроем документ, найдем процесс Winword.exe и перейдем на вкладку Memory. В памяти отыщем обращение к папке C:\Windows\Fonts и увидим, что процесс пытается загрузить шрифт times.ttf. Значит, это шрифт Times New Roman.
ВЫВОДЫ
На этих двух примерах мы рассмотрели методику исследования подозрительных документов, которые распространяются злоумышленниками по электронной почте при фишинговых атаках. На GitHub можно найти РОС для рассмотренной нами эксплуатации уязвимости CVE-2017-11882, который выполняет шелл‑код по адресу в памяти 0x00402114. Microsoft закрыла эту уязвимость, выпустив патч KB4011604. Не забудь установить это обновление, чтобы обезопасить себя от подобной атаки.
Для просмотра ссылки необходимо нажать
Вход или Регистрация