Модификация UEFI BIOS, часть первая: знакомство с UEFITool

в 1:51, , рубрики: Без рубрики

Прикрываясь полумифическими «безопасностью» и «защитой простого пользователя от буткитов» производители UEFI все сильнее закручивают гайки с каждым новым поколением своих продуктов. При этом поддержка предыдущих поколений быстро сходит на нет, и их пользователям ничего не остается, кроме как брать эту самую поддержку в свои руки. Конечно, при отсутствии исходного кода вносить какие-то изменения довольно сложно, но и без него можно сделать многое.
В своих предыдущих статьях об UEFI я планировал описать различные полезные модификации, которые помогают преодолеть некоторые заложенные производителями ограничения, но тогда до них руки не дошли, зато теперь — самое время.
В первой части этой статьи я опишу работу с написанным мной инструментом для модификации образов UEFI, а вторая будет посвящена самим модификациям.

Вступление, отказ от ответственности

Прошивка UEFI BIOS на современных платах, несмотря на наличие различных технологий вроде USB BIOS Flashback, Dual BIOS, Flash Recovery и т.п. — все равно лотерея. Прошивка же модифицированных образов — лотерея вдвойне.
Именно поэтому я прошу до начала любых экспериментов с прошивкой сделать при помощи аппаратного SPI-программатора полный дамп содержимого микросхемы, иначе восстановление после неудачной прошивки (а она рано или поздно случится) будет долгим, дорогим и болезненным.
SPI-программатор в данный момент может быть собран в домашних условиях из чего угодно, от пары резисторов и конденсаторов (SPIPGM) до Arduino или Raspberry Pi. Мой вариант дешевого и быстрого SPI-программатора описан здесь. Любителям вытравить пару-тройку плат советую обратить внимание на этот проект, а почитателям устройств «все-в-одном» — на этот.
Далее по тексту я полагаю, что у вас есть программатор, возможность восстановления после сбоя прошивки и готовность к экспериментам. Безумству храбрых, конечно, тоже можно петь песни, но не говорите потом, что я не предупреждал.
Традиционно, все, что вы тут сейчас прочитаете, написано в образовательных целях, автор не несет ответственности за возможную порчу вашего оборудования, недополученную прибыль, потерю времени и веры в человечество, вы пользуетесь предоставленным софтом на свой страх и риск и так далее.

UEFITool

Устав от ограничений существующих утилит для работы с образами UEFI (ну и пораженный синдромом NIH в самое сердце), я написал кроссплатформенную утилиту с открытым исходным кодом — UEFITool.
Это редактор образов UEFI, написан на C++Qt, распространяется под лицензией BSD, готовые сборки выкладываются сюда.
Проект находится в активной разработке, поэтому код не блещет красотой и баги нет-нет, да попадаются. Если вдруг наткнетесь — буду рад репортам.
Для нормальной работы с утилитой стоит прочитать предыдущие статьи о структуре образа UEFI, иначе непонятно будет, что вообще происходит, но я постараюсь все же пояснить некоторые моменты. Будем считать, что это заготовка для будущей документации.
В качестве примеров в обеих частях статьи я буду использовать полные дампы с Zotac Z77-ITX WiFi (AMI Aptio4) и Dell Vostro 3360 (Phoenix SCT 2.3). К сожалению, у меня нет тестового стенда на платформе Insyde H2O, поэтому рассказать о ней мне нечего. Возможно, Falseclock знает о них немного больше.
С точки зрения UEFITool'а разницы между образами UEFI разных производителей практически нет, поэтому я остановлюсь на ней при описании патчей.
Итак, запускаем UEFITool, открываем образ (Ctrl+O) и видим примерно такое:
Модификация UEFI BIOS, часть первая: знакомство с UEFITool
В левой части окна отображается структура открытого образа в виде дерева, справа — информация о выбранном элементе дерева, снизу — сообщения, указывающие на ошибки в формате файла, в данном случае — использование разработчиками Phoenix секций с типом 0xF0, назначение которых не описано в спецификации UEFI PI. Двойной щелчок по сообщению раскроет дерево так, чтобы был виден либо на сам элемент, который это сообщение вызвал, либо его родительский элемент. В это же окно выводятся результаты поиска, который можно вызвать нажатием Ctrl+F (оба варианта одной картинкой):
Модификация UEFI BIOS, часть первая: знакомство с UEFITool
Здесь следует немного пояснить терминологию. Практически все структурные элементы в образе UEFI имеют заголовок, в котором хранятся служебные данные вроде GUID, атрибутов, контрольных сумм и т.п., и тело — в нем хранятся собственно данные. Текст же в заголовках не хранится, поэтому для него такой выбор не нужен.
На первом уровне дерева находятся Flash-регионы, в данном случае это Descriptor, ME и BIOS:
Модификация UEFI BIOS, часть первая: знакомство с UEFITool
При выборе региона Descriptor можно узнать настройки доступа к регионам, в данном случае доступ полный, но такие настройки встречаются очень редко. Intel рекомендует производителям оборудования закрывать доступ к региону МЕ на чтение/запись и региону Descriptor на запись, именно поэтому на большинстве плат встроенными средствами полный дамп снять без «танцев с бубном» практически невозможно. При выборе региона ME можно узнать версию ME firmware, если же она не отображается — это не к добру и такой образ лучше не шить.
Перейдем еще на уровень ниже, к содержимому региона BIOS:
Модификация UEFI BIOS, часть первая: знакомство с UEFITool
На этом уровне могут встречаться два типа элементов: тома и свободное место. Свободное в данном случае — не обязательно пустое, к примеру, в этом образе в самом начале Padding'а хранится прошивка EC.
Тома делятся на обыкновенные (формат файловой системы известен), загрузочные (формат ФС известен, содержат Security Core, изменять стоит с особой осторожностью) и неизвестные (либо неизвестен формат ФС, либо разбор еще не реализован). В нашем случае первый том после свободного пространства в начале — обычный, затем два неизвестных (на самом деле, в первом хранится NVRAM, а во втором — ключи и БД для SecureBoot, но программе я это пока еще не объяснил), последний том является загрузочным.
Откроем теперь обычный том, в данном случае в нем хранятся файлы, загружаемые в фазе DXE.
Модификация UEFI BIOS, часть первая: знакомство с UEFITool
Такая структура (основной том внутри сжатой секции) используется довольно часто, она позволяет сэкономить приличное количество места в микросхеме. Есть еще вариант сжимать не весь том целиком, а каждый файл по отдельности — это несколько менее экономно в плане места, зато стартует такой UEFI BIOS быстрее, т.к. нет смысла распаковывать файлы, к которым не было обращений.
Теперь заглянем внутрь файла:
Модификация UEFI BIOS, часть первая: знакомство с UEFITool
Все данные в нем хранятся внутри GUID-defined-секции (в заголовке таких секций обычно хранится ЭЦП или контрольная сумма, в данном случае — 4 байта, похожие на КС, которую, однако, никто не проверяет), и делятся на 4 секции: образ PE32 — собственно исполняемый файл в формате PE/COFF, секция зависимостей DXE — определяет порядок загрузки DXE-драйверов, секция UI — в ней хранится текст «SystemCapsuleRt.efi» в формате Unicode и неизвестная секция типа 0xF0 (скорее всего, её содержимое каким-то образом связано с вышеупомянутой КС).
Все это хорошо, конечно, но редактирования пока не видно. Не беда, вызываем для любого элемента контекстное меню, в котором видно, что с этим элементом можно сделать.
Модификация UEFI BIOS, часть первая: знакомство с UEFITool
А сделать можно следующее:

  • сохранить элемент в файл либо целиком (Extract as is), либо только данные, без заголовков (Extract body)
  • пересобрать элемент (Rebuild), в этом случае при сохранении измененного образа для него (и всех его родительских элементов) будут пересчитаны размеры, контрольные суммы, исправлено выравнивание, т.е. структура образа будет приведена в соответствие со спецификацией UEFI PI
  • вставить элемент из файла, либо перед выбранным (Insert before), либо после (Insert after), либо внутрь него (Insert into, в данном случае внутрь PE32-секции ничего вставить не получится)
  • заменить элемент на другой элемент из файла, либо целиком (Replace as is), либо только его тело (Replace body)

