![]() |
Авторы: aLS и Alfredo
Переводчик: Ex0rcist a.k.a. Heroin Оригинал (EN): www.phrack.org Источник (RU): www.reverse4you.org Persistent BIOS Infection ------[ 0.- Предисловие Уважаемые пользователи, если вы читаете эту статью, мы можем предположить, что вы уже знаете, что такое BIOS и как он работает. Или, по крайней мере, вы имеете общtе представление о том, что делает BIOS, и его значение для нормальной работы компьютера. Основываясь на этом, мы кратко объясним некоторые основные понятия, чтобы ввести в курс дела, а затем мы будем переходить к более актуальным техническим тонкостям. ------[ 1.- Введение На протяжении многих лет многое было сказано по этой теме. Но кроме старого вируса Chernobyl, который просто обнулял BIOS, если твоя материнская плата была одной из поддерживаемых, или для некоторых изменений для моддинга, такими как работа Pinczakko, мы не в состоянии найти общедоступные разработки, характерные для определенного класса вредоносных BIOS инфекций. Люди, как правило, думают, что эта тема раскурена вдоль и поперек, стара и имеются готовые разработки. Иногда даже путают с MBR вирусами. Мы намерены показать, что такой тип атаки возможен и может быть очень надежным и стойким руткитом, находясь в прошивке BIOS и оставаясь невидимой для ОС инфекцией. В этой статье мы покажем универсальный метод, чтобы внедрить код в BIOS прошивки. Этот метод позволит нам встроить наш собственный код в BIOS прошивки так, что он будет выполнен непосредственно перед загрузкой операционной системы. Мы также продемонстрируем, как с контролем жесткого диска или просто путем изменения конфиденциальных данных ОС в Linux box, развертывать полностью функциональный код непосредственно в процесс Windows. ---[ 1.1 - Назначение статьи Основной идеей данной работы является показать то, как BIOS прошивки можно модифицировать и использовать как метод сохранения контроля после успешного рутанья. Ну, начнем потихонечку и постепенно будем рассматривать возникающие вопросы, разделив статью в двух основных направлениях: - Модификации VMWare's (Phoenix) BIOS - Рельные модификации BIOS В каждом разделе мы расскажем основные моменты, чтобы показать, как провести атаку, а затем перейдем непосредственно к рассмотрению кода. ------[ 2.- Основы BIOS ---[2.1 - Введение в BIOS Из википедии: Цитата:
Цитата:
Еще в 80-х BIOS прошивки загружались в ПЗУ или ППЗУ чипы, которые не могли быть изменены, но в настоящее время эта прошивка хранится в EEPROM (электрически стираемая программируемая Read-Only память). Этот вид памяти разрешает пользователю перепрошивать его, позволяя поставщику создавать обновления встроенного программного обеспечения для того чтобы исправить ошибки, добавить поддержку нового железа и функциональности. ---[2.1.2 - Как это работает? BIOS имеет очень важное значение в работе компьютера. Он должен быть всегда доступен, как первая инструкция, выполняемая центральным процессором, при его включении. Вот почему он хранится в ROM. Первый модуль BIOS называется загрузочный блок (Bootblock) и отвечает за POST (Power-On Self-Test) и аварийную загрузочную процедуру. POST является общим термином предварительной загрузки для компьютера, маршрутизатора или принтера. Он должен протестировать и инициализировать почти все аппаратные компоненты в системе, чтобы убедиться, что все работает правильно. Современный BIOS имеет модульную структуру, что означает, что есть несколько модулей, интегрированных в одну прошивку, каждый из которых отвечает за конкретные задачи, от аппаратной инициализации до безопасности. Каждый модуль является сжатым, поэтому есть точный алгоритм декомпрессии, отвечающий за декомпрессию и проверку других модулей, которые впоследствии будут выполняться. После декомпрессии, определяются другие аппаратные средства, такие как PCI ROM (если необходимо), и в конце концов, в поисках загрузчика, читается 0 сектор жесткого диска (MBR), чтобы начать загрузку операционной системы. ---[2.2 - Файловая структура прошивки Как мы упоминали ранее, прошивка BIOS имеет модульную структуру. При хранении в нормальном файле, он состоит из нескольких LZH сжатых модулей, каждый из которых содержит 8 бит контрольной суммы. Однако, не все модули являются сжатыми. Несколько модулей, такие как загрузочный блок (Bootblock) и алгоритм декомпрессии, явно не сжаты, потому что они являются фундаментальной частью процесса загрузки и должны выполнять декомпрессию других модулей. Далее мы увидим, почему для нас это так удобно. Мы имеем выход Phnxdeco (доступны в Debian репозитории), открытый исходный код для разбора и анализа прошивки Phoenix BIOS ROM (то, что собираемся извлечь в 3.1.1): Код:
Code:---[2.3 - Обновление Программное обеспечение BIOS не так уж сильно отличается от любого другого программного обеспечения. Это относится к ошибкам, которые можно встретить и в другом программном обеспечении. С новыми версиями выходит поддержка нового железа, дополнения, исправление ошибок и т. д. Но процесс обновления может быть очень опасным на реальной машине. BIOS является одним из основных компонентов компьютера. Это первая часть кода, выполняемая при включении машины. Именно поэтому мы должны быть очень осторожны, когда делаем такого рода вещи. Неудачное обновление BIOS может привести к зависанию машины. И ты соснешь тунца. Вот почему так важно иметь такую платформу для тестирования как VMWare. По крайней мере на первое время, потому что, как мы увидим далее, есть много различий между VMware и реальным железом. ------[ 3 .- Заражение BIOS --- [3.0 - Первичная настройка --- [3.1 - Модификация VMware (Phoenix) BIOS Во-первых, мы должны получить действительную прошивку VMWARE BIOS для работы. Для того чтобы читать EEPROM (где хранится прошивка BIOS) нам необходимо запустить код в режиме отладки ядра, чтобы отправлять и получать данные непосредственно в южный мост через порты ввода-вывода. Для этого нам также необходимо знать некоторые конкретные данные о текущем оборудовании. Эти данные обычно предоставляются производителем. Более того, почти все поставщики плат предоставляют некоторые инструменты для обновления BIOS, и очень часто они имеют возможность резервного копирования существующей прошивки. В VMWare мы не можем использовать эти инструменты, потому что эмулируемое железо не имеет ту же функциональность, как реальное оборудование. В этом есть смысл... Почему бы не обновить VMWare BIOS изнутри...? ---[3.1.1 - Дамп VMWare BIOS Для начала было бы неплохо иметь встроенный GDB сервер, который предлагает VMWare. Он позволяет нам производить отладку и понимать, что происходит. Таким образом, в целях исправления и изменения некоторых маленьких кусков кода, чтобы начать тестирование, мы использовали некоторые случайные массивы байтов в качестве шаблонов для поиска BIOS в памяти.П роделывая это, мы обнаружили, что в VMware-VMX существует основная исполняемая VMware секция, весом почти 256кб, которая называется .bios440 (которая в нашей версии VMware находится между смещением в файле 0x6276c7-0x65B994). Она содержит всю прошивку BIOS, точно так же, как и в обычном файле, готовом к выполнению.Вы можете использовать objdump для того чтобы видеть разделы файла: Код:
Code:Код:
Code:Но Существуют более простые способы решения этой задачи. Мы собираемся изменить его несколько раз, и он не будет работать все время... Чем проще, тем лучше. ---[3.1.2 - Настройка VMWARE для загрузки альтернативного BIOS Мы поняли, что VMWare предлагает очень практичный путь, чтобы пользователь мог использовать конкретный файл прошивки BIOS прямо через файл конфигурации .VMX. Существует не очень известный тег, который называется "bios440.filename" и он позволяет избегать использование встроенного в VMWare BIOS и вместо этого позволяет нам указать BIOS файл, который нужно использовать. Добавь в файл .VMX следующий код: Код:
Code:Код:
Code:Код:
Code:Как мы уже говорили, некоторые из модулей сжаты LZH. Есть несколько доступных средств для извлечения и распаковки каждого отдельного модуля файла прошивки. Наиболее часто используемыми являются Phnxdeco и Awardeco (два отличных Linux GPL инструмента) совместно с Phoenix BIOS Editor и Award BIOS Editor (не GPL инструменты для Windows). Если хочешь, можешь использовать Phoenix BIOS Editor в Linux с помощью wine. Он будет извлекать все модули в каталог/временный каталог внутри Phoenix BIOS Editor, которые готовы к открытию привычным тебе дизассемблером. Хорошей возможностью Phoenix BIOS Editor является то, что он также может восстанавливать основной файл прошивки. Он может сжимать и встраивать различные распакованные модули, чтобы прошивка была в неизменном виде. Учти, что эта функция была сделана для последних версий Phoenix BIOS и он пропускает проверку контрольной суммы, поэтому нам придется делать это вручную (мы увидим это в 3.2.2.1) Некоторые из этих задач выполняются отдельными инструментами, которые могут быть вызваны непосредственно из командной строки, что является очень удобным, для того чтобы автоматизировать процесс для исследования простых скриптов. ---[3.1.4 - Модификации Итак, вот мы и приблизились к самому интересному. У нас есть все распакованные модули, и возможность их изменения, а затем и восстановления в полностью рабочий BIOS Flash Update. Первая фраза, которая приходит на ум это, "где патчить?". Мы можем поставить "ловушку" на выполнение нашего кода почти в любом месте. Но мы должны все продумать, прежде чем решить о том, в каком месте патчить. В начале мы думали о подключении к первой инструкции, которую выполняет процессор, а именно 0xF000: FFF0. Это казалось самым лучшим вариантом, потому что эта команда всегда в точном месте, и ее легко найти. Но мы должны принимать во внимание сам процесс выполнения. Чтобы наш код работал, все распознавание оборудования должно производится нами (DRAM, северный мост, кэш, PCI и т.д.) Например, если мы хотим иметь доступ к жестким дискам, мы должны быть уверены, что, при выполнении нашего кода, мы уже имеем доступ к жесткому диску. По этой причине мы выбрали для подключения алгоритм декомпрессии. Также это удобно потому, что он не меняется от версии к версии. Кроме того, его очень легко найти путем поиска по шаблону. Он не сжат и вызывается много раз в течение последовательной загрузки BIOS, что дает нам возможность проверить, все ли необходимые службы доступны и приступить к реальным вещам. Далее мы имеем дамп скрипта для быстрого извлечения прошивки модулей, сбора данных, их внедрения, и компиляции измененного файла прошивки. PREPARE.EXE и CATENATE.EXE являются собственными инструменты создания прошивки Phoenix, которые можно найти в Phoenix BIOS Editor, а также в комплекте с другими инструментами. В более поздних версиях скрипта эти инструменты не нужны (как показано в 3.2.2.1). [CODE] Code: #!/usr/bin/python import os,struct #--------------------------- Decomp processing ------------------------------ #assemble the whole code to inject os.system('nasm ./decomphook.asm') decomphook = open('decomphook','rb').read() print "Leido hook: %d bytes" % len(decomphook) minihook = '\x9a\x40\x04\x3b\x66\x90' # call near +0x430 #Load the decompression rom decorom = open('DECOMPC0.ROM.orig','rb').read() #Add the hook hookoffset=0x23 decorom = decorom[:hookoffset]+minihook+decorom[len(minihook)+hookoffset:] #Add the shellcode decorom+="\x90"*100+decomphook decorom=decorom+'\x90'*10 #recalculate the ROM size decorom=decorom[:0xf]+struct.pack(" |
---[3.1.5.1 - Готовый сигнал
В VMWare мы видели, что когда наша подгрузка на второй стадии, и IVT уже инициализирован, у нас есть все, что нам нужно. Исходя из этого мы решили использовать IVT инициализацию, как сигнал готовности. Это очень просто, потому что всегда отображается на 0000:0000. Каждый раз, когда шеллкод запускается на выполнение, проверяем, инициализируется ли IVT с правильными указателями, выполняется ли шеллкод, если нет, то возвращается, ничего не делая. ---[3.1.5.1 - The Real stuff Что же мы будем делать теперь, когда у нас есть исполняемый код, и мы знаем, что у нас есть все сервисы? Мы не можем взаимодействовать с ОС отсюда. В этот момент операционная система просто массив символов, находящийся на диске. Погоди! Мы же имеем доступ к диску через Int 13h (низкоуровневая служба). Мы можем изменить его в любое время, какое нам нужно! Оке, давай попробуем это проделать. При реальной реализации вредоносного кода тебе нужно накодить некий основной драйвер, чтобы корректно различать файловые системы, по крайней мере FAT и NTFS (возможно также использование GRUB или LILO). Для этой статьи, в доказательство концепции, мы будем использовать Int 13h для последовательного чтения диска в нестандартном режиме. Мы будем реализовывать все это дело через (_о_), но как мы говорили ранее, в общем случае, изменение, добавление и удаление любых файлов на диске позволет злоумышленнику изменять модули драйверов, заражать файлы, отключать антивирус или антируткиты и т.д. Используем шеллкод, с помощью которого мы просмотрим весь диск в соответствии с маской: "root:$", чтобы найти запись /etc/passwd. Затем мы заменим root хэш нашим собственным хэшем, установив пароль "root" для суперпользователя. Код:
Code:Код:
Code:VMWare - отлично подходит для исследования BIOS и разработоки платформы. Но для завершения этого исследования, мы должны атаковать реальную систему. Для этого мы использовали обычную материнскую плату (Asus A7V8X-MX) очень популярной версией Award-Phoenix 6.00 PG BIOS. ---[3.2.1 - Дамп прошивки BIOS Флэш-микросхемы отлично совместимы, и даже взаимозаменяемы. Но они подключаются к материнской плате по-разному (PCI, ISA bridge, и т.д.), что, в общем случае, делает чтение довольно сложной адачей. Как же мы сможем сделать руткит, если мы даже не можем найти способ надежно читать память? Конечно, одним из решений может являться Flash reader, но на данном этапе мы его не имеем, и это не вариант, если ты хочешь удаленно заразить BIOS без физического доступа. Поэтому мы начали искать программные альтернативы. Первый инструмент, который мы нашли, работал неплохо. Это утилита FlashROM от проекта coreboot с открытым исходным кодом, см. [COREBOOT] (также имеется в Debian репозиториях). Она содержит обширную базу данных чипов и обладает read/write методами. Мы обнаружили, что она почти всегда работает, даже если придется вручную указать модель IC, потому что утилита не всегда распознает их автоматически. Код:
Code:Мы также использовали FlashROM в общем случае для загрузки измененного BIOS на материнскую плату. ---[3.2.2 - Модификация После того как мы получили образ BIOS, мы можем начать процесс вставки вредоносного кода. При изменении реального BIOS'a, в частности Award / Phoenix BIOS'a, мы столкнулись с некоторыми большими проблемами: 1) отсутствие документации BIOS структуры 2) отсутствие инструментов упаковки / распаковки 3) отсутствие способа отладки оборудования. Есть множество бесплатных инструментов для управления BIOS, но как всегда получается с собственными разработками форматов, мы не могли найти инструмент, который работал бы именно с нашей прошивкой. Мы можем использовать утилиты Linux awardeco и phnxdeco в качестве отправной точки, но они часто работают со сбоями на современных BIOS версиях. Наш план для получения исполняемого кода таков: 1) мы должны сделать произвольные изменения (мы должны знать позиции контрольной суммы и алгоритмы) 2) основной код должен быть вставлен в общей, легкодоступной части BIOS. 3) после выполнения кода, может быть вставлен Shellcode. ---[3.2.2.0 - Black Screen of Death Ты должен понимать, что сломаешь много BIOS чипов, проделывая эти трюки. Но большинство BIOS имеют механизм безопасности для восстановления поврежденной прошивки. RTFM (читаймануалы по материнской плате). Если это не поможет, ты можешь использовать чип для "горячей замены": ты грузишься с рабочего чипа, затем делаешь его "горячую замену" на поврежденный, и перепрошиваешь. Конечно, для этой техники у тебя должен быть резервный рабочий BIOS. --- [3.2.2.1 - Изменение бита в единицу времени Наши первые попытки были неудачными и почти всегда система не загружалась. В основном мы не обращали внимания, сколько контрольных сумм имеет BIOS, но ты должен будешь пропатчить каждую или лицезреть ошибку "BIOS CHECKSUM ERROR" на черном экране смерти. Черный экран смерти дает нам подсказку, он говорит: "контрольная сумма". Скорее всего он должен быть каким-то дополнением, сравневаемым с числом. И этот вид проверки можно легко обойти, внедряя значение в определенное место, которое будет являться "дополнением". Разве это не весомая причина для создания CRC? Оказывается, что все контрольные суммы были 8-битными, и, коснувшись только одного байта в конце шеллкода, все контрольные суммы были правильными. Можно написать очень простой алгоритм на вложения внутри этого Python скрипта: Код:
Code:---[3.2.2.1 - Внедрение кода Вредоносный код находится все в том же месте: блок декомпрессора. Мы также переходим на то же место, что и в инъекции кода VMware: в конце блока декомпрессора в целом было достаточно места для того чтобы сделать довольно приличный первый шеллкод. Подсказка: при поиске "= Award Decompression Bios =" в BIOS Phoenix, имеем блок с пометкой "DECOMPCODE" (с использованием phnxdeco или любого другого инструмента). Техника почти никогда не меняется. Есть несколько пунктов, которые ты должен сделать, чтобы убедиться, что подключился правильно. Во-первых, включить основной вредоносный код, который перебрасывает вперед, а затем возвращает. Задем изменить его, чтобы привести к бесконечному циклу (у нас нет отладчика, поэтому мы должны использовать эту ужасную технику). Если ты можешь контролировать правильную загрузку компьютера и его блокировку, Graz! Теперь у тебя есть код, скрыто выполняющийся из BIOS. ---[3.2.3 - Подгрузка Теперь у нас есть контроль над BIOS. Ты откапываешь в своей голове навык 16-битного шеллкодинга и пытаешься заюзать 10h INT для вывода "I Pwned J00!" на экран, а затем приступить к использованию INT 13h, чтобы писать на жесткий диск. Не беги вперед паровоза, иначе тебя поглотит черный экран эпик фэйла. Это потому, что у тебя все еще нет полного контроля над BIOS. Для начала впомни, как мы это делали с кодом на VMware: мы исполняли код несколько раз во время процесса загрузки. В первый момент времени диск не вращается, экран по-прежнему выключен и, что самое удивительное, прерывание векторной таблицы не инициализировано. Звучит круто, но на самом деле это большая проблема. Ты не можешь производить запись на диск, если он не вращается, но ты можешь использовать прерывание, если IVT не инициализирован. Тебе следует подождать. Но как мы узнаем, когда для подойдет время для выполнения? Нам опять потребуется некий ready-to-go signal (сигнал готовности). ---[3.2.3.1 - Сигнал готовности В VMware, мы использовали содержание IVT как сигнал готовности. Шеллкод проверял, готов ли IVT, путем получения от него правильных значений. Это было очень легко, потому что в реальном режиме IVT всегда находится на ожном и том же месте (0000:0000 легко запомнить, кстати). Этот метод - полный отстой, потому что реально ты из этого больше ничего не извлечешь. Указатели на IVT все время отличаются, даже между версиями одного и того же производителя BIOS. Нам необходима лучшая, превосходящая "работу-на-другом-компьютере-отличном-от-моего" техника. Короче говоря, вот решение, и оно прекрасно работает: Код:
Code:Остальное уже история. Ты можешь использовать INT 13h с LBA для проверки готовности диска, и если он готов, то вставить disk-stage rootkit или SMBIOS руткит (см. [PHRACK65]), или BluePill, или I-Love-You вирус, да и вообще, что тебе угодно. Твой код теперь бессмертен. Кстати, вот второй шеллкод: Код:
Code: |
------[ 4.- BIOS32 (Прямая инфекция ядра)
Теперь у тебя есть BIOS руткит, который выполняется в BIOS. Но находясь в BIOS, он просто сосет с точки зрения атакующего. В идеале нам нужен контроль над ядром операционной системы. Вот почему ты должен аплоаднуть шеллкод на жесткий диск или сделать SMBIOS-руткит. Но что делать, если жесткий диск зашифрован? Или если машина не имеет жесткого диска и грузится по сети? Не ссы, потому что этот раздел именно для таких случаев. Есть заблуждение, что BIOS не используется после загрузки. Это неправда. ОС обращается к BIOS по многим причинам, как, например, установка видеорежимов (Int 10h) или вызов BIOS-32. Что такое BIOS32? Используя поиск Google, мы пришли к выводу, что это скрытая служба BIOS, которая предоставляет информацию о других сервисах BIOS современным 32-разрядным операционным системам. Вы можете обратиться к [BIOS32SDP] для получения более детальной информации. Важно то, что многие операционные системы обращаются к нему. И единственным требованием, чтобы подменить службу BIOS32, является то, что Вам необходимо сделать заголовок BIOS32 где-то от E000:0000 до F000:FFFF области памяти. Структура заголовка: Код:
Code:[CODE] Code: arch/x86/pci/pcibios.c,check_pcibios() ... if ((pcibios_entry = bios32_service(PCI_SERVICE))) { pci_indirect.address = pcibios_entry + PAGE_OFFSET; local_irq_save(flags); __asm__( "lcall *(%%edi); cld\n\t" |
| Время: 11:21 |