Отключение проверки целостности bootmgr и winload

Метки:  , ,

Зачастую возникают потребности изучения процесса загрузки операционной системы Windows на уровне исходного кода. Ну а тут уж без внесения изменений в код просто не обойтись.. и в этом самом месте нас ждет разочарование. Дело в том, что если вносить изменения в код модулей bootmgr, winload.exe и файлы драйверов, участвующих в процессе начальной загрузки, то процесс запуска операционной системы начинает "вылетать" с ошибками, "валиться" в синий экран и режим восстановления. Логично, ведь мы столкнулись с проверкой целостности bootmgr и winload, которая препятствует модификации исполняемых образов, задействованных в цепочке запуска. Подобный механизм впервые появился в линейке операционных систем Windows начиная с версии Vista и теперь приобрел перманентно-устойчивый вид. Для самописных драйверов разработчики оставили возможность загрузки в тестовом режиме (флаг TESTSIGNING), тем не менее остаются условия, при которых внесение изменений в код компонентов оканчивается отказом в запуске ОС. Исследователям архитектуры Windows этот факт существенно портит настроение, поэтому сегодня мы разберем несколько нестандартный метод отключения проверки целостности bootmgr и winload.

Для 32/64-битных версий Windows Vista/7/8 и далее есть вполне официальный способ отключения проверки проверки целостности драйверов режима загрузки, тем не менее иногда приходится работать с тестовыми (измененными) версиями некоторых загрузочных файлов, в этом случае требуется отключение вообще всех проверяющих механизмов.

Для подавления проверки целостности мы будем патчить код модулей таким образом, чтобы алгоритмы внутренних функций проверки хэшей файлов всегда выполнялись по ветвлению типовой (нормальной) загрузки. В качестве учебного материала статьи будет использована операционная система Windows 7 SP1 Professional RUS x86 в нормальном (legacy, PC/AT-MBR) режиме загрузки. Не смотря на то, что отключение проверки целостности в 32-битной системы имеет меньше смысла нежели в x64-версии, приведенное в данной статье решение является универсальным, поскольку логика работы внутренних функций проверки целостности аналогична (даже для режима загрузки UEFI), за исключением, разумеется, исходного кода.

Перед выполнением нижеприведенных действий не забудьте сделать резервные копии файлов:

  • %SystemRoot%\System32\Boot\Winload.exe;
  • %SystemRoot%\System32\Winload.exe;
  • Bootmgr (находящийся на скрытом системном разделе/разделе EFI);

Итак, нам потребуется:

  • Интерактивный дизассемблер IDA
  • Шестнадцатеричный редактор с возможностью поиска/замены шестнадцатеричных значений (ваш любимый)
  • Утилита bmzip
  • Утилита BOOTMGR Recompiler v2
  • PE-редактор LordPE

Bootmgr

