Acpi vmbus 4 4b018eb 0

Acpi vmbus 4 4b018eb 0

Программирование, извращения и всё остальное

пятница, 17 сентября 2010 г.

Проблемы с VMBus при миграции с Virtual PC на Hyper-V

Тут перетаскивали локальную виртуалку на Висте с Virtual PC на Hyper-V. При этом вылезла проблема с тем, что виртуалка на новом месте не видела сети (только Legacy) безумно тормозила (100% загрузки процессора и почти всё время в ядре), в списке устройств лежал неработающий VMBus (это виртуальное устройство от Hyper-V).

Естественно, это всё было после удаления гостевых служб от Virtual PC и установки соответствующих от Hyper-V, танцы с бубном не помогали.

Решение нагуглилось, но с трудом, поэтому и решил поделиться им. Для этого нужно всего-лишь:

  1. Запустить msconfig
  2. Выбрать вкладку boot (загрузка), Advanced Options (Дополнительные опции)
  3. Поставить галочку "Detect HAL" (Обнаружение HAL)
  4. Перегрузиться

После этого всё должно замечательно работать. Как я понимаю проблема в том, что идёт обновление ядра, а система не понимает этого и использует бракованное ядро, занимаясь усиленным самокопанием.

Ещё возможно потребуется переустановить гостевые дополнения (кстати, для них рекомендуется включить Windows Update Services, иначе говорят что бывают проблемы), но это уже совсем другая история.

Если бы работа хакера, а точнее программиста-исследователя происходила так, как это показано в классических фильмах: пришел, постучал по клавишам, на экране все замелькало зеленым, пароли взломались, а деньги внезапно переехали из пункта А в пункт В, — то жить было бы однозначно проще и веселее. Но в действительности любому серьезному хаку всегда предшествует основательная и скучная аналитическая работа. Вот ею мы и займемся, а результаты выкатим на твой суд в виде цикла из двух статей. Убедись, что у тебя есть достаточный запас пива и сигарет, — прочтение таких материалов опасно для неподготовленного мозга :).

Обнаружение бага, получившего впоследствии номер MS13-092 (ошибка в компоненте Hyper-V Windows Server 2012, позволяющая отправить гипервизор в BSOD из гостевой ОС или выполнить произвольный код в других гостевых ОС, запущенных на уязвимом хост-сервере), стало очень неприятным сюрпризом для инженеров Microsoft. До этого в течение почти трех лет никто не обнаруживал уязвимости в Hyper-V. До нее была только MS10-102, которую нашли в конце 2010 года. За эти четыре года популярность облачных сервисов сильно возросла, и исследователи проявляют все больший интерес к безопасности гипервизоров, лежащих в основе облачных систем. Однако количество публично доступных работ крайне невелико: исследователи неохотно тратят свое время на изучение таких сложных и плохо документированных архитектурных решений. В этой статье не рассказано о конкретных уязвимостях гипервизора, но она должна пролить свет на работу некоторых внутренних механизмов Hyper-V и тем самым частично упростить будущие исследования.

Перед прочтением статьи рекомендуется ознакомиться с отчетом ERNW, материалом «Hyper-V debugging for beginners», а также с официальным документом Hypervisor TLFS.

VMBus

Во время написания статьи в качестве Hyper-V-сервера и гостевой ОС использовалась Windows Server 2012 R2 Update 1 (тип машины — Generation 1), но для отражения некоторых особенностей работы шины были использованы и другие версии операционных систем Windows, что явно будет указано в статье. Тестовую среду лучше разворачивать в VMware Workstation 2014 July TechPreview или поздних, поскольку в более ранних версиях баг в Workstation не позволяет выполнять отладку виртуальных машин по сети (либо необходимо в конфигурации виртуальной машины принудительно указывать использование UEFI). Также в дальнейшем будет подразумеваться, что стенд развернут на аппаратной платформе Intel и функции гипервизора реализованы в hvix64.exe.

Термины и определения

  • Root-раздел (родительский раздел, root ОС) — Windows Server 2012 R2 с включенным компонентом Hyper-V;
  • Гостевая ОС — виртуальная машина Hyper-V с установленной Windows Server 2012 R2;
  • TLFS — Hypervisor Top-Level Functional Specification: Windows Server 2012 R2;
  • LIS — Linux Integration Services;
  • ACPI — Advanced Configuration and Power Interface

О Vmbus

Если говорить кратко, то VMBus — это технология взаимодействия гостевых операционных систем и root ОС. Соответственно, как в гостевой, так и в root ОС присутствуют компоненты, реализующие это взаимодействие через интерфейсы, предоставляемые гипервизором и описанные в TLFS 4.0. Microsoft разрабатывает гостевые компоненты для операционных систем семейства Linux, которые интегрированы в ядро Linux и выложены отдельно на GitHub: github.com/LIS/LIS3.5.

Начиная с Windows Server 2008 в ядре Windows появились функции, оптимизирующие работу операционной системы в виртуальной среде Hyper-V. Для сравнения, в ядре Windows Server 2008 (x64) реализовано всего 25 функций с префиксом Hvl, который идентифицирует их принадлежность к библиотеке интеграции с гипервизором, в Windows Server 2012 R2 уже присутствует 109 Hvl-функций.

Читайте также:  Asrock утилита для обновления bios

Рассмотрим, каким же образом компоненты шины VMBus взаимодействуют с гипервизором, root ОС и гостевой ОС. Сперва заглянем в исходные коды LIS и увидим, что VMBus — это устройство, поддерживающее ACPI. ACPI позволяет стандартизировать аппаратную платформу для различных операционных систем и реализован в Hyper-V (как, впрочем, и в других популярных платформах виртуализации), что позволяет использовать стандартные утилиты для получения необходимой для исследования информации.

ACPI-устройства можно просмотреть при помощи утилиты ACPI tool, входящей в старую версию AIDA64 (в более поздних она была удалена). С ее помощью в _SB.PCI0.SBRG обнаруживаются два устройства: VMB8 и VMBS (см. рис. 1).


Рис. 1. Устройства VMB8 и VMBS

Сдампим ACPI DSDT (Differentiated System Description Table) таблицу, которая содержит информацию о периферийных устройствах и дополнительных функциях аппаратной платформы, с помощью той же утилиты ACPI Tool и декомпилируем AML-дизассемблером в ASL. Получим дамп, показанный на рис. 2.


Рис. 2. Дамп ASL

Поверхностное чтение Advanced Configuration and Power Interface Specification 5.0 дало понять, что в случае, если гостевая ОС — Windows 6.2 и выше, то будет задействовано устройство VMB8, в противном случае — VMBS. Единственное отличие этих устройств — объект _UID (Unique ID), который присутствует в VMB8. Если верить спецификации на ACPI, то присутствие этого объекта в таблице опционально и требуется только в том случае, если устройство не может иными способами предоставить операционной системе постоянный уникальный идентификатор устройства. Также стали известны ресурсы, которое использует устройство, — прерывания 5 и 7.

Для сравнения: в виртуальной машине типа Generation 2 присутствует только устройство VMBS, размещенное в _SB_.VMOD.VMBS (но с объектом _UID), которое использует только прерывание 5 (см. рис. 3).


Рис. 3. Часть ASL дампа Gen2

Обработка прерываний в виртуальной среде

В Windows обработку прерываний выполняют процедуры, зарегистрированные в таблице диспетчеризации прерываний (IDT). Между обнаруженными нами в ACPI DSDT IRQ 5 и 7 и обработчиками в IDT прямой связи нет, и для того, чтобы сопоставить прерыванию его обработчик, Windows использует арбитр прерываний (вообще, существует несколько классов арбитров, помимо IRQ, — DMA, I/O, memory).

Все об арбитрах в блоге MSDN

Информацию о зарегистрированных арбитрах можно увидеть в WinDBG при помощи команды !acpiirqarb.

kd> !acpiirqarb — Для гостевой Windows Server 2012 R2 Gen1 (рис. 4):


Рис. 4. !acpiirqarb Windows Server 2012 R2 Gen1 Guest

Вывод команды показывает, что для IRQ 7 адрес обработчика будет находиться в 0x71 элементе IDT, для IRQ 5 — в 0x81. Генерация номеров обработчиков прерываний происходит в функции acpi!ProcessorReserveIdtEntries на этапе построения дерева устройств PnP-менеджером, когда функциональный драйвер устройства еще не загружен. Регистрация ISR в IDT происходит уже на более поздних этапах, например при выполнении процедуры IoConnectInterrupt самим драйвером устройства. Однако, просмотрев элементы IDT, мы увидим, что ISR для прерываний 0x71 и 0x81 не зарегистрированы:

В Windows Server 2012 R2 Gen2 для IRQ 5 был сопоставлен 0x90-й элемент IDT.

Однако, как показывает отладчик, ISR-процедура для вектора 0x90 также не определена:

В Windows 8.1 x86 мы видим несколько иную картину:

При этом для прерывания с номером 0x81 определена ISR-процедура vmbus!XPartPncIsr:

s3cap — вспомогательный драйвер для работы с эмулируемой Hyper-V видеокартой S3 Trio.


Vmbus interrupt object

Таким образом, ISR vmbus!XPartPncIsr регистрируется в IDT только в Windows 8.1 x86 (предположительно, в других x86 операционных системах, которые Microsoft поддерживает в качестве гостевых ОС для Hyper-V, используется такой же метод). Процедура vmbus!XPartPncIsr используется для обработки прерываний, генерируемых гипервизором.

В x64-битных системах, начиная с Windows 8Windows Server 2012, интеграция с гипервизором реализована несколько иначе. В IDT операционных систем были добавлены обработчики системных прерываний, генерируемых гипервизором. Кратко рассмотрим, каким образом формируется IDT на этапе загрузки Windows.

После инициализации загрузчика Windows winload.efi IDT выглядит следующим образом (вывод скрипта на pykd в точке останова WinDBG в winload.efi при загрузке операционной системы с параметром /bootdebug):

Затем во время выполнения winload!OslArchTransferToKernel IDT обнуляется, управление передается ядру Windows, где в функции nt!KiInitializeBootStructures IDT инициализируется значениями из таблицы KiInterruptInitTable:

Соответственно, обработчики системных прерываний 0x30–0x34 после завершения инициализации будут выглядеть следующим образом:

Читайте также:  B85h3 ad2 материнская плата

Виртуальную машину второго поколения в Hyper-V можно создать только на базе ОС, содержащих в ядре пять описанных выше дополнительных обработчиков. В целях генерации прерываний Intel представляет аппаратную функцию virtual interrupt delivery, однако Hyper-V не использует указанную возможность для передачи управления на эти обработчики. Вместо этого в гипервизоре происходит активация бита, соответствующего номеру вектора, в специальной области памяти с помощью инструкции вида lock bts [rcx+598h], rax, где rax — номер вектора прерывания (0x30–0x32), так что, возможно, разработчики Hyper-V сочли вариант с регистрацией процедуры vmbus!XPartPncIsr в качестве обработчика менее производительным решением, чем вариант генерации прерываний посредством виртуализации APIC на основе данных в виртуальных регистрах SINTx.

Указанные обработчики регистрируются в IDT даже в том случае, если операционная система работает вне среды Hyper-V. Каждый обработчик вызывает HvlRouteInterrupt, передавая индекс в качестве параметра (см. рис. 6).


Рис. 6. Дополнительные системные обработчики ядра Windows

HvlRouteInterrupt выглядит следующим образом (рис. 7).


Рис. 7. HvlRouteInterrupt

Эта функция вызывает обработчик из массива указателей HvlpInterruptCallback в зависимости от значения индекса. Этот массив в root ОС выглядит так:

XPartEnlightenedIsr по индексу, переданному из KiVmbusInterruptX, добавляет в DPC-очередь одну из двух возможных функций из массива DPC-структур в vmbusr: vmbusr!ParentInterruptDpc или же vmbusr!ParentRingInterruptDpc (рис. 8).


Рис. 8. DPC-объекты

Количество структур DPC в массиве определяется функцией vmbusr!XPartPncPostInterruptsEnabledParent и зависит от количества логических процессоров в root ОС. Для каждого логического процессора добавляется DPC c vmbusr!ParentInterruptDpc и vmbusr!ParentRingInterruptDpc. Функция vmbusr!ParentRingInterruptDpc определяет адрес DPC-процедуры для nt!KeInsertQueueDpc исходя из того, на каком процессоре выполняется в текущий момент.

В гостевой ОС VMBus регистрирует в массиве HvlpInterruptCallback только один обработчик:

Массив HvlpInterruptCallback заполняется с помощью экспортируемой ядром функции nt!HvlRegisterInterruptCallback. Обработчик WinHvOnInterrupt регистрируется при загрузке драйвера winhvr.sys (winhvr!WinHvpInitialize-> winhvr!WinHvReportPresentHypervisor-> winhvr!WinHvpConnectToHypervisor-> nt!HvlRegisterInterruptCallback)/

Остальные четыре обработчика регистрируются драйвером vmbusr.sys при его загрузке PnP-менеджером (vmbusr!RootDevicePrepareHardwareParent-> nt!HvlRegisterInterruptCallback).

Попробуем разобраться, каким же образом гипервизор передает управление на обработчики системных прерываний. Для этого необходимо обратиться к разделу Virtual Interrupt Control в TLFS. Если кратко, то Hyper-V управляет прерываниями в гостевой ОС через синтетический контроллер прерываний (SynIC), который является расширением виртуализованного локального APIC и использует дополнительный набор регистров, отображаемых на память (memory mapped registers). То есть каждый виртуальный процессор, помимо обычного APIC, обладает дополнительным SynIC. SynIC содержит две страницы: SIM (synthetic interrupt message) и SIEF(synthetic interrupt event flags). SIEF и SIM — это массивы из 16 элементов, размер элемента — 256 байт. Физические адреса (если быть точнее — GPA) этих массивов расположены в MSR-регистрах SIEF и SIMP соответственно. Адреса этих страниц для каждого логического процессора будут разными. Также для SynIC определены 16 регистров SINTx. Каждый из элементов массивов SIEF и SIM сопоставлен с соответствующим регистром SINTx. WinDBG показывает содержимое регистров SINTx с помощью команды !apic (начиная с WinDBG 6.3).


!apic в root ОС


!apic в гостевой ОС

Конфигурирование регистров SINT0 и SINT1 выполняется функцией nt!HvlEnlightenProcessor путем записи параметров в MSR-регистры 40000090h и 40000091h соответственно. SINT4 и SINT5 конфигурируются драйвером vmbusr.sys: vmbusr!XPartPncPostInterruptsEnabledParent-> winhvr!WinHvSetSint->winhvr!WinHvSetSintOnCurrentProcessor. SINT2 в гостевой ОС конфигурируется драйвером vmbus.sys в функции winhv!WinHvSetSintOnCurrentProcessor.

В каждом SINTx присутствует 8-битное поле Vector. От значения этого поля зависит то, какой процедуре обработки прерываний будет передано управление при выполнении гипервызовов, в параметрах которых задается PortID (HvSignalEvent, HvPostMessage).

SINTx может быть задан неявно (например, для сообщения перехвата всегда будет контролироваться регистром SINT0 и соответственно располагаться в первом элементе страница SIM), явно (для сообщений таймера) или же указан в параметрах порта, созданного с помощью гипервызова HvCreatePort. Одним из параметров является PortTypeInfo. Если тип порта — HvPortTypeMessage или HvPortTypeEvent, то в параметре PortTypeInfo присутствует TargetSint, содержащий номер SINT, к которому будет привязан порт и значение которого может быть в пределах от 1 до 15 (SINT0 зарезервирован для сообщений от гипервизора и не может быть указан в качестве TargetSint при создании порта).

Анализ значений активных регистров SINT в root ОС показывает, что в работе будут задействованы только три обработчика системных прерываний (KiHvInterrupt, KiVmbusInterrupt0, KiVmbusInterrupt1) из пяти. В каких целях в ядро были добавлены системные обработчики KiVmbusInterrupt2 и KiVmbusInterrupt3, обнаружить не удалось. Возможно, они будут нужны на серверах с большим количеством логических процессоров (например, 64), но, к сожалению, в тестовой среде это проверить не удалось. Также по значениям регистров SINTx видно, что обработчик nt!KiHvInterrupt (вектор 30) будет вызываться как при генерации прерываний от гипервизора, так и через порты, созданные с параметром TargetSint, равным 1.

Читайте также:  Asus fonepad 8 материнская плата

Windows и TLFS

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


Рис. 11. Порты служб интеграции

Взаимодействие root ОС и гостевой ОС в ходе работы компонентов Integration Services происходит через 5-й элемент массива SIEF, то есть обработчиком в root ОС будет KiVmbusInterrupt1.

Номер каждого следующего создаваемого порта равен предыдущему, увеличенному на 1. То есть если отключить все сервисы интеграции и затем включить их повторно, то номера портов, создаваемых для этих сервисов, будут находиться в диапазоне от 0x22 до 0x27.

Параметры порта можно увидеть, если подключиться отладчиком непосредственно к гипервизору и отслеживать данные, передаваемые обработчику гипервызова HvCreatePort, или же подключиться отладчиком к ядру и отслеживать параметры функции WinHvCreatePort в драйвере winhvr.sys.

Остальные порты, которые создаются при включении гостевой ОС (количество портов зависит от конфигурации гостевой операционной системы), представлены на рис. 12. Нумерация приведена в порядке создания портов при включении виртуальной машины Windows Server 2012 R2 с конфигурацией оборудования по умолчанию.


Рис. 12. Порты, создаваемые при запуске виртуальной машины00000000000000.

Важно отметить тот факт, что нулевой слот SIM как в гостевой, так и в родительской ОС зарезервирован для передачи сообщений от гипервизора. Формат таких сообщений документирован в TLFS. При передаче данных через оставшиеся слоты используется иной формат данных. Сообщения VMBus не документированы, но необходимая информация для работы с ними присутствует в исходных кодах LIS.

Некоторая информация об обработке VMBus-сообщений драйвером vmbusr.sys (см. рис. 13). Такие сообщения в root ОС обрабатывает функция vmbusr!ChReceiveChannelMessage, которая анализирует содержимое 4-го слота SIM и определяет код VMBus-сообщения. Если он равен 0 (CHANNELMSG_INVALID) или же больше 0x12, то функция возвращает ошибку и 0xC000000D (STATUS_INVALID_PARAMETER). В противном случае функция обрабатывает переданное гостевой или root ОС сообщение. Например, при включении компонента Guest Services root ОС отправляет гостевой ОС сообщение CHANNELMSG_OFFERCHANNEL, в ответ гостевая ОС отправляет сообщение CHANNELMSG_GPADL_HEADER, затем root ОС отправляет CHANNELMSG_GPADL_CREATED, получает обратно сообщение CHANNELMSG_OPENCHANNEL и в завершение диалога отправляет гостевой ОС сообщение CHANNELMSG_OPENCHANNEL_RESULT с кодом результата выполнения операции по созданию канала. Стоит обратить внимание на то, что перед обработкой каждого валидного сообщения функция ChReceiveChannelMessage выполняет проверку переданного сообщения (ChpValidateMessage), в частности на предмет того, кто является отправителем (root ОС или гостевая ОС), минимального размера тела сообщения. Для каждого типа сообщения заданы свои условия проверки. На рис. 13 отмечены те сообщения, которые будут обрабатываться в случае их отправки гостевой ОС (могут быть интересны, например, для создания фаззера).


Рис. 13. VMBus-сообщения, обрабатываемые драйвером vmbusr.sys

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

Заключение

В первой части статьи были проанализированы изменения ядра операционной системы, внесенные Microsoft для оптимизации работы в виртуальной среде, влияющие на работу VMBus. В этом номере ][ мы разобрали теорию, а в следующем будет опубликована практическая часть исследования, поэтому запасайся терпением.


Впервые опубликовано в журнале «Хакер» от 11/2014.

Подпишись на «Хакер»

  • Бумажный вариант
  • «Хакер» на iOS/iPad
  • «Хакер» на Android

Windows DLL файлы
В этом разделе размещен архив dll файлов. Вы можете скачать vmbus.sys бесплатно.

Инструкции по регистрации DLL файлов в Windows 98, XP, Vista, 7:
Если у Вас возникла ошибки, связанная с файлами *.dll и *.ocx, необходимо:

1. Проверить наличие в системе требуемых файлов. Файлы *.dll и *.ocx, как правило, должны быть расположены в системной папке C:WINDOWSsystem32.
Если файлы присутствуют, нужно зарегистрировать их.
— Нажать на “Пуск/Выполнить” или нажать сочетания клавиш Win + R
или

— Ввести regsvr32 vmbus.sys (например: regsvr32 vmbus.sys )

— Перезагрузить компьютер
2. Если требуемых файлов нет, то поищите их на сайте, скачайте и скопируйте в папку C:WINDOWSsystem32 и зарегистрировать как указано в первом пункте. A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

Ссылка на основную публикацию
Adblock detector