какую первую задачу решает буткит alipop при загрузке
Разбор буткита
Всем привет! В связи с запуском курса «Реверс-инжиниринг» мы провели плановый открытый урок. На нём разобрали алгоритм работы буткита на разных стадиях его загрузки.
Преподаватель — Артур Пакулов, вирусный аналитик в Kaspersky Lab.
Следующая статья носит вступительный характер и представляет собой текстовую версию лишь части урока, которая посвящена установщику буткита. Подробный разбор самого буткита смотрите в видео.
Буткит (Bootkit) — вредоносная программа, осуществляющая модификацию Master Boot Record — первого сектора первого физического диска либо загрузочного сектора — VBR. Программы такого рода, в основном, имеют троянский функционал и используются для осуществления каких-либо скрытых действий в системе. В нашем примере, буткит осуществляет повышение привилегий до уровня системы процессу, имя которого начинается на последовательность букв: “inte”. Фактически, буткит — это руткит, начинающий работать в 0 кольце защиты, который запускается ещё до начала загрузки операционной системы. Именно из-за этого он и представляет большой интерес для исследования.
Чтобы разработать такую программу, обычных навыков реверс-инжиниринга недостаточно. Мало просто уметь читать листинг, нужно ещё и понимать такие вещи, как архитектура процессора, адресация памяти и т. д. Ключевые места буткита мы и посмотрели на открытом уроке.
Для работы был подготовлен специальный семпл bootkit-xp.exe, работающий под Windows XP. Поэтому, кроме изучения буткита, немного поностальгировали по этой операционной системе. Но вообще, ОС XP была выбрана для того, чтобы проще было реверсить, так как XP — это хорошая наглядность и отсутствие лишних осложнений. Ну и, семпл был написан именно под эту OS, судя по его коду.
Просто глядя на него, можно сделать определённые выводы. Например, сразу бросается в глаза, что этот файл имеет маленький вес. Если же глянуть на точку входа, то можно заметить, что в коде идёт получение дескриптора файла с именем символьной ссылки на первый физический диск — “PhysicalDrive0”:
Далее для удобства восприятия кода перешли в IDA. Становится ясно, что для типичного трояна имеющийся функционал довольно мал. Даже таблица импорта подозрительно мала:
Такая картина обычно вырисовывается при анализе упакованных семплов. Но, в нашем случае файл не выглядит упакованным. Выходит, что семпл либо накрыт каким-либо протектором/криптором и в процессе своей работы получает адреса функций динамическим образом, после чего вызывает нужный функционал, либо всё нормально, и сэмпл такой, какой есть.
Продолжаем исследовать код.
Как мы уже видели в HIEW, вызывается функция CreateFileA с интересным аргументом в качестве первого параметра Что именно тут делается? Тут уместно вспомнить про такое понятие, как объекты ядра. Ими нельзя манипулировать напрямую из режима пользователя, ими управляет ядро операционной системы. Из user mode программа может только сделать запрос на получение/изменение состояния какого-либо объекта ядра. Чтобы указать системе, с каким именно объектом ядра будет работать программа, требуется получить хендл нужного объекта ядра. При запросе на получение, если все проверки будут пройдены, OS вернёт нам handle запрашиваемого ОЯ. А уже используя handle, мы можем работать со связанным с ним ОЯ.
Таким образом, на приведённом выше изображении с помощью CreateFile идёт обращение через символьную ссылку к первому подключенному физическому жёсткому диску. Если доступ предоставляется, то работать с таким “файлом” можно будет как и с любым другим простым файлом. Т. е. весь жёсткий диск целиком будет представляться как один большой файл.
Итак, продолжим. Handle вернулся, и мы оказываемся здесь:
Что дальше происходит? А дальше функция ReadFile, считывает первые 0x200 байт. А находится у нас там самый первый сектор первого физического диска.
Как вы уже догадались, это Master Boot Record (MBR). MBR состоит из 3 частей: кодовой части, таблицы разделов и сигнатуры. В обычной ситуации bios вычитывает MBR в память по адресу 0:0x7c00h, передавая на неё управление. Так, кодовая часть MBR начинает выполняться. В процессе выполнения она парсит таблицу разделов, находит загрузочный сектор и грузит его. В случае буткита, если MBR будет перезаписан, его код уже сейчас получит управление.
Ок, MBR считан а, что дальше? А дальше буткит снова открывает PhysicalDrive0, но с режимом доступа на запись.
Дальше устанавливается указатель по 600-му смещению. То есть оригинальный сектор считывается и копируется в третий сектор.
Зачем бэкапить сектор? Очевидно, что это нужно для того, что он понадобится в дальнейшем.
Дальше запускается цикл. Естественно, глядя на код, нельзя не обратить внимание на константы типа var_1C, 1BEh и прочие. И, заодно, следует освежить в памяти структуру MBR, размещённую выше. В частности, нас интересует колонка «Смещение».
Смотрите, прочитанный буфер первого сектора находится в lpBuffer. Далее к нему прибавляется 1BEh, Фактически, указатель направляется на начало таблицы разделов. Все данные, начиная с таблицы и до конца сектора вставляются в _marked_bytes, начиная с того же смещения — 1BE.
То есть, в _marked_bytes вставляется вторая и третья часть оригинального MBR.
Что происходит дальше? А дальше SetFilePointer устанавливает указатель в самое начало нашего “файла”, т. е. на MBR.
Потом происходит запись (WriteFile) сформированного _marked_bytes и освобождение памяти. На этом функционал установщика буткита заканчивается.
Но неплохо было бы посмотреть, а что именно находится в первой части _marked_bytes. Для этого, сдампим её на диск и проанализируем. Первое, что бросается в глаза, — уменьшение на 2 содержимого переменной по адресу 0x413.
Если посмотреть техническую документацию, то можно найти, что переменная по адресу 0X413 содержит количество установленной физической памяти в килобайтах. Соответственно, код буткита “отрезает” два килобайта памяти:
Теперь, чтобы не делалось дальше, будет считаться, что имеется на 2 килобайт памяти меньше, чем было. Зачем — пока непонятно.
Дальше происходит рассчитывание физического адреса к “откусанному” куску памяти с помощью побитового сдвига влево на 6 разрядов:
Сдвиг на 6 делает два действия разом — переводит килобайты в байты (домножив значение переменной на 2^10), тем самым получив физический адрес к откусанному куску памяти, и извлекает из него номер сегмента, поделив результат на 0x10 (2^4).
После произойдёт копирование своего тела по этому куску памяти, причём, т. к. код буткита находится именно в “откусанном” куске, его дальше уже никто не потревожит. Мало того, никакие прерывания не изменят того, что написано в этой области памяти. Можно сказать, что код становится фактически невидимым для системы, как будто там и нет никакой памяти.
Это только самое начало работы буткита. Дальше будет перехват прерывания, отслеживание сигнатуры ntldr, модификация модуля ядра ОС и т. д…
Поэтому не будем спойлерить, лучше досмотрите вебинар до конца, чтобы ничего не пропустить.
Современные буткит-технологии и детальный анализ Win32/Gapz
В последние несколько лет увеличилось распространение вредоносных программ (буткитов), модифицирующих загрузочные сектора в процессе заражения системы. Среди самых видных представителей — TDL4, Olmasco и Rovnix. Каждый из них использует различные способы заражения жесткого диска, это либо модификация главной загрузочной записи (MBR), либо модификация первых секторов загрузочного раздела, т. е. VBR или IPL (первые сектора тома, куда передается управление из MBR — Volume Boot Record/Initial Program Loader). Наглядно эти семейства показаны на рисунке ниже.
Рис. 1. Схема различных семейств буткитов и методов заражения диска.
Существует несколько причин использования буткитов в современных угрозах:
● Возможность запуска вредоносного кода раньше кода ОС, что дает неоспоримые преимущества и позволяет контролировать процесс загрузки ОС.
● Как следствие первого пункта, позволяет обходить систему мониторинга целостности ключевых компонентов ядра — PatchGuard (практически единственный способ обеспечить выживаемость руткита в x64-среде).
● Возможность глубоко скрывать свой код и, таким образом, делать его невидимым для AV-сканеров.
● Буткит имеет посекторную архитектуру хранения своего тела на диске, что дает возможность выносить свой вредоносный код и код полезной нагрузки далеко за пределы файловой системы и даже разделов диска, делая почти невозможным его обнаружение.
● Безопасная установка руткита в системе.
В отчете ESET по угрозам и трендам за 2012 г., мы указали, что буткиты являются одним из ключевых технических трендов прошедшего года. Наши эксперты отслеживают появление новых сложных угроз. Мы также не обошли стороной и Win32/Gapz, так как он содержит ряд технических особенностей, которые делают его действительно интересным. Александр Матросов и Евгений Родионов проделали большую работу, занимаясь анализом этого буткита. Сегодняшний наш пост посвящен этому анализу.
Начнем с дроппера — компонента, который является изначальным носителем кода буткита и отвечает за его установку в системе. Мы детектируем его как: Win32/Gapz.X, X-версия. Мы обнаружили три его версии, A, B и C. Ниже в таблице приведены их характеристики:
Рис. 2.
В соответствии с нашими наблюдениями, первая известная версия дроппера была скомпилирована в апреле прошлого года и содержала много отладочной информации, т. е. не подразумевалась для массового распространения. Вполне вероятно, что Win32/Gapz начали массово распространять в конце лета или начале сентября прошедшего года. Для поднятия своих привилегий в системе Win32/Gapz использует LPE-эксплойты и COM Elevation метод.
В процессе анализа мы обнаружили, что заражению Win32/Gapz подвержены: 32-битные Windows XP SP2 и выше (исключая Windows Vista и Vista SP1) и 64-битные Windows XP SP2 и выше. Обсуждаемая версия дроппера Win32/Gapz способна заражать Windows XP и Windows 7, включая x64 версии, однако на Windows 8 буткит-часть не работает должным образом и после заражения часть, надлежащая к исполнению в режиме ядра, не исполнялась.
Рис. 3. Часть кода дроппера, проверяющая версию ОС.
Дроппер, устанавливающий буткит в систему, тщательно продуман и способен обойти современные проактивные защиты (HIPS), а также поднимать свои привилегии до уровня системы. Кроме того, он содержит хитрый метод внедрения кода в адресное пространство процесса. Файл дроппера экспортирует из себя несколько функций, которые указаны ниже на рисунке.
Рис. 4. Функции, экспортируемые исполняемым файлом дроппера.
Есть три экспортируемые функции, на которые следует обратить внимание: start, icmnf и isyspf. Краткое описание:
● start — точка входа в дроппер, осуществляет его внедрение в адресное пространство доверенного процесса explorer.exe;
● icmnf — отвечает за повышение (эскалацию) привилегий;
● isyspf — выполняет заражение жертвы кодом буткита.
Код дроппера использует специальную секцию, которая спроецирована в адресное пространство процесса explorer. Через эту секцию он загружает шелл-код в этот процесс и далее, с помощью специально сформированного API-вызова, производит его активацию. Соответственно, после того, как шелл-код активирован, он подгружает образ дроппера в адресное пространство процесса explorer, вызывает функцию повышения привилегий и инициирует процедуру заражения кодом буткита, записывая его на диск.
Рис. 5. Стадии выполнения дроппера и заражения жертвы кодом буткита.
После того, как дроппер заразил систему буткитом, его задача исполнена, и он удаляет свой файл с диска.
Вредоносный код MBR
Мы обнаружили две модификации буткита Win32/Gapz, которые различаются методами заражения диска жертвы. Самая ранняя модификация появилась в начале лета 2012 г., эта версия была нацелена на заражение MBR. Другая, более поздняя модификация, которая заражает VBR, была замечена в конце осени 2012 г.
Рис. 6. Две модификации Win32/Gapz, нацеленные на заражения MBR и VBR.
Давайте рассмотрим более раннюю модификацию буткита, которая нацелена на заражение MBR, подробнее. В этом случае, код буткита можно разбить на несколько частей:
● вредоносный MBR;
● код режима ядра и полезная нагрузка, внедряемая в процессы.
Вредоносный код сохраняет свой код режима ядра и полезную нагрузку либо перед самым первым разделом, либо после последнего раздела на жестком диске. Такой подход очень похож на тот, который использовался в бутките Rovnix, за исключением того, что Rovnix заражает VBR.
Что касается буткит части Win32/Gapz, то в ней нет ничего необычного: как только код из вредоносного MBR исполнился, он восстанавливает оригинальный код в памяти и читает следующие секторы жесткого диска, содержащие код для последующего исполнения, на который и передается управление. Код буткита перехватывает обработчик прерывания 0x13, int 13h и отслеживает, таким образом, загрузку ниже перечисленных модулей ОС для установки туда перехватов:
● ntldr (на системах до Windows Vista)
● bootmgr (на системах Vista+)
● winload.exe (на системах Vista+)
Код буткита идентифицирует каждый из вышеперечисленных модулей, используя специальные последовательности байт. Ниже перечислен список функций, которые буткит перехватывает в этих модулях:
Как только вредоносный код обнаруживает, что конкретный модуль читается с жесткого диска, он модифицирует его таким образом, чтобы вернуть себе контроль после того, как процессор переключится в защищенный режим. Буткит устанавливает перехваты на загрузчик ядра ОС: это либо ntldr в устаревших системах до Windows Vista, либо bootmgr в Vista и выше. В случае с bootmgr, он также перехватывает функцию OslArchTransferToKernel в winload.exe.
Рис. 7. Перехватчик функции OslArchTransferToKernel в winload.exe.
Следующий этап, это установка перехвата на функцию IoInitSystem, которая вызывается в процессе инициализации ОС. Она перехватывается вредоносным кодом либо из ntldr, либо из winload.exe, в зависимости от версии ОС.
Рис. 8. Код перехвата, устанавливаемого на функцию IoInitSystem.
После того, как вредоносный код из IoInitSystem был исполнен, буткит восстанавливает модифицированные байты в образе ядра ntoskrnl и передает управление оригинальной IoInitSystem. Перед передачей управления оригинальному коду, буткит перезаписывает адрес возврата в стеке на свою функцию, которая, соответственно, будет исполнена по завершении исполнения IoInitSystem. С помощью такого трюка вредоносный код получает управление после того, как ядро ОС будет инициализировано. Далее вредоносный код считывает остальную свою часть с жесткого диска и создает отдельный системный поток, который исполняет эти инструкции и в завершении возвращает управление ядру. В этой части буткита, которая исполняется в режиме ядра, реализуется руткит-функционал, внедрение полезной нагрузки в процессы и взаимодействие с C&C сервером.
Вредоносный код VBR
Как мы уже упоминали, последняя модификация Win32/Gapz заражает VBR тома, который помечен как активный в MBR (Volume Boot Record — первые сектора тома, в которых прописана служебная информация, а также VBR-код, на который передается управление из MBR и который отвечает за дальнейшую загрузку ОС). Буткит использует оригинальный подход для заражения VBR с последующей передачей управления своему коду. Для того чтобы быть более скрытным и незаметным, он модифицирует только несколько байт оригинальной VBR. Суть такого подхода заключается в том, что он модифицирует значение поля «Hidden Sectors» в поле служебной структуры VBR, при этом оставляя код VBR и код IPL нетронутым! IPL, Initial Program Loader — код, на который передается управление после исполнения кода VBR, он отвечает за поиск загрузчика в рамках файловой системы тома и передает на него управление. В состав VBR включены следующие части:
● Bootstrap-код (VBR-код), отвечающий за загрузку IPL.
● BIOS Parameter Block (BPB) — структура данных, хранящая блок параметров NTFS.
● Текстовые строки, отображаемые пользователю в случае ошибки.
● 0xAA55 — стандартная двухбайтовая сигнатура, маркер служебного сектора.
Рис. 9. Схема первого сектора VBR.
В случае с Win32/Gapz, наиболее интересным местом для анализа является BPB и особенно поле «Hidden Sectors». Это поле содержит количество секторов, предшествующих IPL (т. е. смещение до IPL в секторах, с помощью которого код из VBR определяет, куда передавать управление далее) и хранящихся на NTFS-томе, как показано ниже.
Рис. 10. Структура NTFS-тома.
Таким образом, в процессе загрузки на чистой системе, VBR-код считывает 15 секторов, начиная со смещения, указанного в «Hidden Sectors», и передает туда управление. Этим и пользуется буткит для передачи управления на себя. Он перезаписывает это значение, указывая смещение в секторах до своего вредоносного кода, хранящегося на диске. После заражения том выглядит так:
Рис. 11. Модифицированное буткитом значение «Hidden Sectors» приводит к тому, что код VBR передает управление на код буткита, а не на IPL.
В случае заражения системы, VBR-код вызывает на исполнение код буткита вместо легального IPL. Код буткита, как уже упоминалось, записывается либо перед самым первым разделом диска, либо после последнего. В остальном код буткита, по существу, ничем не отличается от версии с MBR-инфектором.
Вредоносный код режима ядра
Основное предназначение непосредственно той части, которая и называется буткитом, описанной выше, заключается в загрузке вредоносного кода режима ядра или руткита в системное адресное пространство, обходя ограничения, накладываемые ОС для такого привилегированного кода. Мы уже упоминали, что этот загружаемый буткитом код, содержит в себе руткит для скрытия своего присутствия, механизм работы с управляющим сервером C&C, а также полезную нагрузку (payload), которая предназначена для внедрения в процессы.
В отличие от Rovnix, TDL4 и других распространенных буткитов, вредоносный код режима ядра в Win32/Gapz не имеет структуры исполняемого PE-файла. Вместо этого он структурирован особым образом. Код состоит из 12 объединенных между собой блоков, каждый из которых имеет заголовок — структуру, которая хранит служебную информацию о нем. Она имеет следующий вид:
Каждый из блоков реализует определенный функционал: внедрение полезной нагрузки, взаимодействие с C&C серверами, самозащиту и так далее. Функционал кода режима ядра является достаточно сложным и может быть рассмотрен отдельно (выходит за рамки этого поста).
Bootkits vs. Microsoft ELAM
В этой части нашего поста мы хотим остановиться на специальном средстве, которое Microsoft решили использовать для борьбы с различного рода угрозами, особенно, руткитами и буткитами, которые пытаются загрузить себя раньше других драйверов в системе. Средство называется ELAM, Early Launch Anti-Malware Module и поставляется в составе ОС, начиная с Windows 8. По сути ELAM – это драйвер, предоставляемый антивирусным вендором, которому гарантирован приоритет при загрузке драйверов режима ядра. С точки зрения же ядра ОС, ELAM представляет собой API для антивирусных драйверов, а также набор правил, которых такому драйверу следует придерживаться. Одна из главных возможностей этого средства заключается в том, что он гарантированно позволяет AV-драйверу загружаться раньше остальных драйверов в системе и, таким образом, выходить за рамки обычных правил автозагрузки, регламентируемых для остальных драйверов.
Мы отмечаем, что ELAM сам по себе не может быть так эффективен для борьбы с буткитами, поскольку это часть ядра ОС, а буткит получает управление гораздо раньше.
Рис. 12. Мы видим, что буткит может компрометировать систему с активным ELAM, делая его бесполезным инструментом. Поскольку буткит загружается раньше инициализации ОС, он будет уже находиться в памяти на тот момент, когда ELAM получит управление.
В то же время, следует отметить, что ELAM является частью декларируемой Microsoft концепции или схемы «Безопасной загрузки» — Secure Boot. В случае с Secure Boot, программное обеспечение, встроенное в UEFI (такое ПО получает управление как только компьютер начал свою работу) может контролировать целостность и легитимность кода, на который передается управление в процессе выполнения кода, предшествующего выполнению основного кода ОС. Концепция Secure Boot, совместно с новым стандартом UEFI, призвана предотвратить компрометацию критичных структур данных ОС/UEFI со стороны буткитов.
Мастера перевоплощений: охотимся на буткиты
Давайте начнем с небольшой исторической справки.
► В 2013 году Себастьен Качмарек (Sébastien Kaczmarek) из QuarksLab создал PoC-буткит Dreamboot, использующий UEFI для атаки на загрузчик ОС. Его исходный код доступен на GitHub. Следует отметить, что данный буткит работал только при отключенном механизме Secure Boot, и в том же году на конференции BlackHat USA 2013 был представлен доклад «A Tale of One Software Bypass of Windows 8 Secure Boot», в котором авторы описали первый публичный способ обхода этого механизма.
► В 2014 году Рафаль Войтчук (Rafal Wojtczuk) и Кори Калленберг (Corey Kallenberg) опубликовали информацию об уязвимости Darth Venamis в механизме S3 Resume. Это механизм, определяющий продолжение работы компьютера после выхода из состояния сна. В результате исследования выяснилось, что область памяти, в которой хранится S3 BootScript (список команд, проводящих инициализацию устройств после выхода из состояния сна), не защищена от модификации, что приводит к различным уязвимостям. Эта же уязвимость использовалась, предположительно, ЦРУ для установки имплантов. Почитать об этом можно здесь, здесь и здесь.
► В 2015 году Кори Калленберг и еще один исследователь, Ксено Ковах (Xeno Kovah), представили LightEater — руткит, позволяющий получать различную важную информацию (ключи шифрования и прочее) за счёт прямого доступа к физической памяти и постраничного поиска с использованием сигнатур.
► В том же году, после утечки данных из компании HackingTeam, был обнаружен фреймворк Vector-EDK, разработанный для внедрения имплантов в UEFI-based прошивки. Этот же фреймворк использовался для разработки Mosaic Regressor.
► В 2016 году Дмитро Олексюк (Dmytro Oleksiuk) создал PeiBackdoor — первый публично доступный UEFI-руткит, загружаемый на этапе PEI (Pre-EFI Initialization).
► В том же году из-за утечки документов Equation Group (по некоторым источникам, связана с АНБ США) появилась информация о существовании BIOS-модуля BANANABALLOT, загружающего некий имплант для взаимодействия с роутерами CISCO.
► В 2017-м WikiLeaks опубликовали информацию о DerStarke — UEFI-версии бэкдора Triton для macOS.
► В 2018-м компания ESET нашла и проанализировала UEFI-руткит LoJax — первый UEFI-буткит, обнаруженный ИБ-компаниями in the wild.
► В октябре 2020 года Лаборатория Касперского в процессе расследования атаки обнаружила Mosaic Regressor — UEFI-буткит, созданный с использованием инструментов, полученных из утечки данных HackingTeam.
► В декабре 2020-го зафиксирована новая версия TrickBot, которая обладает функциональными возможностями по внедрению кода UEFI. На данный момент нет свидетельств активного внедрения UEFI-имплантов in the wild TrickBot’ом, но сам факт появления подобного функционала говорит о том, что злоумышленники интересуются подобными атаками.
Даже этот неполный список прекрасно демонстрирует, насколько актуальны и опасны атаки, связанные с UEFI. В последние несколько лет количество публично выявленных уязвимостей в прошивках удваивается каждый год, что приводит к явному увеличению интереса со стороны киберпреступников и активному росту количества выявленных таргетированных атак.
Создание стенда с UEFI-буткитом
Mosaic Regressor состоит из нескольких модулей, которые описаны в таблице.