В процессе загрузки операционной системы Windows, после окончания этапов MBR и PBR, управление передается на код менеджера загрузки Bootmgr. Что бы сам менеджер загрузки в случае модификации у нас не "брыкался" разнообразными ошибками контрольных сумм, нам требуется его пропатчить:

  • Для начала нам необходимо получить файл bootmgr со специального "скрытого" системного раздела. Метод описан в этой статье, тем не менее я приведу здесь краткую последовательность действий: запускаем оснастку Управление дисками, выделяем (маркируем) первый раздел диска (размер ~100-300Мб), щелкаем правой кнопкой мыши - выбираем пункт меню Изменить букву диска или путь к диску.. и назначаем литеру.
  • В системе появляется (становится доступен) новый диск. Открываем, настраиваем представление проводника на показ скрытых файлов, папок и дисков, отменяем сокрытие защищенных системных файлов.
  • В корне обнаруживаем сжатый файл Bootmgr.
  • Распаковываем его при помощи консольной утилиты bmzip (ссылка выше):

    bmzip bootmgr bootmgr.exe

    В целевом каталоге обнаруживаем новый только что распакованный файл bootmgr.exe.

  • Дизассемблируем полученный модуль bootmgr.exe при помощи IDA. Обязательно с работоспособной возможностью по выкачиванию символов с сервера Microsoft.
  • В интерфейсе IDA, идем в Options - General - вкладка Disassembly, выставляем значение параметра Number of opcode bytes в 8. Это нужно для отображения в листинге опкодов инструкций.
  • В основном окне дизассемблированного исходного кода откручиваем на начало листинга, ставим курсор в начало, затем жмем Alt+T и вводим в строку поиска ImgpValidateImageHash (можно без учета регистра символов), жмем OK.
  • Для дальнейшего поиска можно использовать комбинацию Ctrl+T. Перемещаясь по исходному коду находим точку входа функции (не путать с вызовами функции call _ImgpValidateImageHash)
  • Найдя таким образом функцию, перемещаемся в конец её кода и видим примерно следующее:

  • Функция ImgpValidateImageHash выполняет проверку контрольной суммы (хэш) загружаемых модулей. Для того, что бы обойти разнообразные проверки собственной целостности и загружаемого в дальнейшем модуля Winload.exe, необходимо заставить функцию возвращать нулевое значение (согласно соглашению о вызовах в регистре eax) в любой случае.
  • На данный момент в приведенном исходном коде мы можем наблюдать сигнатуру для поиска и замены:

    Конкретно в вашем случае она может быть иной, поскольку все зависит от текущей ревизии файла bootmgr;

  • Скачиваем и запускаем шестнадцатеричный редактор. Открываем в нем наш файл bootmgr.exe.
  • Поиском по шестнадцатеричному значению находим сигнатуру. Нужно поменять найденный нами код так, что бы в регистре eax возвращалось значение 0. В оригинале мы видим команду mov eax, edi (опкоды 8B C7), которая выполняет присвоение eax=edi. Давайте заменим её на xor eax, eax (опкоды 33 C0), которая обнуляет регистр eax. Для этого в редакторе байты 8B C7 меняем на 33 C0. Сохраняем изменения, закрываем редактор.
  • Теперь нам необходимо преобразовать образ bootmgr.exe обратно в сжатый bootmgr. Для этого используем утилиту BOOTMGR Recompiler v2 (ссылка выше).
  • Помещаем получившийся сжатый файл bootmgr в корень скрытого раздела (который был у нас подмаплен в систему в начале). Атрибуты на скрытый менять не надо!

Winload.exe

Но это еще не все, поскольку после того, как код менеджера загрузки Bootmgr находится на завершающей стадии исполнения, им подгружается загрузчик следующей стадии - так называемый загрузчик операционной систем под названием Winload.exe. Данный модуль так же имеет привычку проверять целостность ключевых файлов, поэтому нам необходимо обновить и его код тоже. Дабы не описывать несколько раз одно и то же, условимся, что шаги предыдущего раздела актуальны и для текущего.

Метод №1

  1. По вышеописанной методике ищем функцию ImgpValidateImageHash.
  2. В конце функции находим примерно такой вот фрагмент кода:
  3. В шестнадцатеричном редакторе находим сигнатуру и меняем (выделены цветом) четыре байта 8B 44 24 18 на 33 C0 90 90, что будет эквивалентно серии команд:

Метод №2

  1. По вышеописанной методике ищем функцию OslInitializeCodeIntegrity.
  2. Смотрим точку входа функции:
  3. В шестнадцатеричном редакторе находим сигнатуру и меняем (выделены цветом) первые три байта 8B FF 55 на B0 01 C3, что будет эквивалентно серии команд:
Модификацию требуют два файла Winload.exe, находящиеся по путям: %SystemRoot%\System32\ и %SystemRoot%\System32\Boot\. Поэтому после модификации одного файла не забудьте обновить и второй.

Корректировка контрольной суммы файлов

Имеется еще один тонкий момент. Возьмите в привычку, что если вы модифицируете winload.exe или ntoskrnl.exe, или любой драйвер начальной загрузки, то после всех сделанных изменений не забудьте пересчитать и поменять контрольную сумму (поле Checksum заголовка PE). Осуществляется это посредством утилиты LordPE или любого аналогичного редактора PE-модулей. Причина простая: где-то в коде Winload.exe имеется еще одна проверка (которую я пока не смог обнаружить), которая верифицирует контрольную сумму модуля, и при несовпадении уходит на процесс восстановления системы.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *