• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Гиперотладка. Разбираем отладку Microsoft Hyper-V с самого начала

weaver

31 c0 bb ea 1b e6 77 66 b8 88 13 50 ff d3
Забанен
Регистрация
19.12.2018
Сообщения
3 301
Решения
11
Реакции
4 622
Депозит
0.0001
Пожалуйста, обратите внимание, что пользователь заблокирован
Содержание
  1. Отладка гипервизора Hyper-V
  2. Отладка через COM-порт
  3. Отладка по сети
  4. Отладка с использованием встроенных возможностей vmwp.exe
  5. Отладка через протокол GDB
  6. Отладка эмулятора Windows 10X
  7. Отладка Hyper-V c помощью подмененного загрузчика
  8. Отладка secure kernel
  9. Отладка с помощью Radare2
  10. Radare2 и интерфейс dbgeng.dll
  11. Radare2 и встроенный протокол
  12. Cutter
  13. QEMU
  14. Ghidra + плагин ret-sync
  15. Загрузка гипервизора
  16. Поиск символьной информации
  17. Утилиты
  18. Гипервызовы
  19. Вывод

Гипервизор производства корпорации Microsoft, как и любая другая программа, создан людьми, а значит, содержит определенное количество ошибок. Поиск этих ошибок — занятие не только увлекательное, но и полезное: во‑первых, Microsoft располагает собственной программой Bug Bounty (о ее особенностях я расскажу чуть ниже), а во‑вторых… Во‑вторых, знания об уязвимостях и недокументированных возможностях приложений ценны сами по себе. В сегодняшней статье мы рассмотрим принципы отладки гипервизора Hyper-V и разберемся в его особенностях.

Гипервизор компании Microsoft используется в большом числе компонентов Windows и, как любой сложный продукт, не лишен допущенных при разработке ошибок. Число уязвимостей, найденных в этом продукте только в 2020 году, составило 21.


vulnlist2.jpg

В 2020 году в Hyper-V была обнаружена 21 уязвимость


Для Hyper-V Microsoft предлагает отдельную программу баг‑баунти, размер выплат которой может достигать 250 тысяч долларов. Однако стоит упомянуть, что Microsoft не работает со странами, которые находятся в санкционном списке США. Россия формально присутствует в этом списке, поэтому следует проявлять осмотрительность, когда отправляешь информацию об уязвимостях в Microsoft, если ты еще ни разу не получал вознаграждение напрямую от вендора. Лучше воспользоваться услугами посредника, иначе ты можешь столкнуться с тем, что обнаруженная тобою уязвимость вдруг одновременно будет найдена другой компанией или исследователем. И неважно, что уязвимость оставалась в продукте несколько лет (этот вариант был проверен на практике).

Отладка гипервизора Hyper-V​

Чтобы искать уязвимости в Hyper-V, нужно владеть методами отладки этого гипервизора. Актуальные способы отладки и будут темой сегодняшней статьи. Для этих целей можно использовать эмуляторы, поддерживающие вложенную виртуализацию (такие как VMware Workstation или сам Hyper-V), либо обычный компьютер или ноутбук.


Термины
  • Гипервизор — компонент Hyper-V, отвечающий за функционирование подсистемы аппаратной виртуализации процессора (hvix64.exe — Intel, hvax64.exe — AMD, hvaa64.exe — ARM). В статье рассматривается гипервизор для процессоров Intel.
  • Гипервызов (hypercall) — вызов заданной функции в гипервизоре с помощью инструкции vmcall\\vmmcall\\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.dll, которое, к сожалению, не входит в дистрибутив и доступно только партнерам Microsoft (поскольку этому расширению требуются символы для модуля гипервизора, которые Microsoft не предоставляет). Также в каталоге winxp, находящемся в папке WinDbg, есть расширение nvkd.dll, которое предназначено для отладки расширений виртуального коммутатора Hyper-V.

Файл справки WinDbg содержит описание отладки гипервизора через COM-порт (отладка Hyper-V через нуль‑модемное кабельное соединение в файле debugger.chm), подразумевающее наличие двух физических машин. Также гипервизор можно отладить, если запустить его в любом поддерживаемом программном обеспечении виртуализации. Далее мы будем использовать VMware Workstation.

Для начала нужно установить Windows Server 2019 в качестве гостевой ОС и включить компонент Hyper-V. Если напрямую подключиться к виртуальному COM-порту VMware, то при коммуникации пойдут ошибки обмена пакетов (сложно сказать, с чем это связано). Используй какую‑нибудь бесплатную утилиту эмуляции COM-порта для стабилизации соединения (я установил утилиту эмулятора COM-порта Free Virtual Serial Ports от HHD-software версии 3.32. Последняя версия 4.12 выдает ошибки, когда vmdemux пытается открыть COM-порт).


Общий порядок действий таков.

1) Создай COM-порт для виртуальной машины VMware (Hardware → Add → Serial port → Use named pipe). Введи \\.\pipe\com_1.

1613205052100.png

Создание COM-порта для виртуальной машины

2) Для настройки отладки введи в командной строке опции отладки гипервизора:

Код:
bcdedit /hypervisorsettings serial DEBUGPORT:1 BAUDRATE:115200
bcdedit /set hypervisordebug on

Затем нужно ввести параметры отладки хостовой ОС (будет использован тот же COM-порт):

Код:
bcdedit /set dbgtransport kdhvcom.dll
bcdedit /dbgsettings serial DEBUGPORT:1 BAUDRATE:115200
bcdedit /debug on

Дополнительно (для отладки загрузки гипервизора — см. соответствующий раздел статьи):

Код:
Bcdedit /set bootdebug on

Ниже приведен список модулей отладки, присутствующих в Windows:

kdcom.dll
kdhvcom.dll
kd1934.dll
kdhv1394.dll
kdusb.dll
kdnet.dll (разные производители сетевых карт — разные модули)
kd.dll

В нашем случае мы используем kdhvcom.dll.

3) Перезагрузи Windows Server 2019. Загрузка остановится и будет ждать подключения отладчика.
4) Открой HHD software Free Virtual Serial Ports, выбери File, затем Create Pipe Port. В поле Pipe name укажи то же значение, что было раньше заполнено для виртуальной машины, — \\.\pipe\com_1. Чекбокс Create pipe должен быть отключен (в противном случае будет создан новый именованный канал, а не выполнено подключение к существующему). Нажми OK.

1613205308400.png

Создание нового порта

Виртуальный COM-порт нужно создавать после запуска виртуальной машины, иначе ты увидишь ошибку, что канал не был создан (VMware создает канал после запуска ВМ).

5) Запусти утилиту vmdemux (находится в папке с WinDbg x64) с указанием имени только что созданного COM-порта в качестве одного из параметров:

Код:
vmdemux.exe -src com:port=com2,baud=115200

Утилита создаст два именованных канала: Vm0 для гипервизора и Vm1 для root-раздела.

1613205426100.png

Утилита vmdemux создаст два именованных канала

6) Ты можешь подключить WinDbg Preview к каждому каналу для тестирования:

Код:
WinDBGx.exe  -k com:port=\.pipeVm1,pipe,reconnect,resets=0 – root-раздел
WinDBGx.exe  -k com:port=\.pipeVm0,pipe,reconnect,resets=0 – гипервизор

1613205518400.png

Подключение WinDbg к созданным нами каналам

7) После этого можно открыть файл hvix64.exe в IDA PRO, выбрать WinDbg в качестве отладчика и указать в process options → connection string: com:port=\\.\pipe\Vm0,pipe,resets=0.
8) Выбери Process Attach, нажми Same.
9) Отладчик остановится внутри гипервизора.

1613205617700.png

Отладчик остановится внутри гипервизора

10) По сравнению с Windows Server 2012 (R2) в актуальной версии серверной винды появился новый модуль — kdstub.dll. Ранние версии гипервизора статически линковались с библиотекой отладки и имели достаточно большой размер (2–3 Мбайт), размер текущей версии (10.0.17763.1577) гипервизора hvix64.exe — 1230 Кбайт. В случае сетевой отладки kdstub.dll будет заменен подходящим отладочным модулем, например kd_02_8086.dll.

1613205665000.png

При сетевой отладке kdstub.dll будет заменен подходящим отладочным модулем

Во всех подробностях настройка отладки через COM-порт в среде Hyper-V описана в статье Саара Амара (@AmarSaar).

ОТЛАДКА ПО СЕТИ​

В Windows Server 2012 и выше появилась возможность отладки гипервизора по сети. Также эта возможность присутствует во всех версиях Windows 10. Для этого в хостовой ОС необходимо выполнить команды, чтобы настроить параметры отладки гипервизора:

Код:
bcdedit /set hypervisordebug on
bcdedit /hypervisorsettings NET HOSTIP:192.168.2.1 PORT:50000

Если есть необходимость, для отладки ОС на хосте нужно указать другой порт:

Код:
bcdedit /debug yes
bcdedit /dbgsettings net hostip:192.168.2.1 port:50002

После выполнения команд будет отображена строка для подключения. В настройках виртуальной машины VMware нужно установить тип адаптера Host Only, в настройках виртуальной сети (Edit → Virtual Network Editor) настроить DHCP для этого адаптера и убедиться, что гостевая ОС нормально получает этот адрес, например выполнив команду ipconfig /renew. Опция bcdedit /dbgsettings nodhcp позволяет использовать IP-адрес операционной системы. В этом случае настройка DHCP необязательна.

После этого нужно запустить два экземпляра IDA PRO, выбрать тип отладки KernelMode, указать в Process Option → Connection string следующие строки, полученные в результате выполнения приведенных выше команд:

Код:
net:port=50002,Key=1.2.3.4 — root partition
net:port=50000,Key=5.6.7.8 — hypervisor

Это позволяет одновременно отлаживать root-раздел и гипервизор. Сетевая отладка гораздо проще в конфигурации, дает бо́льшую производительность и стабильнее, поэтому я рекомендую использовать ее там, где это возможно. Выполнить некоторые команды WinDbg можно даже без наличия символов. Если какие‑то из перечисленных ниже команд не будут доступны, просто повторно загрузи следующие расширения WinDbg:

Код:
.load kext
.load kdexts
.load exts
.load ext

Здесь:
  • lm — просмотр загруженных модулей (обычно hv и модуль отладки);
  • k — просмотр стека;
  • d, e — чтение/запись данных по виртуальных адресам;
  • !d, !e — чтение/запись данных в физической памяти;
  • r — отображение значений регистров;
  • !vtop — трансляция виртуальных адресов в физические. Сперва нужно получить содержимое регистра cr3 и использовать его как первый параметр. Виртуальный адрес — второй параметр.

Код:
2: kd> !vtop 0x10839d000 0xfffffbb3aa6c3e66
Amd64VtoP: Virt fffffbb3aa6c3e66, pagedir 000000010839d000
Amd64VtoP: PML4E 000000010839dfb8
Amd64VtoP: PDPE 000000010a603670
Amd64VtoP: PDE 000000010a604a98
Amd64VtoP: Large page mapped phys 00000001000c3e66
Virtual address fffffbb3aa6c3e66 translates to physical address 1000c3e66.
!pte2va
!ptov <cr3>

dx — расширение доступно тоже, но с некоторыми ограничениями (из‑за отсутствия символов): @$debuggerRootNamespace.Debugger.State.PseudoRegisters.General. Exentry — псевдорегистр, отображающий адрес загрузки модуля гипервизора (hvix64).

1613205895900.png

Exentry — псевдорегистр, отображающий адрес загрузки модуля гипервизора

ОТЛАДКА С ИСПОЛЬЗОВАНИЕМ ВСТРОЕННЫХ ВОЗМОЖНОСТЕЙ VMWP.EXE​

Отладка виртуальной машины может быть выполнена с использованием встроенных возможностей процесса vmwp.exe (на одну ВМ один экземпляр). Эту возможность впервые упомянул на форуме OSR online один из архитекторов Hyper-V Джейк Ошинс (Jake Oshins). Более подробно описал Рафаэль Ривера (Rafael Rivera — @WithinRafael) в своем блоге. Я обновил скрипт Риверы и выложил его на GitHub.

Скрипт также может сконфигурировать параметры загрузчика гостевой ОС при помощи PowerShell direct. Для этого:

1) Выключи гостевую ОС.
2) Укажи параметры для скрипта hyperv-dbg-2019.ps1.

1613206052600.png


Параметры для скрипта hyperv-dbg-2019.ps1

3) Запусти скрипт от имени администратора (или отключи UAC).
4) Запусти WinDbg следующей командой:

Код:
WinDBG -k net:port=50010,target=127.0.0.1,key=1.2.3.4

5) Выполни команду break (Ctrl-Break), после которой отладчик остановится внутри гостевой ОС. Теперь можно исследовать ВМ, используя стандартные команды WinDbg, но в моих экспериментах интенсивная отладка (например, трассировка) несколько раз приводила к тому, что все зависало.

ОТЛАДКА ЧЕРЕЗ ПРОТОКОЛ GDB​

VMware Workstation поддерживает встроенный GDB-отладчик. Чтобы его включить, нужно добавить несколько строк в конфигурационный файл VMware:

Код:
debugStub.listen.guest64 = "TRUE"
debugStub.listen.guest64.remote = "TRUE" — для подключения с других сетевых машин
debugStub.hideBreakpoints = "TRUE"
monitor.debugOnStartGuest64 = "TRUE" — остановка сразу же после включения VM

Затем ты можешь подключить IDA PRO, «Гидру» или Radare2 к активированному серверу GDB. Пример отладки через GDB-протокол будет показан в разделе «Загрузка гипервизора».

ОТЛАДКА ЭМУЛЯТОРА WINDOWS 10X​

Эмулятор Windows 10X доступен в магазине Microsoft Store. Этот эмулятор работает на базе Hyper-V. Сам эмулятор запускается как Hyper-V ВМ, Windows 10X — вложенная ВМ.

Необходимо смонтировать образ flash.vhdx (просто два раза щелкнуть мышью на файле), с которым работает эмулятор и который расположен в папке по следующему пути:

Код:
C:ProgramFilesWindowsAppsMicrosoft.Windows10XEmulatorImage10.0.19578.0Previ_1.0.1.0_x64__8wekyb3d8bbweContent

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

1613206238800.png

Состояние системы до монтирования

1613206261400.png

Состояние системы после монтирования

Выбери том с меткой VIRT_EFIESP:


Код:
Get-Volume | ? {$_.FileSystemLabel -eq "VIRT_EFIESP"} | Format-List
mountvol Z: \?Volume{12aef83a-6cf2-4ea1-932f-b3a586a65308}
bcdedit /store "Z:efiMicrosoftbootBCD" /dbgsettings

Команда bcdedit /enum all /v /store "Z:\efi\Microsoft\boot\BCD" покажет опции загрузочной записи операционной системы эмулятора. Чтобы у нас появилась возможность отладки гостевой ОС, понадобится дамп ядра, который можно получить с использованием встроенных функций эмулятора.

1613206344500.png

Получение дампа ядра

Открой Windows device portal — «Отладка». Загрузи live kernel dump, а затем открой его в WinDbg и запусти скрипт decypher_kdnet_key.py. Скрипт найдет параметры kdnet и закодирует в формате Base36.

1613206386700.png

Использование скрипта decypher_kdnet_key.py


Теперь запусти WinDbg, используя команду windbgx.exe -k net:port=50005,key=2k85xmoorkrbx.u7xg1f35gwi4.24033ib08wzhs.2o8xly2z2ik5y. В результате ты сможешь подключиться к ОС хоста.

1613206418700.png

Подключение к хостовой ОС

ОТЛАДКА HYPER-V C ПОМОЩЬЮ ПОДМЕНЕННОГО ЗАГРУЗЧИКА​

На эту тему опубликованы два исследования: Hyper-V backdoor Дмитрия Олексюка (@d_olex) и Voyager, созданный @_xeroxz. Их суть — в замене загрузочных файлов Windows в целях перехвата процесса загрузки гипервизора и интеграции своих управляющих модулей. Полноценной отладкой это сложно назвать, но с применением этого метода появляется возможность читать и изменять память Hyper-V. Подробности ты найдешь на страницах упомянутых проектов.

Загрузи последнюю сборку бэкдора и запусти скрипт bootkit_installer.ps1 в хостовой ОС (протестировано в виртуальной среде на Windows Server 2019 внутри VMware Workstation). Перезагрузим хостовую ОС и увидим следующую картину.

1613206461600.png

Запуск скрипта bootkit_installer.ps1

В гостевой ОС мы можем запустить backdoor_client.exe и получить доступ к различным структурам данных Hyper-V.

1613206492400.png

Доступ к различным структурам данных Hyper-V на гостевой ОС

Второй проект, Voyager, может быть загружен с сайта GitHacks. Бинарников он не содержит, поэтому их необходимо скомпилировать с помощью Visual Studio для подходящей версии Windows. После чего запустить файл launch.bat, который заменит загрузочные файлы Windows. После перезагрузки мы увидим следующую картину.

1613206529900.png

Загрузка ОС после применения Voyager

Для проверки работоспособности можно запустить example.exe внутри гостевой ВМ.

1613206554000.png

Проверка работоспособности Voyager

Надеюсь, мы увидим в будущем больше примеров для этого проекта.

ОТЛАДКА SECURE KERNEL​

Отладку позволяет выполнить модуль EXDi для LiveCloudKd без включения опции отладки в загрузчике гостевой ОС. Все подробности можно узнать в соответствующей документации.

ОТЛАДКА С ПОМОЩЬЮ RADARE2​

Radare2 — консольное средство отладки, поддерживающее очень много режимов. Мы рассмотрим только отладку ядра Windows. Бинарники можно загрузить с того же github.com по адресу https://github.com/radareorg/radare2/releases.

Незначительно изменив исходники, можно получить дополнительную информацию о Hyper-V (модифицированные бинарники приложены к статье). Для начала рекомендую почитать официальные источники, они содержат отличные инструкции.

До запуска необходимо скопировать следующие расширения WinDbg x64 в папку с Radare2:

Код:
ext.dll
exts.dll
kdexts.dll
kext.dll

Не забудь указать путь к папке с установленным WinDbg x64 в переменной окружения _NT_DEBUGGER_EXTENSION_PATH. Вот некоторые команды для тестирования успешности подключения:
  • pd — дизассемблирование;
  • xq @0x<address> — отображение региона памяти;
  • v — переключение в режим GUI.
Radare2 может подключаться к ядру Windows в двух режимах: через интерфейс dbgeng.dll и с использованием собственного протокола winkd.

Radare2 и интерфейс dbgeng.dll​

Сперва необходимо настроить гипервизор в режиме сетевой отладки, как это было описано раньше, и запустить Radare2 следующим образом:

Код:
radare2 -d "windbg://-k net:port=50011,key=1.2.3.4"

1613206653900.png

Запуск Radare2

Подключено! Теперь ты можешь выполнять стандартные команды WinDbg, используя префикс =!.

1613206883400.png

Выполнение стандартных команд отладчика

Radare2 и встроенный протокол​

Можно попробовать подключиться к гипервизору по сети, выполнив команду radare2 -D winkd winkd://192.168.174.1:50011:1.2.3.4. Я получил ошибку открытия UDP-сокета, хотя netstat показал, что порт открыт. Возможно, это ошибка настройки на моем стенде, но исправить ее мне не удалось. В связи с этим будем использовать отладку через COM-порт. Для этого нужно настроить гипервизор так, как это было описано раньше, запустить vmdemux и подключить Radare2 к именованному каналу:

Код:
radare2 -D winkd winkd://\\.\pipe\Vm0

Используя данные протокола отладки, можно получить дополнительную информацию о загруженном модуле Hyper-V.


image29.jpg

Получение дополнительной информации о загруженном модуле Hyper-V

Иногда Radare2 не может подключиться к COM-порту и виснет. В этом случае нужно просто сперва подключиться обычным WinDbg-отладчиком, отключиться и подсоединиться с помощью Radare2.


Cutter​

Cutter — GUI-фронтенд для Radare2, обладает достаточно интересными отладочными возможностями, но пока что находится в бета‑стадии. К тому же Cutter обладает встроенной поддержкой декомпилятора Ghidra, что делает его очень полезным. В настоящее время Cutter поддерживает отладку по GDB-протоколу и именованным каналам WinDbg. Мне удалось подключиться к начальной стадии загрузки ОС.

1613207207200.png

Подключение к начальной стадии загрузки ОС

QEMU​

QEMU поддерживает вложенную виртуализацию, но без ядерного акселератора работает очень медленно. Ускоряющий модуль KVM, поддерживающий вложенную виртуализацию, доступен на платформе Linux. Ради интереса рекомендую посмотреть проект Debugging secure kernel. Microsoft WHPX и Intel haxm пока что вложенную виртуализацию не поддерживают.


Ghidra + плагин ret-sync​

Ты можешь загрузить скомпилированную версию «Гидры» с официального сайта, а плагин ret-sync — с GitHub. Плагин позволяет синхронизировать различные отладчики между собой. Синхронизировать будем с WinDbg (хотя можно и с GDB).

Для создания проекта нужно выполнить следующие действия:

1) Запусти «Гидру», используя ghidraRun.bat.

2) Импортируй плагин ret-sync: File → Install extension, нажми зеленый плюсик. Выбери архив ZIP с плагином.

1613207292300.png

Импорт плагина ret-sync

3) Нажми ОK, перезапусти «Гидру».

4) Выполни команды File → New project. Non shared project. Укажи имя проекта и папку, в которой будут храниться служебные файлы.

5) Запусти CodeBrowser нажатием кнопки в панели Tool Chest. Ты увидишь сообщение об установке плагина ret-sync.

1613207367600.png

Сообщение об установке плагина ret-sync

6) Нажми ОK, появится окно с пустым проектом. Загрузи файл hvix64.exe, используя File → Import file.


1613207425000.png

Загрузка файла

7) Нажми OK. Файл будет загружен. После того как появится запрос на выполнение анализа, нажми Yes.

1613207461700.png

Нажми Yes, юзернейм!

8) Включи функцию Aggressive Instruction Finder.

1613207521300.png

Включение Aggressive Instruction Finder

9) Нажми OK. Прогресс операции можно увидеть в правом нижнем углу окна.

10) Далее появится сообщение о том, что файл hvix64.pdb отсутствует. Просто нажми OK.

11) Нажми Alt-S для активации плагина ret-sync, и ты увидишь следующие сообщения.

1613207588300.png

Сообщения в консоли

12) Подключи WinDbg к Hyper-V (например, по сети) и загрузи расширение ret-sync:

Код:
.load @”C:hv_debuggingsync.dll”
!sync

Если все прошло успешно, ты увидишь сообщение в консольном окне «Гидры».

1613207811900.png

Сообщение в консольном окне «Гидры»

Окно WinDbg будет отображать выполнение команд.

1613207866000.png

Выполнение команд в окне WinDbg

Для проверки я поставил точку останова на обработчик гипервызова HvPostMessage (F2) и затем запустил отладку (F5). Точка останова сработала.

1613207920800.png

Точка останова сработала

Комбинации клавиш ret-sync можно найти на официальной странице Radare2, опции плагина ret-sync для WinDbg отображаются в консоли по команде !synchelp.Ты можешь скопировать символьную информацию из IDA PRO в «Гидру» с использованием плагина Fake PDB.

1613208055800.png

Плагин Fake PDB

Интересно, что «Гидра» во время анализа hvix64.exe (сборка 10.0.17763.1577) нашла 4100 функций, в отличие от IDA PRO, которая обнаружила всего 3687 функций.

Загрузка гипервизора​

Вспомогательные компоненты загрузки гипервизора со временем менялись:

  • hvboot.sys — Windows Server 2008, 2008 R2;
  • hvloader.exe или hvloader.efi — Windows Server 2012 R2, 2016;
  • hvloader.dll — Windows 10, Windows Server 2019.
Отладка гипервизора с помощью WinDbg достаточно удобна, но не всегда возможна — например, когда нужно отладить secure kernel или среду со включенной опцией Secure Boot. Поэтому мы рассмотрим загрузку гипервизора при помощи GDB-отладки.

Для этого нам нужно загрузить в IDA PRO следующие файлы:

  • winload.efi (сборка 10.0.17763.1554);
  • hvloader.dll (сборка 10.0.17763.1577);
  • hvix64.exe (сборка 10.0.17763.1577).
Затем надо настроить для них опции отладки по GDB-протоколу. Для файлов hvix64.exe и hvloader.dll символы отсутствуют. Сперва мы должны найти адреса загрузки winload.efi и hvloader.dll с помощью WinDbg, затем отключить WinDbg, включить Secure Boot и продолжить отладку уже по протоколу GDB.

Для тестирования я использовал Windows Server 2019 c четырьмя CPU (для загрузки количество процессоров не так важно, но, как только загрузится гипервизор GDB, отладчик будет постоянно переключаться между контекстом гипервизора и ядра Windows). Сперва загрузим winload.efi. IDA PRO не показывает некоторые опции отладки, если бинарник имеет тип Windows boot application. Запусти свой любимый PE-редактор, выбери Optional header → Subsystem и поменяй Windows boot application на Windows GUI.

Для настройки отладки необходимо выбрать Debugger → Select Debugger → GDB, в поле Process Options указать Hostname 127.0.0.1 и port 8864.

1613208334600.png

Настройка отладки гипервизора

В гостевой ОС был активирован режим bootdebug on, поэтому после включения ОС загрузка остановится в процедуре winload!DebugService2.

Запусти WinDbg командой WinDBG.exe -b -k net:port=50002,key=1.2.3.4, и ты получишь адрес загрузки:

Код:
kd> lm
start end module name
00000000`008c4000 00000000`00aa5000 winload (pdb symbols)

Модуль winload.efi уже был открыт в IDA PRO, поэтому выбери Debugger → attach для подключения к GDB-серверу отладки VMware, запусти Edit → Segments → Rebase, укажи полученный ранее адрес winload.efi (0x008c4000) и нажми OK. Теперь дождись завершения процедуры и сохрани базу. Адрес загрузки winload.efi не изменится после перезагрузки, поэтому операция rebase не потребуется. Затем:

  • поставь точку останова на winload!OslArchHypervisorSetup и продолжи отладку (F9);
  • продолжи отладку в ранее запущенном WinDbg (F5).

Функция winload!OslGetHypervisorLaunchType проверяет, была ли установлена опция загрузки hypervisorlaunchtype (0x250000f0).

1613208434100.png

Опция загрузки hypervisorlaunchtype


1613208458600.png

Вызов функции HvlpLoadHvLoader


Если параметр был задан и его значение равно 1 (Auto), функция загружает hvloader.dll и получает адреса следующих функций, экспортируемых библиотекой:

  • HvlRescindVsm
  • HvlLaunchHypervisor
  • HvlLoadHypervisor
  • HvlRegisterRuntimeRange
  • HvlUpdateMcUpdateStatus
  • HvlPreloadHypervisor

1613208499000.png

Получение адресов функций, экспортируемых hvloader.dll

Далее выполняется функция winload!HvlpLoadHypervisor. После вызова CmpFindSkuType выполняется hvloader!HvlLoadHypervisor. Для отладки hvloader.dll мы должны переключиться между базами. C этой целью был написан скрипт для IDA PRO PatchHvLoader2019.py, который покажет базу загрузки hvloader (вернее, получит ее напрямую из базы winload.exe) и пропатчит функцию hvloader!HvlLoadHypervisor таким образом, чтобы она зациклилась (EB FE — jmp rip).

1613208537600.png

PatchHvLoader2019.py пропатчил hvloader!HvlLoadHypervisor

Скрипт требует ручного определения имен в базе IDA PRO: hvloader_image_base и p_HvlLoadHypervisor. Переменные расположены внутри функции winload!HvlpLoadHvLoader, это видно на следующей иллюстрации.

1613208568800.png


1613208589500.png

Переменные hvloader_image_base и p_HvlLoadHypervisor


Адрес hvloader_image_base нужно запомнить. Отключи текущую GDB-сессию и загрузи hvloader.dll в IDA. Подключись к GDB-серверу. CPU должен быть зациклен с помощью инструкции jmp rip. Теперь выполни Edit → segments → rebase и введи найденный адрес hvloader_image_base. Запусти RestoreHvLoader2019.py. Можно отлаживать hvloader.dll. Сперва hvloader получает все опции загрузки Windows и подготавливает hvix64.exe к отладке, если она была включена.

1613208612900.png

Подготовка hvix64.exe к отладке

Теперь у нас есть адрес загрузки winload.efi и hvloader.dll. Выключаем ВМ, включаем опцию SecureBoot (Option → Advanced → UEFI → Enable secure boot). Добавь строчку monitor.debugOnStartGuest64 = "TRUE" в конфигурационный файл ВМ (расширение .vmx) и запусти ВМ. Открой базу winload.efi в IDA PRO, подключись отладчиком к GDB-серверу VMware, и ты остановишься непосредственно на начальной процедуре запуска виртуальной операционной системы (где‑то на ранней стадии загрузки BIOS).

1613208640100.png

Начало загрузки BIOS

Нажми F9 и подожди, пока снова не произойдет остановка в процедуре winload!OslArchHypervisorSetup. Можно продолжать отладку, будут выполняться Winload.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.dll!p_HvlLaunchHypervisor. В свою очередь, Hvloader.dll!HvlLaunchHypervisor выполняет bootlib!BlGetExecutionEnvironment, bootlib!OslLoadMicrocodeUpdate и затем передает управление загруженному гипервизору.

1613208675900.png

1613208686900.png

Передача управления гипервизору

После выполнения инструкции mov cr3, rcx мы видим, что адреса памяти выше 0x3000 перестают быть доступны.

1613208710300.png

Адреса памяти выше 0x3000 перестают быть доступны

Однако Hvix64.exe уже загружен в 64-битное адресное пространство. Для доступа к памяти нужно вручную создать в IDA PRO область памяти для отладчика (manual memory region).

1613208742900.png


1613208760400.png

Создаем в IDA PRO область памяти для отладчика

Выделяемая область памяти имеет следующие начальный и конечный адреса:

Start address: FFFFFB0000000000
End Address: FFFFFCFFFFFFFFFF

В принципе, если отладчик не выдает ошибку, можно задать расширенный диапазон (0-0xFFFFFFFFFFFFFFFF). Если текущая инструкция выйдет за диапазон указанных адресов, то IDA PRO просто зависнет.

Выполни пошаговую отладку до инструкции jmp rdx, затем скрипт PatchHvix64_2019.py. Закрой базу hvloader.dll, открой hvix64.exe и снова подключись к GDB-серверу. Потом для поиска адреса загрузки гипервизора запусти RebaseHVGdb2019.py, затем — RestoreHvix64_2019.py, который возвращает назад замененные инструкции. Мы внутри hvix64.exe.

1613208800300.png


1613208827100.png


1613208850300.png

hvix64.exe

После выполнения инструкции vmlaunch мы вернемся в hvloader.dll, в точку vm_exit, которая была задана в поле vmcs, и загрузка ОС продолжится в обычном режиме.

1613208909100.png

Возврат из hvloader.dll

Если нужно отладить hvix64.exe с помощью GDB, сделай следующее:

  • запустить VMware в режиме отладки GDB и выполнить остановку на начальной стадии загрузки BIOS;
  • открыть базу данных с winload.efi, подключить к GDB и поставить точку останова на инструкции, которая вызывает hvloader!HvlLaunchHypervisor;
  • нажать F9;
  • запустить скрипт 1_PatchHvLoader2019.py;
  • закрыть базу IDA PRO с winload.efi, открыть базу с hvloader.dll и подключиться к GDB;
  • запустить 2_RestoreHvLoader2019.py;
  • создать точку останова на инструкции, передающей управление гипервизору (jmp r8);
  • запустить 3_PatchHvix64_2019.py;
  • закрыть базу данных с hvloader.dll, открыть базу данных с hvix64.exe и подключиться к GDB-серверу;
  • запустить скрипт 4_RebaseHVGdb2019.py;
  • запустить скрипт 5_RestoreHvix64_2019.py.

После этого можно отлаживать hvix64.exe (в скрипте забит стартовый адрес по смещению 0x7a). Следует отметить, что процесс загрузки гипервизора в Windows Server 2012 (и выше) существенно отличается от Windows Server 2008 R2, где подготовка и запуск гипервизора производится драйвером hvboot.sys, который запускается после загрузки ядра Windows. Активация гипервизора с помощью инструкции vmlaunch, выполненная в hvboot.sys, и следующий выход из ВМ обрабатывается hvix64.exe. Более поздние версии используют hvloader, который запускается непосредственно из winload.exe.

Поиск символьной информации​

С 2018 года многие компоненты Hyper-V имеют общедоступные символы. На момент публикации только hvix64.exe, hvax64.exe и hvaa64.exe с hvloader.dll не имели символов. Последние модули hvloader.exe (.efi) и hvloader.dll, имеющие символы, могут быть загружены для модулей, скомпилированных до марта 2018-го (я использовал символы hvloader.dll из Windows 10, сборка 17115, дата сборки — 03.03.2018).

При загрузке hvix64.exe в IDA PRO мы получаем около четырех тысяч функций с именами вроде sub_FFFFF8000XXXXX. Для ускорения исследования гипервизора можно сначала попытаться определить некоторые функции без подробного изучения. В первую очередь стоит использовать bindiff (или diaphora) для сравнения файлов hvix64, hvloader и winload, для которых предоставляется символьная информация. Сравнение показывает, что сетевая функция (e1000), USB, криптография и некоторые другие функции в точности такие же, как и в winload.exe (в Windows Server 2019 и Windows 10 функции отладки Hyper-V и сетевого драйвера были перемещены в отдельные модули, например bootlib.dll). Тот же самый bindiff позволяет перемещать имена совпадающих функций из одной базы данных в другую. Однако к этому методу стоит отнестись с осторожностью и не переносить сразу все полностью совпавшие функции. По крайней мере, проанализируй результат: сравни графы совпавших функций (Ctrl-E).

Далее надо определить функции обработки прерываний и исключений, стандартные для процессоров архитектуры x86. Облегчит эту задачу небольшой скрипт на Python (ParseIDT.py) для парсинга IDT. Его необходимо запускать в IDA PRO, предварительно подключившись через отладочный модуль WinDbg к гипервизору. Если часть ISR не была найдена, следует проверить вкладку List of problems в IDA PRO, так как IDA может не найти эти процедуры автоматически.

Далее можно определить процедуру выхода VM exit, прочитав значения полей VMCS: изучи процедуру заполнения VMCS в hvix64.exe или же воспользуйся скриптом display-vmcs.py, который в контексте гипервизора считывает все поля VMCS и выводит их значения. Есть хорошие скрипты IDA-Python от Вехруза Аббасси (Behrooz Abbassi — @rceninja): ia32_msr_decoder.py и IA32_VMX_Helper.py. С их помощью можно получить символические имена полей MSR и VMCS внутри базы данных IDA.

Хорошие новости: здесь присутствуют символы hvix64.exe, hvax64.exe, hvboot.sys для Windows Server 2008. Плохая новость заключается в том, что Windows Server 2008 уже давно не обновляется и не включает в себя многих новых функций Hyper-V. Но ты можешь изучить базовый механизм работы Hyper-V и реализацию гипервызовов в сравнении с Hyper-V TLFS 1.0.

Очень хороший заголовочный файл hvgdk.h, содержащий актуальную информацию о Hyper-V (о структурах гипервизора Windows 10 и Windows Server 2019), создал Алекс Ионеску (@aionescu).

Утилиты​

В последние годы было разработано множество полезных системных утилит. Я не буду описывать утилиты Sysinternals, потому что они знакомы всем, кто занимается исследованием внутреннего устройства Windows. Еще существует интересный набор утилит от Павла Йосифовича (@zodiacon), который известен как один из авторов седьмого издания первой части книги «Внутреннее устройство Windows». Они похожи на утилиты Sysinternals, но поставляются с открытым исходным кодом.

С помощью ETWProvider можно посмотреть список ETW-провайдеров, используемых компонентами Hyper-V в работающей системе.

image66.jpg

Утилита ETWProvider

С использованием утилиты DrvMon можно увидеть взаимодействие ядерных компонентов и компонентов, запущенных в пользовательском режиме.

1613209227700.png

Утилита DrvMon

Набор утилит для диагностирования от Microsoft также может быть использован для получения дополнительной информации о работе компонентов Hyper-V. Не менее полезны утилиты для сбора событий ETW:

  • VMLtrace;
  • Fruti;
  • tss_VMLverbosity.ps1;
  • V_Tracing_Using_Channels.ps1.


image68.jpg

VMLtrace и Fruti

image69.jpg

tss_VMLverbosity.ps1 и V_Tracing_Using_Channels.ps1

Гипервызовы​

Последняя версия документа «Hypervisor Top-Level Functional Specification» для Windows Server 2019 — 6.0b — описывает интерфейсы Hyper-V и внутреннее устройство некоторых компонентов гипервизора. Каждая виртуальная машина, а также непосредственно ОС с установленным компонентом Hyper-V представляется в виде раздела (partition). У каждого раздела есть свой идентификатор, который должен быть уникальным в рамках хост‑сервера и имеет 64-битное значение.

Для каждого раздела при создании задаются привилегии (структура HV_PARTITION_PRIVILEGE_MASK), которые и определяют возможность выполнения конкретных гипервызовов. Узнать привилегии можно, выполнив в root-partition следующий код в ring0:


Код:
WinHvGetPartitionId(&PartID);// id раздела
WinHvGetPartitionProperty(PartID,HvPartitionPropertyPrivilegeFlags,&HvProp); // Свойства раздела возвращаются в HvProp

Здесь HvPartitionPropertyPrivilegeFlags — одно из значений перечисления HV_PARTITION_PROPERTY_CODE, которыми оперируют функции, экспортируемые драйверами winhvr.sys и winhv.sys.

Код:
HV_STATUS
WinHvGetPartitionProperty(
__in HV_PARTITION_ID PartitionId,
__in HV_PARTITION_PROPERTY_CODE PropertyCode,
__out PHV_PARTITION_PROPERTY PropertyValue
);


Также при необходимости эти привилегии можно поменять, вызвав в root-partition следующую функцию:

Код:
HV_STATUS
WinHvSetPartitionProperty(
__in HV_PARTITION_ID PartitionId,
__in HV_PARTITION_PROPERTY_CODE PropertyCode,
__in HV_PARTITION_PROPERTY PropertyValue
);

Значение HvPartitionPropertyPrivilegeFlags для раздела Windows Server 2019: 002BB9FF00003FFF.

1613209676900.png

1613209695600.png


Значение HvPartitionPropertyPrivilegeFlags для гостевого раздела: 003B80B000002E7F.

В гостевой ОС привилегии можно получить, поместив в EAX 0x40000003 и выполнив инструкцию CPUID (в документе Hyper-V TLFS 6.0b дана расшифровка результатов CPUID).

EAX =00002E7F (101110 01111111) — биты 31-0 HV_PARTITION_PRIVILEGE_MASK
EBX =003B8030 (111011 10000000 00110000) — биты 63-32 HV_PARTITION_PRIVILEGE_MASK
ECX =00000002 (10) — зарезервировано
EDX =00BED7B2 (10111110 11010111 10110010)
Bit 1: Guest debugging support is available
Bit 4: Support for passing hypercall input parameter block via XMM registers is available
Bit 5: Support for a virtual guest idle state is available
Bit 7: Support for querying NUMA distances is available
Bit 8: Support for determining timer frequencies is available
Bit 9: Support for injecting synthetic machine checks is available.
Bit 10: Support for guest crash MSRs is available
Bit 12: Support for NPIEP is available
Bit 14: ExtendedGvaRangesForFlushVirtualAddressListAvailable
Bit 15: Support for returning hypercall output via XMM registers is available
Bit 17: SintPollingModeAvailable
Bit 18: HypercallMsrLockAvailable
Bit 19: Use direct synthetic timers
Bit 20: Support for PAT register available for VSM
Bit 21: Support for bndcfgs register available for VSM
Bit 23: Support for synthetic time unhalted timer available
В гипервизоре можно получить привилегии раздела, который выполнил операцию, вызвавшую VM exit, если вычислить значение gs:0. Для этого нужно прочитать значение поля HOST_GS_BASE в VMCS или же IA32_GS_BASE MSR:

Код:
WINDBG>rdmsr 0xc0000101
msr[c0000101] = fffffbdb`a68c2000

Затем следует получить значение, на которое указывает gs:83a8, и перейти по смещению 0xd8.

Код:
WINDBG>dc poi(fffffbdb`a68c2000+0x83a8)+d8
ffffe800`000010d8 00003fff 002bb9ff 00000000 ffffe800 .?….+……...
ffffe800`000010e8 00000000 00000000 00216560 ffffe800 ……..`e!…..
ffffe800`000010f8 00000001 00000000 00000000 00000000 …………….
ffffe800`00001108 002342c0 ffffe800 00000000 00000000 .B#………….

В данном случае VM exit был выполнен из root-partition. Гипервизор в каждом из разделов формирует специальную страницу для выполнения гипервызовов. Ее адрес можно получить, прочитав MSR 0x40000001 (HV_X64_MSR_HYPERCALL).

Windows Server 2019 на Windows Server 2019:

Код:
kd> rdmsr 0x40000001
msr[40000001] = 00000000`00767000

kd> up 00000000`00767000 L50
kd> up 00000000`00767000 L50
00000000`00767000 0f01c1 vmcall
00000000`00767003 c3 ret
00000000`00767004 8bc8 mov ecx,eax
00000000`00767006 b811000000 mov eax,11h
00000000`0076700b 0f01c1 vmcall
00000000`0076700e c3 ret
00000000`0076700f 488bc1 mov rax,rcx
00000000`00767012 48c7c111000000 mov rcx,11h
00000000`00767019 0f01c1 vmcall
00000000`0076701c c3 ret
00000000`0076701d 8bc8 mov ecx,eax
00000000`0076701f b812000000 mov eax,12h
00000000`00767024 0f01c1 vmcall
00000000`00767027 c3 ret
00000000`00767028 488bc1 mov rax,rcx
00000000`0076702b 48c7c112000000 mov rcx,12h
00000000`00767032 0f01c1 vmcall
00000000`00767035 c3 ret
00000000`00767036 90 nop
00000000`00767037 90 nop

Чтобы иметь возможность использовать экспортируемые функции winhv.sys и winhvr.sys, можно либо динамически вычислять адреса функций, либо создать lib-файл. Рассмотрим второй вариант. Для создания def-файла используем вывод команды dumpbin:

Код:
dumpbin /exports winhv.sys

Windows Server 2016 и новее используют драйвер winhvr.sys для root-раздела, таким образом def-файл для драйвера, предназначенного для работы на хост‑сервере, необходимо формировать на основе этого файла. Для сборки 64-битного драйвера правки вносить не нужно. Формирование lib-файла выполняется следующей командой (для x86):

Код:
lib.exe /def:winhv.def /OUT:winhv.lib /machine:x86

Для x64:

Код:
lib.exe /def:winhvr.def /OUT:winhvr.lib /machine:x64

Перед выполнением команд не забудь запустить Visual Studio native tools. Мы можем найти таблицу гипервызовов в файле hvxi64.exe, используя специальный скрипт. Скрипт создает таблицу наподобие показанной на иллюстрации ниже.

1613209883600.png

Пример таблицы, создаваемой скриптом CreatemVmcallHandlersTable2019.py

Мы можем отобразить значения VMCS полей внутри hvix64.exe, используя скрипт display-vmcs.py. Скрипт необходимо запустить в IDA PRO для файла hvix64.exe при подключенной отладочной сессии к гипервизору. Скрипт формирует и вызывает процедуру

Код:
vmread rax, rax
jmp —3

Он считывает значение регистра rax и отображает его в консоли IDA PRO. Для сравнения вот некоторые значения VMCS.

1613209949600.png

Например, ты можешь увидеть, что гостевой раздел гипервизора обрабатывает весь поток информации, проходящей через порты ввода‑вывода (I/O exiting Unconditional), а для root-раздела выполняется перехват только некоторых портов (используется I/O bitmaps).

Код:
WINDBG>!db 0x101001000 L1300

#101001000 00 00 00 00 03 00 00 00-00 00 00 00 10 00 00 00 ................
#101001010 00 00 00 00 03 00 00 00-00 00 00 00 00 00 00 00 ................
...
#101001080 00 00 00 00 00 00 00 00-20 00 00 00 00 00 00 00 ........ .......
...
#101001190 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 f1 ................

Вывод​

В статье было описано создание стенда для исследования Hyper-V, а также очень кратко описаны некоторые нюансы работы гипервизора. Надеюсь, эта информация пригодится начинающим исследователям безопасности гипервизора компании Microsoft.

Автор: Артур Худяев
Источник: Xakep.ru
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх