Гипервизор производства корпорации Microsoft, как и любая другая программа, создан людьми, а значит, содержит определенное количество ошибок. Поиск этих ошибок — занятие не только увлекательное, но и полезное: во‑первых, Microsoft располагает собственной программой Bug Bounty (о ее особенностях я расскажу чуть ниже), а во‑вторых… Во‑вторых, знания об уязвимостях и недокументированных возможностях приложений ценны сами по себе. В сегодняшней статье мы рассмотрим принципы отладки гипервизора Hyper-V и разберемся в его особенностях.
Гипервизор компании Microsoft используется в большом числе компонентов Windows и, как любой сложный продукт, не лишен допущенных при разработке ошибок. Число уязвимостей, найденных в этом продукте только в 2020 году, составило 21.
Для Hyper-V Microsoft предлагает отдельную программу баг‑баунти, размер выплат которой может достигать 250 тысяч долларов. Однако стоит упомянуть, что Microsoft не работает со странами, которые находятся в санкционном списке США. Россия формально присутствует в этом списке, поэтому следует проявлять осмотрительность, когда отправляешь информацию об уязвимостях в Microsoft, если ты еще ни разу не получал вознаграждение напрямую от вендора. Лучше воспользоваться услугами посредника, иначе ты можешь столкнуться с тем, что обнаруженная тобою уязвимость вдруг одновременно будет найдена другой компанией или исследователем. И неважно, что уязвимость оставалась в продукте несколько лет (этот вариант был проверен на практике).
- Отладка гипервизора Hyper-V
- Отладка через COM-порт
- Отладка по сети
- Отладка с использованием встроенных возможностей vmwp.exe
- Отладка через протокол GDB
- Отладка эмулятора Windows 10X
- Отладка Hyper-V c помощью подмененного загрузчика
- Отладка secure kernel
- Отладка с помощью Radare2
- Radare2 и интерфейс dbgeng.dll
- Radare2 и встроенный протокол
- Cutter
- QEMU
- Ghidra + плагин ret-sync
- Загрузка гипервизора
- Поиск символьной информации
- Утилиты
- Гипервызовы
- Вывод
Отладка гипервизора Hyper-V
Чтобы искать уязвимости в Hyper-V, нужно владеть методами отладки этого гипервизора. Актуальные способы отладки и будут темой сегодняшней статьи. Для этих целей можно использовать эмуляторы, поддерживающие вложенную виртуализацию (такие как VMware Workstation или сам Hyper-V), либо обычный компьютер или ноутбук.
Термины
- Гипервизор — компонент Hyper-V, отвечающий за функционирование подсистемы аппаратной виртуализации процессора ( hvix64.<wbr />exe — Intel, hvax64.<wbr />exe — AMD, hvaa64.<wbr />exe — ARM). В статье рассматривается гипервизор для процессоров Intel.
- Гипервызов (hypercall) — вызов заданной функции в гипервизоре с помощью инструкции vmcall\\<wbr />vmmcall\\<wbr />hvc (в зависимости от производителя процессора);
- root-раздел — Windows Server 2019 с включенным компонентом Hyper-V;
- гостевой раздел (виртуальная машина, ВМ) — операционная система, запущенная в системе виртуализации Hyper-V;
- VMCS (virtual-machine control structure) — структура, определяющая логику работы гипервизора;
- VMX root — режим, в котором работает гипервизор;
- VMX non-root — режим, в котором работает операционная система и обслуживаемое ею прикладное программное обеспечение;
- VM exit — переход из VMX non-root в VMX root при выполнении инструкций или условий, заданных в VMCS или заложенных непосредственно в логику работы процессора.
Отладка через COM-порт
Hyper-V состоит из нескольких компонентов, краткое описание его структуры можно найти в документации. Для отладки компонентов Hyper-V ты можешь использовать WinDbg либо другой отладчик пользовательского режима или режима ядра, однако для подключения непосредственно к гипервизору необходимо выполнить несколько дополнительных шагов, чтобы настроить рутовый раздел.
Для отладки гипервизора Microsoft разработала специальное расширение WinDbg hvexts.<wbr />dll, которое, к сожалению, не входит в дистрибутив и доступно только партнерам Microsoft (поскольку этому расширению требуются символы для модуля гипервизора, которые Microsoft не предоставляет). Также в каталоге winxp, находящемся в папке WinDbg, есть расширение nvkd.<wbr />dll, которое предназначено для отладки расширений виртуального коммутатора Hyper-V.
Файл справки WinDbg содержит описание отладки гипервизора через COM-порт (отладка Hyper-V через нуль‑модемное кабельное соединение в файле debugger.<wbr />chm), подразумевающее наличие двух физических машин. Также гипервизор можно отладить, если запустить его в любом поддерживаемом программном обеспечении виртуализации. Далее мы будем использовать VMware Workstation.
Для начала нужно установить Windows Server 2019 в качестве гостевой ОС и включить компонент Hyper-V. Если напрямую подключиться к виртуальному COM-порту VMware, то при коммуникации пойдут ошибки обмена пакетов (сложно сказать, с чем это связано). Используй какую‑нибудь бесплатную утилиту эмуляции COM-порта для стабилизации соединения (я установил утилиту эмулятора COM-порта Free Virtual Serial Ports от HHD-software версии 3.32. Последняя версия 4.12 выдает ошибки, когда vmdemux пытается открыть COM-порт).
Общий порядок действий таков.
-
Создай COM-порт для виртуальной машины VMware (Hardware → Add → Serial port → Use named pipe). Введи \\.\<wbr />pipe\<wbr />com_1.
-
Для настройки отладки введи в командной строке опции отладки гипервизора:
bcdedit /hypervisorsettings serial DEBUGPORT:1 BAUDRATE:115200bcdedit /set hypervisordebug onЗатем нужно ввести параметры отладки хостовой ОС (будет использован тот же COM-порт):
bcdedit /set dbgtransport kdhvcom.dllbcdedit /dbgsettings serial DEBUGPORT:1 BAUDRATE:115200bcdedit /debug onДополнительно (для отладки загрузки гипервизора — см. соответствующий раздел статьи):
Bcdedit /set bootdebug onНиже приведен список модулей отладки, присутствующих в Windows:
kdcom.dllkdhvcom.dllkd1934.dllkdhv1394.dllkdusb.dllkdnet.dll (разные производители сетевых карт — разные модули)kd.dllВ нашем случае мы используем kdhvcom.<wbr />dll.
-
Перезагрузи Windows Server 2019. Загрузка остановится и будет ждать подключения отладчика.
-
Открой HHD software Free Virtual Serial Ports, выбери File, затем Create Pipe Port. В поле Pipe name укажи то же значение, что было раньше заполнено для виртуальной машины, — \\.\<wbr />pipe\<wbr />com_1. Чекбокс Create pipe должен быть отключен (в противном случае будет создан новый именованный канал, а не выполнено подключение к существующему). Нажми OK.
Виртуальный COM-порт нужно создавать после запуска виртуальной машины, иначе ты увидишь ошибку, что канал не был создан (VMware создает канал после запуска ВМ).
-
Запусти утилиту vmdemux (находится в папке с WinDbg x64) с указанием имени только что созданного COM-порта в качестве одного из параметров:
vmdemux.exe —src com:port=com2,baud=115200Утилита создаст два именованных канала: Vm0 для гипервизора и Vm1 для root-раздела.
-
Ты можешь подключить WinDbg Preview к каждому каналу для тестирования:
WinDBGx.exe —k com:port=\.pipeVm1,pipe,reconnect,resets=0 – root—разделWinDBGx.exe —k com:port=\.pipeVm0,pipe,reconnect,resets=0 – гипервизор -
После этого можно открыть файл hvix64.exe в IDA PRO, выбрать WinDbg в качестве отладчика и указать в process options → connection string: com:<wbr />port=\\.\<wbr />pipe\<wbr />Vm0,<wbr />pipe,<wbr />resets=0.
-
Выбери Process Attach, нажми Same.
-
Отладчик остановится внутри гипервизора.
-
По сравнению с Windows Server 2012 (R2) в актуальной версии серверной винды появился новый модуль — kdstub.<wbr />dll. Ранние версии гипервизора статически линковались с библиотекой отладки и имели достаточно большой размер (2–3 Мбайт), размер текущей версии (10.0.17763.1577) гипервизора hvix64.<wbr />exe — 1230 Кбайт. В случае сетевой отладки kdstub.<wbr />dll будет заменен подходящим отладочным модулем, например kd_02_8086.<wbr />dll.
Во всех подробностях настройка отладки через COM-порт в среде Hyper-V описана в статье Саара Амара (@AmarSaar).
Отладка по сети
В Windows Server 2012 и выше появилась возможность отладки гипервизора по сети. Также эта возможность присутствует во всех версиях Windows 10. Для этого в хостовой ОС необходимо выполнить команды, чтобы настроить параметры отладки гипервизора:
Если есть необходимость, для отладки ОС на хосте нужно указать другой порт:
После выполнения команд будет отображена строка для подключения. В настройках виртуальной машины VMware нужно установить тип адаптера Host Only, в настройках виртуальной сети (Edit → Virtual Network Editor) настроить DHCP для этого адаптера и убедиться, что гостевая ОС нормально получает этот адрес, например выполнив команду ipconfig /<wbr />renew. Опция bcdedit /<wbr />dbgsettings nodhcp позволяет использовать IP-адрес операционной системы. В этом случае настройка DHCP необязательна.
После этого нужно запустить два экземпляра IDA PRO, выбрать тип отладки KernelMode, указать в Process Option → Connection string следующие строки, полученные в результате выполнения приведенных выше команд:
Это позволяет одновременно отлаживать root-раздел и гипервизор. Сетевая отладка гораздо проще в конфигурации, дает бо́льшую производительность и стабильнее, поэтому я рекомендую использовать ее там, где это возможно. Выполнить некоторые команды WinDbg можно даже без наличия символов. Если какие‑то из перечисленных ниже команд не будут доступны, просто повторно загрузи следующие расширения WinDbg:
Здесь:
- lm — просмотр загруженных модулей (обычно hv и модуль отладки);
- k — просмотр стека;
- d, e — чтение/запись данных по виртуальных адресам;
- !d, !e — чтение/запись данных в физической памяти;
- r — отображение значений регистров;
- !vtop — трансляция виртуальных адресов в физические. Сперва нужно получить содержимое регистра cr3 и использовать его как первый параметр. Виртуальный адрес — второй параметр.
dx — расширение доступно тоже, но с некоторыми ограничениями (из‑за отсутствия символов): @$debuggerRootNamespace.<wbr />Debugger.<wbr />State.<wbr />PseudoRegisters.<wbr />General. Exentry — псевдорегистр, отображающий адрес загрузки модуля гипервизора (hvix64).
Отладка с использованием встроенных возможностей vmwp.exe
Отладка виртуальной машины может быть выполнена с использованием встроенных возможностей процесса vmwp.<wbr />exe (на одну ВМ один экземпляр). Эту возможность впервые упомянул на форуме OSR online один из архитекторов Hyper-V Джейк Ошинс (Jake Oshins). Более подробно описал Рафаэль Ривера (Rafael Rivera — @WithinRafael) в своем блоге. Я обновил скрипт Риверы и выложил его на GitHub.
Скрипт также может сконфигурировать параметры загрузчика гостевой ОС при помощи PowerShell direct. Для этого:
-
Выключи гостевую ОС.
-
Укажи параметры для скрипта hyperv-dbg-2019.<wbr />ps1.
-
Запусти скрипт от имени администратора (или отключи UAC).
-
Запусти WinDbg следующей командой:
WinDBG —k net:port=50010,target=127.0.0.1,key=1.2.3.4 -
Выполни команду break (Ctrl-Break), после которой отладчик остановится внутри гостевой ОС. Теперь можно исследовать ВМ, используя стандартные команды WinDbg, но в моих экспериментах интенсивная отладка (например, трассировка) несколько раз приводила к тому, что все зависало.
Отладка через протокол GDB
VMware Workstation поддерживает встроенный GDB-отладчик. Чтобы его включить, нужно добавить несколько строк в конфигурационный файл VMware:
Затем ты можешь подключить IDA PRO, «Гидру» или Radare2 к активированному серверу GDB. Пример отладки через GDB-протокол будет показан в разделе «Загрузка гипервизора».
Отладка эмулятора Windows 10X
Эмулятор Windows 10X доступен в магазине Microsoft Store. Этот эмулятор работает на базе Hyper-V. Сам эмулятор запускается как Hyper-V ВМ, Windows 10X — вложенная ВМ.
Необходимо смонтировать образ flash.<wbr />vhdx (просто два раза щелкнуть мышью на файле), с которым работает эмулятор и который расположен в папке по следующему пути:
Скопируй файл в другое место, если у тебя появляются сообщения об ошибках доступа. Имя каталога может отличаться для различных версий эмулятора. До и после монтирования список разделов может выглядеть следующим образом.
Выбери том с меткой VIRT_EFIESP:
Команда bcdedit /<wbr />enum <wbr />all /<wbr />v /<wbr />store <wbr />"Z:\<wbr />efi\<wbr />Microsoft\<wbr />boot\<wbr />BCD" покажет опции загрузочной записи операционной системы эмулятора. Чтобы у нас появилась возможность отладки гостевой ОС, понадобится дамп ядра, который можно получить с использованием встроенных функций эмулятора.
Открой Windows device portal — «Отладка». Загрузи live kernel dump, а затем открой его в WinDbg и запусти скрипт decypher_kdnet_key.<wbr />py. Скрипт найдет параметры kdnet и закодирует в формате Base36.
Теперь запусти WinDbg, используя команду windbgx.<wbr />exe <wbr />-k <wbr />net:<wbr />port=50005,<wbr />key=2k85xmoorkrbx.<wbr />u7xg1f35gwi4.<wbr />24033ib08wzhs.<wbr />2o8xly2z2ik5y. В результате ты сможешь подключиться к ОС хоста.
Отладка Hyper-V c помощью подмененного загрузчика
На эту тему опубликованы два исследования: Hyper-V backdoor Дмитрия Олексюка (@d_olex) и Voyager, созданный @_xeroxz. Их суть — в замене загрузочных файлов Windows в целях перехвата процесса загрузки гипервизора и интеграции своих управляющих модулей. Полноценной отладкой это сложно назвать, но с применением этого метода появляется возможность читать и изменять память Hyper-V. Подробности ты найдешь на страницах упомянутых проектов.
Загрузи последнюю сборку бэкдора и запусти скрипт bootkit_installer.<wbr />ps1 в хостовой ОС (протестировано в виртуальной среде на Windows Server 2019 внутри VMware Workstation). Перезагрузим хостовую ОС и увидим следующую картину.
В гостевой ОС мы можем запустить backdoor_client.<wbr />exe и получить доступ к различным структурам данных Hyper-V.
Второй проект, Voyager, может быть загружен с сайта GitHacks. Бинарников он не содержит, поэтому их необходимо скомпилировать с помощью Visual Studio для подходящей версии Windows. После чего запустить файл launch.<wbr />bat, который заменит загрузочные файлы Windows. После перезагрузки мы увидим следующую картину.
Для проверки работоспособности можно запустить example.<wbr />exe внутри гостевой ВМ.
Надеюсь, мы увидим в будущем больше примеров для этого проекта.
Отладка secure kernel
Отладку позволяет выполнить модуль EXDi для LiveCloudKd без включения опции отладки в загрузчике гостевой ОС. Все подробности можно узнать в соответствующей документации.
Отладка с помощью Radare2
Radare2 — консольное средство отладки, поддерживающее очень много режимов. Мы рассмотрим только отладку ядра Windows. Бинарники можно загрузить с того же github.com по адресу https://github.com/radareorg/radare2/releases.
Незначительно изменив исходники, можно получить дополнительную информацию о Hyper-V (модифицированные бинарники приложены к статье). Для начала рекомендую почитать официальные источники, они содержат отличные инструкции.
До запуска необходимо скопировать следующие расширения WinDbg x64 в папку с Radare2:
Не забудь указать путь к папке с установленным WinDbg x64 в переменной окружения _NT_DEBUGGER_EXTENSION_PATH. Вот некоторые команды для тестирования успешности подключения:
- pd — дизассемблирование;
- xq <wbr />@0x<<wbr />address> — отображение региона памяти;
- v — переключение в режим GUI.
Radare2 может подключаться к ядру Windows в двух режимах: через интерфейс dbgeng.<wbr />dll и с использованием собственного протокола winkd.
Radare2 и интерфейс dbgeng.dll
Сперва необходимо настроить гипервизор в режиме сетевой отладки, как это было описано раньше, и запустить Radare2 следующим образом:
Подключено! Теперь ты можешь выполнять стандартные команды WinDbg, используя префикс =!.
Radare2 и встроенный протокол
Можно попробовать подключиться к гипервизору по сети, выполнив команду radare2 <wbr />-D <wbr />winkd <wbr />winkd://<wbr />192.<wbr />168.<wbr />174.<wbr />1:<wbr />50011:<wbr />1.<wbr />2.<wbr />3.<wbr />4. Я получил ошибку открытия UDP-сокета, хотя netstat показал, что порт открыт. Возможно, это ошибка настройки на моем стенде, но исправить ее мне не удалось. В связи с этим будем использовать отладку через COM-порт. Для этого нужно настроить гипервизор так, как это было описано раньше, запустить vmdemux и подключить Radare2 к именованному каналу:
Используя данные протокола отладки, можно получить дополнительную информацию о загруженном модуле Hyper-V.
Иногда Radare2 не может подключиться к COM-порту и виснет. В этом случае нужно просто сперва подключиться обычным WinDbg-отладчиком, отключиться и подсоединиться с помощью Radare2.
Cutter
Cutter — GUI-фронтенд для Radare2, обладает достаточно интересными отладочными возможностями, но пока что находится в бета‑стадии. К тому же Cutter обладает встроенной поддержкой декомпилятора Ghidra, что делает его очень полезным. В настоящее время Cutter поддерживает отладку по GDB-протоколу и именованным каналам WinDbg. Мне удалось подключиться к начальной стадии загрузки ОС.
QEMU
QEMU поддерживает вложенную виртуализацию, но без ядерного акселератора работает очень медленно. Ускоряющий модуль KVM, поддерживающий вложенную виртуализацию, доступен на платформе Linux. Ради интереса рекомендую посмотреть проект Debugging secure kernel. Microsoft WHPX и Intel haxm пока что вложенную виртуализацию не поддерживают.
Ghidra + плагин ret-sync
Ты можешь загрузить скомпилированную версию «Гидры» с официального сайта, а плагин ret-sync — с GitHub. Плагин позволяет синхронизировать различные отладчики между собой. Синхронизировать будем с WinDbg (хотя можно и с GDB).
Для создания проекта нужно выполнить следующие действия:
-
Запусти «Гидру», используя ghidraRun.<wbr />bat.
-
Импортируй плагин ret-sync: File → Install extension, нажми зеленый плюсик. Выбери архив ZIP с плагином.
-
Нажми ОK, перезапусти «Гидру».
-
Выполни команды File → New project. Non shared project. Укажи имя проекта и папку, в которой будут храниться служебные файлы.
-
Запусти CodeBrowser нажатием кнопки в панели Tool Chest. Ты увидишь сообщение об установке плагина ret-sync.
-
Нажми ОK, появится окно с пустым проектом. Загрузи файл hvix64.<wbr />exe, используя File → Import file.
-
Нажми OK. Файл будет загружен. После того как появится запрос на выполнение анализа, нажми Yes.
-
Включи функцию Aggressive Instruction Finder.
-
Нажми OK. Прогресс операции можно увидеть в правом нижнем углу окна.
-
Далее появится сообщение о том, что файл hvix64.<wbr />pdb отсутствует. Просто нажми OK.
-
Нажми Alt-S для активации плагина ret-sync, и ты увидишь следующие сообщения.
-
Подключи WinDbg к Hyper-V (например, по сети) и загрузи расширение ret-sync:
.load @”C:hv_debuggingsync.dll”!sync
Если все прошло успешно, ты увидишь сообщение в консольном окне «Гидры».
Окно WinDbg будет отображать выполнение команд.
Для проверки я поставил точку останова на обработчик гипервызова HvPostMessage (F2) и затем запустил отладку (F5). Точка останова сработала.
Комбинации клавиш ret-sync можно найти на официальной странице Radare2, опции плагина ret-sync для WinDbg отображаются в консоли по команде !synchelp.Ты можешь скопировать символьную информацию из IDA PRO в «Гидру» с использованием плагина Fake PDB.
Интересно, что «Гидра» во время анализа hvix64.<wbr />exe (сборка 10.0.17763.1577) нашла 4100 функций, в отличие от IDA PRO, которая обнаружила всего 3687 функций.
Загрузка гипервизора
Вспомогательные компоненты загрузки гипервизора со временем менялись:
- hvboot.<wbr />sys — Windows Server 2008, 2008 R2;
- hvloader.<wbr />exe или hvloader.<wbr />efi — Windows Server 2012 R2, 2016;
- hvloader.<wbr />dll — Windows 10, Windows Server 2019.
Отладка гипервизора с помощью WinDbg достаточно удобна, но не всегда возможна — например, когда нужно отладить secure kernel или среду со включенной опцией Secure Boot. Поэтому мы рассмотрим загрузку гипервизора при помощи GDB-отладки.
Для этого нам нужно загрузить в IDA PRO следующие файлы:
- winload.<wbr />efi (сборка 10.0.17763.1554);
- hvloader.<wbr />dll (сборка 10.0.17763.1577);
- hvix64.<wbr />exe (сборка 10.0.17763.1577).
Затем надо настроить для них опции отладки по GDB-протоколу. Для файлов hvix64.<wbr />exe и hvloader.<wbr />dll символы отсутствуют. Сперва мы должны найти адреса загрузки winload.<wbr />efi и hvloader.<wbr />dll с помощью WinDbg, затем отключить WinDbg, включить Secure Boot и продолжить отладку уже по протоколу GDB.
Для тестирования я использовал Windows Server 2019 c четырьмя CPU (для загрузки количество процессоров не так важно, но, как только загрузится гипервизор GDB, отладчик будет постоянно переключаться между контекстом гипервизора и ядра Windows). Сперва загрузим winload.<wbr />efi. IDA PRO не показывает некоторые опции отладки, если бинарник имеет тип Windows boot application. Запусти свой любимый PE-редактор, выбери Optional header → Subsystem и поменяй Windows boot application на Windows GUI.
Для настройки отладки необходимо выбрать Debugger → Select Debugger → GDB, в поле Process Options указать Hostname 127.<wbr />0.<wbr />0.<wbr />1 и port 8864.
В гостевой ОС был активирован режим bootdebug on, поэтому после включения ОС загрузка остановится в процедуре winload!DebugService2.
Запусти WinDbg командой WinDBG.<wbr />exe <wbr />-b <wbr />-k <wbr />net:<wbr />port=50002,<wbr />key=1.<wbr />2.<wbr />3.<wbr />4, и ты получишь адрес загрузки:
Модуль winload.<wbr />efi уже был открыт в IDA PRO, поэтому выбери Debugger → attach для подключения к GDB-серверу отладки VMware, запусти Edit → Segments → Rebase, укажи полученный ранее адрес winload.<wbr />efi ( 0x008c4000) и нажми OK. Теперь дождись завершения процедуры и сохрани базу. Адрес загрузки winload.<wbr />efi не изменится после перезагрузки, поэтому операция rebase не потребуется. Затем:
- поставь точку останова на winload!OslArchHypervisorSetup и продолжи отладку (F9);
- продолжи отладку в ранее запущенном WinDbg (F5).
Функция winload!OslGetHypervisorLaunchType проверяет, была ли установлена опция загрузки hypervisorlaunchtype (<wbr />0x250000f0).
Если параметр был задан и его значение равно 1 (Auto), функция загружает hvloader.<wbr />dll и получает адреса следующих функций, экспортируемых библиотекой:
- HvlRescindVsm
- HvlLaunchHypervisor
- HvlLoadHypervisor
- HvlRegisterRuntimeRange
- HvlUpdateMcUpdateStatus
- HvlPreloadHypervisor
Далее выполняется функция winload!HvlpLoadHypervisor. После вызова CmpFindSkuType выполняется hvloader!HvlLoadHypervisor. Для отладки hvloader.<wbr />dll мы должны переключиться между базами. C этой целью был написан скрипт для IDA PRO PatchHvLoader2019.<wbr />py, который покажет базу загрузки hvloader (вернее, получит ее напрямую из базы winload.<wbr />exe) и пропатчит функцию hvloader!HvlLoadHypervisor таким образом, чтобы она зациклилась (EB FE — jmp rip).
Скрипт требует ручного определения имен в базе IDA PRO: hvloader_image_base и p_HvlLoadHypervisor. Переменные расположены внутри функции winload!HvlpLoadHvLoader, это видно на следующей иллюстрации.
Адрес hvloader_image_base нужно запомнить. Отключи текущую GDB-сессию и загрузи hvloader.<wbr />dll в IDA. Подключись к GDB-серверу. CPU должен быть зациклен с помощью инструкции jmp <wbr />rip. Теперь выполни Edit → segments → rebase и введи найденный адрес hvloader_image_base. Запусти RestoreHvLoader2019.<wbr />py. Можно отлаживать hvloader.<wbr />dll. Сперва hvloader получает все опции загрузки Windows и подготавливает hvix64.<wbr />exe к отладке, если она была включена.
Теперь у нас есть адрес загрузки winload.<wbr />efi и hvloader.<wbr />dll. Выключаем ВМ, включаем опцию SecureBoot (Option → Advanced → UEFI → Enable secure boot). Добавь строчку monitor.<wbr />debugOnStartGuest64 <wbr />= <wbr />"TRUE" в конфигурационный файл ВМ (расширение .<wbr />vmx) и запусти ВМ. Открой базу winload.<wbr />efi в IDA PRO, подключись отладчиком к GDB-серверу VMware, и ты остановишься непосредственно на начальной процедуре запуска виртуальной операционной системы (где‑то на ранней стадии загрузки BIOS).
Нажми F9 и подожди, пока снова не произойдет остановка в процедуре winload!OslArchHypervisorSetup. Можно продолжать отладку, будут выполняться Winload.<wbr />efi!BlSiHandleHypervisorLaunchEvent, затем winload!OslArchHypercallSetup и winload!VlpSetupPhase0. Далее загрузчик выполняет инициализацию дисков (включая VHD, если была настроена опция загрузка с VHD-диска), инициализацию UEFI ( winload!BlHSTICallProviders), политики целостности кода ( winload!OslInitializeCodeIntegrity), а также процедуры winload!OslFwProtectSecConfigVars, winload!OslpProcessEVStore.
Переходим к winload!VlpSetupPhase1. Из этой процедуры вызывается ранее найденная функция hvloader!p_HvlRescindVsm. Далее winload!OslExecuteTransition снова вызывает winload!VlpSetupLaunchPhase, а winload!OslArchHypervisorSetup выполняет другой блок кода и на этот раз вызывает hvloader.<wbr />dll!p_HvlLaunchHypervisor. В свою очередь, Hvloader.<wbr />dll!HvlLaunchHypervisor выполняет bootlib!BlGetExecutionEnvironment, bootlib!OslLoadMicrocodeUpdate и затем передает управление загруженному гипервизору.
После выполнения инструкции mov <wbr />cr3, <wbr />rcx мы видим, что адреса памяти выше 0x3000 перестают быть доступны.
Однако Hvix64.<wbr />exe уже загружен в 64-битное адресное пространство. Для доступа к памяти нужно вручную создать в IDA PRO область памяти для отладчика (manual memory region).
Выделяемая область памяти имеет следующие начальный и конечный адреса:
В принципе, если отладчик не выдает ошибку, можно задать расширенный диапазон ( 0-0xFFFFFFFFFFFFFFFF). Если текущая инструкция выйдет за диапазон указанных адресов, то IDA PRO просто зависнет.
Выполни пошаговую отладку до инструкции jmp <wbr />rdx, затем скрипт PatchHvix64_2019.<wbr />py. Закрой базу hvloader.<wbr />dll, открой hvix64.<wbr />exe и снова подключись к GDB-серверу. Потом для поиска адреса загрузки гипервизора запусти RebaseHVGdb2019.<wbr />py, затем — RestoreHvix64_2019.<wbr />py, который возвращает назад замененные инструкции. Мы внутри hvix64.exe.
После выполнения инструкции vmlaunch мы вернемся в hvloader.<wbr />dll, в точку vm_exit, которая была задана в поле vmcs, и загрузка ОС продолжится в обычном режиме.
Если нужно отладить hvix64.<wbr />exe с помощью GDB, сделай следующее:
- запустить VMware в режиме отладки GDB и выполнить остановку на начальной стадии загрузки BIOS;
- открыть базу данных с winload.<wbr />efi, подключить к GDB и поставить точку останова на инструкции, которая вызывает hvloader!HvlLaunchHypervisor;
- нажать F9;
- запустить скрипт 1_PatchHvLoader2019.<wbr />py;
- закрыть базу IDA PRO с winload.<wbr />efi, открыть базу с hvloader.<wbr />dll и подключиться к GDB;
- запустить 2_RestoreHvLoader2019.<wbr />py;
- создать точку останова на инструкции, передающей управление гипервизору ( jmp <wbr />r8);
- запустить 3_PatchHvix64_2019.<wbr />py;
- закрыть базу данных с hvloader.<wbr />dll, открыть базу данных с hvix64.<wbr />exe и подключиться к GDB-серверу;
- запустить скрипт 4_RebaseHVGdb2019.<wbr />py;
- запустить скрипт 5_RestoreHvix64_2019.<wbr />py.
После этого можно отлаживать hvix64.<wbr />exe (в скрипте забит стартовый адрес по смещению 0x7a). Следует отметить, что процесс загрузки гипервизора в Windows Server 2012 (и выше) существенно отличается от Windows Server 2008 R2, где подготовка и запуск гипервизора производится драйвером hvboot.<wbr />sys, который запускается после загрузки ядра Windows. Активация гипервизора с помощью инструкции vmlaunch, выполненная в hvboot.<wbr />sys, и следующий выход из ВМ обрабатывается hvix64.<wbr />exe. Более поздние версии используют hvloader, который запускается непосредственно из winload.<wbr />exe.
Поиск символьной информации
С 2018 года многие компоненты Hyper-V имеют общедоступные символы. На момент публикации только hvix64.<wbr />exe, hvax64.<wbr />exe и hvaa64.<wbr />exe с hvloader.<wbr />dll не имели символов. Последние модули hvloader.<wbr />exe (.<wbr />efi) и hvloader.<wbr />dll, имеющие символы, могут быть загружены для модулей, скомпилированных до марта 2018-го (я использовал символы hvloader.<wbr />dll из Windows 10, сборка 17115, дата сборки — 03.03.2018).
При загрузке hvix64.<wbr />exe в IDA PRO мы получаем около четырех тысяч функций с именами вроде sub_FFFFF8000XXXXX. Для ускорения исследования гипервизора можно сначала попытаться определить некоторые функции без подробного изучения. В первую очередь стоит использовать bindiff (или diaphora) для сравнения файлов hvix64, hvloader и winload, для которых предоставляется символьная информация. Сравнение показывает, что сетевая функция ( e1000), USB, криптография и некоторые другие функции в точности такие же, как и в winload.<wbr />exe (в Windows Server 2019 и Windows 10 функции отладки Hyper-V и сетевого драйвера были перемещены в отдельные модули, например bootlib.<wbr />dll). Тот же самый bindiff позволяет перемещать имена совпадающих функций из одной базы данных в другую. Однако к этому методу стоит отнестись с осторожностью и не переносить сразу все полностью совпавшие функции. По крайней мере, проанализируй результат: сравни графы совпавших функций (Ctrl-E).
Далее надо определить функции обработки прерываний и исключений, стандартные для процессоров архитектуры x86. Облегчит эту задачу небольшой скрипт на Python ( ParseIDT.<wbr />py) для парсинга IDT. Его необходимо запускать в IDA PRO, предварительно подключившись через отладочный модуль WinDbg к гипервизору. Если часть ISR не была найдена, следует проверить вкладку List of problems в IDA PRO, так как IDA может не найти эти процедуры автоматически.
Далее можно определить процедуру выхода VM <wbr />exit, прочитав значения полей VMCS: изучи процедуру заполнения VMCS в hvix64.<wbr />exe или же воспользуйся скриптом display-vmcs.<wbr />py, который в контексте гипервизора считывает все поля VMCS и выводит их значения. Есть хорошие скрипты IDA-Python от Вехруза Аббасси (Behrooz Abbassi — @rceninja): ia32_msr_decoder.<wbr />py и IA32_VMX_Helper.<wbr />py. С их помощью можно получить символические имена полей MSR и VMCS внутри базы данных IDA.
Хорошие новости: здесь присутствуют символы hvix64.<wbr />exe, hvax64.<wbr />exe, hvboot.<wbr />sys для Windows Server 2008. Плохая новость заключается в том, что Windows Server 2008 уже давно не обновляется и не включает в себя многих новых функций Hyper-V. Но ты можешь изучить базовый механизм работы Hyper-V и реализацию гипервызовов в сравнении с Hyper-V TLFS 1.0.
Очень хороший заголовочный файл hvgdk.<wbr />h, содержащий актуальную информацию о Hyper-V (о структурах гипервизора Windows 10 и Windows Server 2019), создал Алекс Ионеску (@aionescu).
Утилиты
В последние годы было разработано множество полезных системных утилит. Я не буду описывать утилиты Sysinternals, потому что они знакомы всем, кто занимается исследованием внутреннего устройства Windows. Еще существует интересный набор утилит от Павла Йосифовича (@zodiacon), который известен как один из авторов седьмого издания первой части книги «Внутреннее устройство Windows». Они похожи на утилиты Sysinternals, но поставляются с открытым исходным кодом.
С помощью ETWProvider можно посмотреть список ETW-провайдеров, используемых компонентами Hyper-V в работающей системе.
С использованием утилиты DrvMon можно увидеть взаимодействие ядерных компонентов и компонентов, запущенных в пользовательском режиме.
Набор утилит для диагностирования от Microsoft также может быть использован для получения дополнительной информации о работе компонентов Hyper-V. Не менее полезны утилиты для сбора событий ETW:
- VMLtrace;
- Fruti;
- tss_VMLverbosity.<wbr />ps1;
- V_Tracing_Using_Channels.<wbr />ps1.
Гипервызовы
Последняя версия документа «Hypervisor Top-Level Functional Specification» для Windows Server 2019 — 6.0b — описывает интерфейсы Hyper-V и внутреннее устройство некоторых компонентов гипервизора. Каждая виртуальная машина, а также непосредственно ОС с установленным компонентом Hyper-V представляется в виде раздела (partition). У каждого раздела есть свой идентификатор, который должен быть уникальным в рамках хост‑сервера и имеет 64-битное значение.
Для каждого раздела при создании задаются привилегии (структура HV_PARTITION_PRIVILEGE_MASK), которые и определяют возможность выполнения конкретных гипервызовов. Узнать привилегии можно, выполнив в root-partition следующий код в ring0:
Здесь HvPartitionPropertyPrivilegeFlags — одно из значений перечисления HV_PARTITION_PROPERTY_CODE, которыми оперируют функции, экспортируемые драйверами winhvr.<wbr />sys и winhv.<wbr />sys.
Также при необходимости эти привилегии можно поменять, вызвав в root-partition следующую функцию:
Значение HvPartitionPropertyPrivilegeFlags для раздела Windows Server 2019: 002BB9FF00003FFF.
Значение HvPartitionPropertyPrivilegeFlags для гостевого раздела: 003B80B000002E7F.
В гостевой ОС привилегии можно получить, поместив в EAX <wbr />0x40000003 и выполнив инструкцию CPUID (в документе Hyper-V TLFS 6.0b дана расшифровка результатов CPUID).
В гипервизоре можно получить привилегии раздела, который выполнил операцию, вызвавшую VM <wbr />exit, если вычислить значение gs:<wbr />0. Для этого нужно прочитать значение поля HOST_GS_BASE <wbr />в <wbr />VMCS <wbr />или <wbr />же <wbr />IA32_GS_BASE <wbr />MSR:
Затем следует получить значение, на которое указывает gs:<wbr />83a8, и перейти по смещению 0xd8.
В данном случае VM exit был выполнен из root-partition. Гипервизор в каждом из разделов формирует специальную страницу для выполнения гипервызовов. Ее адрес можно получить, прочитав MSR <wbr />0x40000001 (<wbr />HV_X64_MSR_HYPERCALL).
Windows Server 2019 на Windows Server 2019:
Чтобы иметь возможность использовать экспортируемые функции winhv.<wbr />sys и winhvr.<wbr />sys, можно либо динамически вычислять адреса функций, либо создать lib-файл. Рассмотрим второй вариант. Для создания def-файла используем вывод команды dumpbin:
Windows Server 2016 и новее используют драйвер winhvr.<wbr />sys для root-раздела, таким образом def-файл для драйвера, предназначенного для работы на хост‑сервере, необходимо формировать на основе этого файла. Для сборки 64-битного драйвера правки вносить не нужно. Формирование lib-файла выполняется следующей командой (для x86):
Для x64:
Перед выполнением команд не забудь запустить Visual Studio native tools. Мы можем найти таблицу гипервызовов в файле hvxi64.exe, используя специальный скрипт. Скрипт создает таблицу наподобие показанной на иллюстрации ниже.
Мы можем отобразить значения VMCS полей внутри hvix64.exe, используя скрипт display-vmcs.py. Скрипт необходимо запустить в IDA PRO для файла hvix64.<wbr />exe при подключенной отладочной сессии к гипервизору. Скрипт формирует и вызывает процедуру
Он считывает значение регистра rax и отображает его в консоли IDA PRO. Для сравнения вот некоторые значения VMCS.
Например, ты можешь увидеть, что гостевой раздел гипервизора обрабатывает весь поток информации, проходящей через порты ввода‑вывода (I/O exiting Unconditional), а для root-раздела выполняется перехват только некоторых портов (используется I/O bitmaps).
WINDBG><wbr />!db <wbr />0x101001000 <wbr />L1300
#101001000 <wbr />00 <wbr />00 <wbr />00 <wbr />00 <wbr />03 <wbr />00 <wbr />00 <wbr />00-00 <wbr />00 <wbr />00 <wbr />00 <wbr />10 <wbr />00 <wbr />00 <wbr />00 ...............<wbr />.
#101001010 <wbr />00 <wbr />00 <wbr />00 <wbr />00 <wbr />03 <wbr />00 <wbr />00 <wbr />00-00 <wbr />00 <wbr />00 <wbr />00 <wbr />00 <wbr />00 <wbr />00 <wbr />00 ...............<wbr />.
..<wbr />.
#101001080 <wbr />00 <wbr />00 <wbr />00 <wbr />00 <wbr />00 <wbr />00 <wbr />00 <wbr />00-20 <wbr />00 <wbr />00 <wbr />00 <wbr />00 <wbr />00 <wbr />00 <wbr />00 ........ ......<wbr />.
..<wbr />.
#101001190 <wbr />00 <wbr />00 <wbr />00 <wbr />00 <wbr />00 <wbr />00 <wbr />00 <wbr />00-00 <wbr />00 <wbr />00 <wbr />00 <wbr />00 <wbr />00 <wbr />00 <wbr />f1 ...............<wbr />.
Вывод
В статье было описано создание стенда для исследования Hyper-V, а также очень кратко описаны некоторые нюансы работы гипервизора. Надеюсь, эта информация пригодится начинающим исследователям безопасности гипервизора компании Microsoft.