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

19 Дек 2015

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

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

А между тем, подобно известной истории про «неуловимого Джо», ответ прост и лежит на поверхности. Согласно сайту sandpile, принадлежащего Кристиану Людлоффу, идентификация виртуального процессора ничуть не сложнее аналогичной процедуры для процессора физического и выполняется с помощью инструкции CPUID, ряд функций которой резервируются для эмуляции гипервизором.

 

Низкоуровневые подробности

Напомним, инструкция CPUID, получает в регистре EAX номер функции в качестве входного параметра. Нумерация стандартных функций, ведется от 0. Для расширенных функций, появившихся с подачи «альтернативных» производителей процессоров, резервируются значения от 80000000h. Виртуальные функции, реализуемые гипервизорами, ведут свою нумерацию от 40000000h.

Сигнатуры, резервируемые для виртуальных машин
Рис.1. Некоторые сигнатуры, резервируемые виртуальными машинами. По материалам сайта www.sandpile.org

Зачем это нужно

Вспомним пример с агрессивным сканированием PCI-шины. Речь шла о методе обнаружения «незаконных» с точки зрения стандарта регистровых блоков многофункционального PCI-устройства, у которого отсутствует функция 0. С тех пор, как системная логика стала программно-конфигурируемой, ответственность за подобные отклонения перекладывается с разработчиков микросхем чипсета на разработчиков UEFI firmware. В низкоуровневом программном обеспечении компании American Megatrends указанная ситуация имеет место.

Итак, «агрессивное» сканирование (а именно, опрос PCI-функций устройства, у которого отсутствует функция 0) позволяет увидеть немного больше, чем «законопослушное». А обращения по неиспользуемому адресу благополучно завершаются получением кода FFFFh или «все единицы» в качестве содержимого регистров, что позволяет сделать вывод об отсутствии адресуемого устройства. Неудивительно, что благодаря изящности и бесконфликтности такого метода, ряд разработчиков информационно-диагностических утилит взяли его на вооружение.

Совсем иначе обстоит дело при выполнении сканера ресурсов на виртуальной машине. Так как конфигурационные регистры находятся в пространстве памяти (memory-mapped configuration), гипервизор виртуальной машины должен подготовить картирующий контекст или массив дескрипторов страниц (page table entries), описывающий диапазоны адресного пространства, доступ к которым он считает «законным». Для остальных диапазонов контекст может быть не инициализирован. Предположительно, именно это обстоятельство приводит к аварийному завершению утилиты сканирования шины PCI:

Проверим на практике

В нашей тестовой лаборатории был написан пример, демонстрирующий использование функции 40000000h инструкции CPUID. Приложение запускается в среде UEFI и благодаря технологии EFI Byte Code работает на 32 и 64-битных реализациях firmware. Проверка выполнена в среде Oracle VirtualBox.

Результат выполнения утилиты UEFIINFO в 32-битной среде Oracle VirtualBox
Рис 2Результат выполнения утилиты UEFIINFO в 32-битной среде Oracle VirtualBox

Результат выполнения утилиты UEFIINFO в 64-битной среде Oracle VirtualBox
Рис.3. Результат выполнения утилиты UEFIINFO в 64-битной среде Oracle VirtualBox

Резюме

В итоге, по результатам детектирования виртуальной платформы, информационно-диагностическая утилита может выбрать безопасный метод сканирования оборудования.

Послесловие

Подробнее о запуске и отладке EBC-приложений рассказано в нашей публикации «Об использовании EBC-драйвера».

Теги: