BAZARLOADER (также известный как BAZARBACKDOOR) — это загрузчик для Windows, который распространяется через вложения в фишинговых письмах. Во время заражения конечная полезная нагрузка загрузчика обычно загружает и запускает маячок кобальта, чтобы предоставить злоумышленникам удаленный доступ, что во многих случаях приводит к развертыванию программы-вымогателя на компьютере жертвы.
В этом начальном посте мы раскроем различные этапы заражения BAZARLOADER, которое приходит в виде файла образа оптического диска (ISO). Мы также углубимся в методы обфускации, используемые основной полезной нагрузкой BAZARLOADER.
Чтобы продолжить, вы можете получить образец, а также файлы PCAP для него на Malware-Traffic-Analysis.net. (https://www.malware-traffic-analysis.net/2022/02/07/index.html)
SHA256: 0900b4eb02bdcaefd21df169d21794c8c70bfbc68b2f0612861fcabc82f28149
Шаг 1: Монтирование ISO-файла и извлечение исполняемого файла этапа № 1
Недавние образцы BAZARLOADER приходят по электронной почте, содержащей ссылки OneDrive для загрузки файла ISO, чтобы избежать обнаружения, поскольку большинство AV, как правило, игнорируют этот конкретный тип файла. В Windows 7 и более поздних версиях функции монтирования интегрированы в проводник Windows, и мы можем монтировать любой файл ISO как виртуальный диск, дважды щелкнув его.
Когда мы монтируем вредоносный файл ISO, мы видим, что в системе подключен диск, который содержит файл ярлыка с именем "Attachments.lnk" и скрытый файл с именем "documents.log".
Файл ярлыка должен быть запущен жертвой, чтобы начать цепочку заражения. Мы можем быстро извлечь фактическую команду, выполняемую этим ярлыком, из окна его свойств.
C:\Windows\System32\rundll32.exe documents.log,vspa
Как только жертва дважды щелкает файл ярлыка, команда запускает программу Windows rundll32.exe для запуска файла "documents.log". Это дает нам понять, что запускаемый файл является DLL-файлом, а точкой входа является его функция экспорта vspa.
Шаг 2: Извлечение шелл-кода второго этапа
Быстро взглянув в IDA, мы можем сказать, что извлеченная DLL упакована, поскольку она имеет только несколько функций и очень подозрительно выглядящий буфер символов ASCII в пользовательском разделе .odata.
Имея это в виду, мы просто проведем небольшой статический анализ, чтобы определить, где мы можем сдампить следующий стейдж.
В первой функции экспорта vspa мы видим, что sub_1800045D6 принимает DWORD в качестве параметра. Эта функция возвращает переменную, содержащую адрес функции, которая позже вызывается в коде.
На данный момент мы можем с уверенностью предположить, что sub_1800045D6 — это функция разрешения API, а параметр, который она принимает, — это хэш имени API. Поскольку это все еще фаза распаковки, мы не будем слишком углубляться в анализ этой функции.
Вместо этого я просто воспользуюсь подключаемым модулем OALabs HashDB IDA для быстрого обратного поиска используемого алгоритма хеширования из хеша. Результат показывает, что хэш соответствует имени API, хэшированному с помощью алгоритма хэширования Metasploit (https://github.com/OALabs/hashdb/bl...16663ac13f02bf1aaf37/algorithms/metasploit.py) ROR13.
После определения алгоритма хэширования мы можем использовать HashDB для быстрого поиска API, которые разрешаются этой функцией. Становится ясно, что эта функция разрешает API RtlAllocateHeap, вызывает его для выделения буфера кучи и записывает в него закодированные данные ASCII.
С этого момента мы можем предположить, что упаковщик будет декодировать этот буфер и запускать его где-то позже в коде. Если мы перейдем к концу экспорта vspa, мы увидим инструкцию вызова переменной, которая не возвращается из разрешающей функции API, поэтому потенциально это может быть наш главный прыжок.
Последняя функция для изменения этой переменной v19 — sub_180003FE6, поэтому мы можем быстро взглянуть на нее.
Оказывается, функция sub_180003FE6 просто разрешает и вызывает NtMapViewOfSection для сопоставления представления раздела с виртуальным адресным пространством и записывает базовый адрес представления в переменную v19. Затем он просто выполняет qmemcpy для копирования данных из второй переменной в возвращенный виртуальный базовый адрес.
Это говорит нам о двух вещах. Во-первых, наше предположение, что переменная v19 будет содержать адрес исполняемого кода, верно. Во-вторых, мы знаем, что исполняемый код является шеллкодом, поскольку данные отображаются и выполняются непосредственно по смещению 0 от того места, где они были записаны.
Отсюда мы можем настроить x64dbg, выполнить файл DLL при экспорте vspa и прервать выполнение инструкции call. После входа в функцию мы окажемся во главе шеллкода.
Теперь мы можем сдампить этот буфер виртуальной памяти, чтобы получить шелл-код второй стадии для следующего шага распаковки.
Шаг 3. Извлечение последней полезной нагрузки BAZARLOADER
Когда мы исследуем шелл-код в IDA, мы можем быстро использовать тот же прием с HashDB, описанный выше, чтобы увидеть, что шелл-код также выполняет хеширование API с ROR13 Metasploit.
В указанной выше точке входа шелл-код разрешает набор функций, которые он будет вызывать, в первую очередь VirtualAlloc и VirtualProtect. Эти две функции обычно используются упаковщиками для выделения виртуальной памяти для декодирования и записи исполняемого файла следующего этапа перед его запуском.
Имея это в виду, нашим следующим шагом должна быть отладка шелл-кода и установка точек останова на этих двух вызовах API. Мы можем выбрать, где мы находимся после дампа в x64dbg на шаге 2, или мы можем запустить шелл-код непосредственно в нашем отладчике, используя BlobRunner (https://github.com/OALabs/BlobRunner) OALabs или аналогичный пусковой механизм шелл-кода.
Наше первое обращение к VirtualAlloc — это вызов выделения буфера виртуальной памяти по виртуальному адресу 0x204140000 размером 0x2A000 байт.
Мы можем запускать до тех пор, пока VirtualAlloc не вернется и не начнет мониторинг памяти по адресу 0x204140000. После запуска до следующего вызова VirtualProtect мы видим, что в эту область памяти был записан допустимый исполняемый файл PE.
Наконец, мы можем выгрузить эту область памяти в файл, чтобы извлечь полезную нагрузку BAZARLOADER.
Шаг 4: Обфускация строк BAZARLOADER
Поскольку мы начинаем выполнять статический анализ BAZARLOADER, крайне важно определить методы запутывания, которые использует вредоносное ПО.
Одним из таких методов является обфускация строк, когда вредоносное ПО использует закодированные строки стека, чтобы скрыть их от статического анализа.
Как показано, типичная закодированная строка помещается в стек и динамически декодируется с использованием некоторых операций умножения, вычитания и модуля.
Существуют разные способы разрешения этих строк стека, например, написание сценариев IDAPython, эмуляция (https://github.com/mandiant/flare-emu) или просто запуск программы в отладчике и сброс строк стека после их разрешения.
Шаг 5: Обфускация API BAZARLOADER
BAZARLOADER запутывает большинство своих вызовов API с помощью нескольких структур, которые он создает в функции DllEntryPoint.
Сначала вредоносная программа заполняет следующую структуру, содержащую дескриптор Kernel32.dll и адреса API, необходимые для загрузки библиотек и получения их API-адресов.
Он вызывает GetModuleHandle для получения дескриптора Kernel32.dll, вызывает GetProcAddress для получения адреса API GetProcAddress и записывает их в структуру.
Используя поле GetProcAddress API структуры, BAZARLOADER извлекает остальные необходимые API для заполнения других полей в структуре. Эта структура API_IMPORT_STRUCT позже будет использоваться для импорта API других библиотек.
Затем для каждой импортируемой библиотеки BAZARLOADER заполняет следующую структуру LIBRARY_STRUCT, содержащую набор функций для взаимодействия с библиотекой и дескриптором библиотеки.
Первые 2 функции в структуре LIB_FUNCS просто вызывают FreeLibrary API из глобального API_IMPORT_STRUCT, чтобы освободить библиотечный модуль.
Третья функция вызывает GetProcAddress из поля API_IMPORT_STRUCT, чтобы получить адрес API, экспортированного из этой конкретной библиотеки.
Чтобы начать заполнение каждой структуры LIBRARY_STRUCT, BAZARLOADER декодирует имя библиотеки из строки стека и заполняет ее соответствующим набором функций и дескриптором библиотеки, полученным при вызове LoadLibraryA.
Ниже приведен список всех библиотек, используемых вредоносной программой.
Соответствующие им структуры LIBRARY_STRUCT помещаются в глобальный список в порядке, указанном ниже.
После того, как этот глобальный список LIBRARY_STRUCT заполнен, API может быть вызван из функции, принимающей структуру LIBRARY_STRUCT соответствующей библиотеки и ее параметры.
Эта функция разрешает имя API из строки стека, извлекает адрес API с помощью функции get_API_addr из структуры библиотеки и вызывает API с его параметрами.
Способ настройки функции-оболочки для вызова фактического API действительно интуитивно понятен, что упрощает понимание кода с помощью статического анализа. Однако автоматизировать этот процесс немного сложнее, поскольку не используется хеширование API.
Для моего анализа я просто вручную декодирую строки стека в своем отладчике и соответствующим образом переименовываю функцию-оболочку.
На данный момент мы полностью распаковали BAZARLOADER и поняли, как вредоносное ПО запутывает свои строки и API, чтобы затруднить анализ.
В следующем посте мы полностью проанализируем, как загрузчик загружает и запускает маячок Cobalt Strike со своих серверов C2!
Переведено специально для xss.pro
Автор перевода: yashechka
Источник: https://www.0ffset.net/reverse-engineering/bazarloader-iso-file-infection/
В этом начальном посте мы раскроем различные этапы заражения BAZARLOADER, которое приходит в виде файла образа оптического диска (ISO). Мы также углубимся в методы обфускации, используемые основной полезной нагрузкой BAZARLOADER.
Чтобы продолжить, вы можете получить образец, а также файлы PCAP для него на Malware-Traffic-Analysis.net. (https://www.malware-traffic-analysis.net/2022/02/07/index.html)
SHA256: 0900b4eb02bdcaefd21df169d21794c8c70bfbc68b2f0612861fcabc82f28149
Шаг 1: Монтирование ISO-файла и извлечение исполняемого файла этапа № 1
Недавние образцы BAZARLOADER приходят по электронной почте, содержащей ссылки OneDrive для загрузки файла ISO, чтобы избежать обнаружения, поскольку большинство AV, как правило, игнорируют этот конкретный тип файла. В Windows 7 и более поздних версиях функции монтирования интегрированы в проводник Windows, и мы можем монтировать любой файл ISO как виртуальный диск, дважды щелкнув его.
Когда мы монтируем вредоносный файл ISO, мы видим, что в системе подключен диск, который содержит файл ярлыка с именем "Attachments.lnk" и скрытый файл с именем "documents.log".
Файл ярлыка должен быть запущен жертвой, чтобы начать цепочку заражения. Мы можем быстро извлечь фактическую команду, выполняемую этим ярлыком, из окна его свойств.
C:\Windows\System32\rundll32.exe documents.log,vspa
Как только жертва дважды щелкает файл ярлыка, команда запускает программу Windows rundll32.exe для запуска файла "documents.log". Это дает нам понять, что запускаемый файл является DLL-файлом, а точкой входа является его функция экспорта vspa.
Шаг 2: Извлечение шелл-кода второго этапа
Быстро взглянув в IDA, мы можем сказать, что извлеченная DLL упакована, поскольку она имеет только несколько функций и очень подозрительно выглядящий буфер символов ASCII в пользовательском разделе .odata.
Имея это в виду, мы просто проведем небольшой статический анализ, чтобы определить, где мы можем сдампить следующий стейдж.
В первой функции экспорта vspa мы видим, что sub_1800045D6 принимает DWORD в качестве параметра. Эта функция возвращает переменную, содержащую адрес функции, которая позже вызывается в коде.
На данный момент мы можем с уверенностью предположить, что sub_1800045D6 — это функция разрешения API, а параметр, который она принимает, — это хэш имени API. Поскольку это все еще фаза распаковки, мы не будем слишком углубляться в анализ этой функции.
Вместо этого я просто воспользуюсь подключаемым модулем OALabs HashDB IDA для быстрого обратного поиска используемого алгоритма хеширования из хеша. Результат показывает, что хэш соответствует имени API, хэшированному с помощью алгоритма хэширования Metasploit (https://github.com/OALabs/hashdb/bl...16663ac13f02bf1aaf37/algorithms/metasploit.py) ROR13.
После определения алгоритма хэширования мы можем использовать HashDB для быстрого поиска API, которые разрешаются этой функцией. Становится ясно, что эта функция разрешает API RtlAllocateHeap, вызывает его для выделения буфера кучи и записывает в него закодированные данные ASCII.
С этого момента мы можем предположить, что упаковщик будет декодировать этот буфер и запускать его где-то позже в коде. Если мы перейдем к концу экспорта vspa, мы увидим инструкцию вызова переменной, которая не возвращается из разрешающей функции API, поэтому потенциально это может быть наш главный прыжок.
Последняя функция для изменения этой переменной v19 — sub_180003FE6, поэтому мы можем быстро взглянуть на нее.
Оказывается, функция sub_180003FE6 просто разрешает и вызывает NtMapViewOfSection для сопоставления представления раздела с виртуальным адресным пространством и записывает базовый адрес представления в переменную v19. Затем он просто выполняет qmemcpy для копирования данных из второй переменной в возвращенный виртуальный базовый адрес.
Это говорит нам о двух вещах. Во-первых, наше предположение, что переменная v19 будет содержать адрес исполняемого кода, верно. Во-вторых, мы знаем, что исполняемый код является шеллкодом, поскольку данные отображаются и выполняются непосредственно по смещению 0 от того места, где они были записаны.
Отсюда мы можем настроить x64dbg, выполнить файл DLL при экспорте vspa и прервать выполнение инструкции call. После входа в функцию мы окажемся во главе шеллкода.
Теперь мы можем сдампить этот буфер виртуальной памяти, чтобы получить шелл-код второй стадии для следующего шага распаковки.
Шаг 3. Извлечение последней полезной нагрузки BAZARLOADER
Когда мы исследуем шелл-код в IDA, мы можем быстро использовать тот же прием с HashDB, описанный выше, чтобы увидеть, что шелл-код также выполняет хеширование API с ROR13 Metasploit.
В указанной выше точке входа шелл-код разрешает набор функций, которые он будет вызывать, в первую очередь VirtualAlloc и VirtualProtect. Эти две функции обычно используются упаковщиками для выделения виртуальной памяти для декодирования и записи исполняемого файла следующего этапа перед его запуском.
Имея это в виду, нашим следующим шагом должна быть отладка шелл-кода и установка точек останова на этих двух вызовах API. Мы можем выбрать, где мы находимся после дампа в x64dbg на шаге 2, или мы можем запустить шелл-код непосредственно в нашем отладчике, используя BlobRunner (https://github.com/OALabs/BlobRunner) OALabs или аналогичный пусковой механизм шелл-кода.
Наше первое обращение к VirtualAlloc — это вызов выделения буфера виртуальной памяти по виртуальному адресу 0x204140000 размером 0x2A000 байт.
Мы можем запускать до тех пор, пока VirtualAlloc не вернется и не начнет мониторинг памяти по адресу 0x204140000. После запуска до следующего вызова VirtualProtect мы видим, что в эту область памяти был записан допустимый исполняемый файл PE.
Наконец, мы можем выгрузить эту область памяти в файл, чтобы извлечь полезную нагрузку BAZARLOADER.
Шаг 4: Обфускация строк BAZARLOADER
Поскольку мы начинаем выполнять статический анализ BAZARLOADER, крайне важно определить методы запутывания, которые использует вредоносное ПО.
Одним из таких методов является обфускация строк, когда вредоносное ПО использует закодированные строки стека, чтобы скрыть их от статического анализа.
Как показано, типичная закодированная строка помещается в стек и динамически декодируется с использованием некоторых операций умножения, вычитания и модуля.
Существуют разные способы разрешения этих строк стека, например, написание сценариев IDAPython, эмуляция (https://github.com/mandiant/flare-emu) или просто запуск программы в отладчике и сброс строк стека после их разрешения.
Шаг 5: Обфускация API BAZARLOADER
BAZARLOADER запутывает большинство своих вызовов API с помощью нескольких структур, которые он создает в функции DllEntryPoint.
Сначала вредоносная программа заполняет следующую структуру, содержащую дескриптор Kernel32.dll и адреса API, необходимые для загрузки библиотек и получения их API-адресов.
Он вызывает GetModuleHandle для получения дескриптора Kernel32.dll, вызывает GetProcAddress для получения адреса API GetProcAddress и записывает их в структуру.
Используя поле GetProcAddress API структуры, BAZARLOADER извлекает остальные необходимые API для заполнения других полей в структуре. Эта структура API_IMPORT_STRUCT позже будет использоваться для импорта API других библиотек.
Затем для каждой импортируемой библиотеки BAZARLOADER заполняет следующую структуру LIBRARY_STRUCT, содержащую набор функций для взаимодействия с библиотекой и дескриптором библиотеки.
Первые 2 функции в структуре LIB_FUNCS просто вызывают FreeLibrary API из глобального API_IMPORT_STRUCT, чтобы освободить библиотечный модуль.
Третья функция вызывает GetProcAddress из поля API_IMPORT_STRUCT, чтобы получить адрес API, экспортированного из этой конкретной библиотеки.
Чтобы начать заполнение каждой структуры LIBRARY_STRUCT, BAZARLOADER декодирует имя библиотеки из строки стека и заполняет ее соответствующим набором функций и дескриптором библиотеки, полученным при вызове LoadLibraryA.
Ниже приведен список всех библиотек, используемых вредоносной программой.
Соответствующие им структуры LIBRARY_STRUCT помещаются в глобальный список в порядке, указанном ниже.
После того, как этот глобальный список LIBRARY_STRUCT заполнен, API может быть вызван из функции, принимающей структуру LIBRARY_STRUCT соответствующей библиотеки и ее параметры.
Эта функция разрешает имя API из строки стека, извлекает адрес API с помощью функции get_API_addr из структуры библиотеки и вызывает API с его параметрами.
Способ настройки функции-оболочки для вызова фактического API действительно интуитивно понятен, что упрощает понимание кода с помощью статического анализа. Однако автоматизировать этот процесс немного сложнее, поскольку не используется хеширование API.
Для моего анализа я просто вручную декодирую строки стека в своем отладчике и соответствующим образом переименовываю функцию-оболочку.
На данный момент мы полностью распаковали BAZARLOADER и поняли, как вредоносное ПО запутывает свои строки и API, чтобы затруднить анализ.
В следующем посте мы полностью проанализируем, как загрузчик загружает и запускает маячок Cobalt Strike со своих серверов C2!
Переведено специально для xss.pro
Автор перевода: yashechka
Источник: https://www.0ffset.net/reverse-engineering/bazarloader-iso-file-infection/