Последнее действие является наиболее полезным, т.к. позволяет произвести модификацию какой-либо части UEFI, не затрагивая при этом структуры всего образа.

Пример использования

Рассмотрим в качестве примера полезную для пользователей MacOS X на ПК модификацию: обход установки бита LOCK (0x0F) в регистре MSR_PMG_CST_CONFIG_CONTROL (0xE2). Бит этот устанавливается DXE-драйвером PowerManagement, чтобы ОС не могла управлять множителем CPU путем записи в этот регистр. Для Windows и Linux это не большая проблема, а вот MacOS X не может стерпеть от UEFI такой наглости. Можно, конечно, пропатчить драйвер AICPM.kext (в 10.8) или ядро (в 10.9), но лучше пропатчить DXE-драйвер и не бояться, что очередное автоматическое обновление сломает загрузку. Патч этот нужен только системам на базе процессоров Intel SandyBridge, IvyBridge и Haswell и их *-E вариантов и делается так:

  1. Открываем свой дамп в UEFITool, очищаем Messages нажатием Ctrl+Backspace, чтобы не мешали
  2. Открываем поиск, выбираем Hex-pattern, Body only, ищем строку «75080FBAE80F»
    Модификация UEFI BIOS, часть первая: знакомство с UEFITool
  3. Делаем двойной щелчок на сообщении о том, что строка найдена, сохраняем тело указанного элемента в файл
    Модификация UEFI BIOS, часть первая: знакомство с UEFITool
  4. Исправляем в Hex-редакторе «75080FBAE80F» на «EB080FBAE80F» (JE становится JMP), сохраняем изменения
    Модификация UEFI BIOS, часть первая: знакомство с UEFITool
  5. Заменяем содержимое выбранного элемента на измененное, старый элемент будет помечен на удаление (Remove), новый — на замену (Replace), все родительские элементы до корня — на перестроение (Rebuild)
    Модификация UEFI BIOS, часть первая: знакомство с UEFITool
    Модификация UEFI BIOS, часть первая: знакомство с UEFITool
  6. Сохраняем измененный образ (Ctrl+S), если сохранение прошло успешно, будет выдан запрос на открытие только что сохраненного образа, если нет — сообщение об ошибке

Прошиваем полученный образ тем же SPI-программатором, которым он был сделан, и получаем отсутствие паники ядра при загрузке MacOS X.

Подробности, другие модификации, заключение

Если вам интересно, откуда взялся магический паттерн «75080FBAE80F» и на какие еще патчи стоит обратить внимание — читайте вторую часть этой статьи, которая будет опубликована немного позже. В ней я постараюсь подготовить побольше примеров в формате «что за модификация, зачем нужна, как сделать, кем и как была найдена», не углубляясь каждый раз в то, как именно вынуть подлежащий модификации элемент и как вставить его обратно.
Надеюсь, что статья не показалась слишком скучной и нудной. Если у вас есть вопросы и предложения — буду рад выслушать и ответить по мере сил. Баг-репортам буду рад еще больше. Спасибо заранее и удачных прошивок.

P.S. Уважаемая администрация и лично НЛО, сделайте для таких вот постов хаб UEFI, пожалуйста.

Автор: CodeRush

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js