Обнаружить виртуальную ОС из приложения? - PullRequest
63 голосов
/ 30 сентября 2008

Мне нужно определить, работает ли мое приложение в виртуализированном экземпляре ОС или нет.

Я нашел статью с некоторой полезной информацией по теме. Одна и та же статья появляется в нескольких местах, я не уверен в первоисточнике. VMware реализует конкретную недопустимую инструкцию x86 для возврата информации о себе, тогда как VirtualPC использует магическое число и порт ввода-вывода с инструкцией IN.

Это выполнимо, но в обоих случаях выглядит недокументированным поведением. Я предполагаю, что будущий выпуск VMWare или VirtualPC может изменить механизм. Есть ли способ лучше? Есть ли поддерживаемый механизм для любого продукта?

Аналогично, есть ли способ обнаружить Xen или VirtualBox ?

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

Приложение в основном Java, хотя я ожидаю использовать нативный код плюс JNI для этой конкретной функции. Поддержка Windows XP / Vista является наиболее важной, хотя механизмы, описанные в указанной статье, являются общими функциями x86 и не зависят от каких-либо конкретных возможностей ОС.

Ответы [ 15 ]

66 голосов
/ 30 сентября 2008

Вы слышали о синей таблетке, красной таблетке? . Это техника, используемая для определения, работаете ли вы на виртуальной машине или нет. Происхождение термина происходит от матричного фильма , где Нео предлагается синяя или красная таблетка (чтобы остаться внутри матрицы = синий или войти в «реальный» мир = красный).

Ниже приведен код, который будет определять, запускаете ли вы внутри «матрицы» или нет:
(код заимствован у этого сайта , который также содержит полезную информацию по данной теме):

 int swallow_redpill () {
   unsigned char m[2+4], rpill[] = "\x0f\x01\x0d\x00\x00\x00\x00\xc3";
   *((unsigned*)&rpill[3]) = (unsigned)m;
   ((void(*)())&rpill)();
   return (m[5]>0xd0) ? 1 : 0;
 } 

Функция вернет 1, когда вы работаете внутри виртуальной машины, и 0 в противном случае.

24 голосов
/ 29 ноября 2010

В Linux я использовал команду: dmidecode (у меня она есть и в CentOS, и в Ubuntu)

от мужчины:

dmidecode - инструмент для выгрузки таблица DMI компьютера (некоторые говорят, SMBIOS) содержимое в удобочитаемом формате.

Итак, я искал вывод и обнаружил, что это, вероятно, Microsoft Hyper-V

Handle 0x0001, DMI type 1, 25 bytes
System Information
    Manufacturer: Microsoft Corporation
    Product Name: Virtual Machine
    Version: 5.0
    Serial Number: some-strings
    UUID: some-strings
    Wake-up Type: Power Switch


Handle 0x0002, DMI type 2, 8 bytes
Base Board Information
    Manufacturer: Microsoft Corporation
    Product Name: Virtual Machine
    Version: 5.0
    Serial Number: some-strings

Другой способ - поиск производителя, с которым связан MAC-адрес eth0: http://www.coffer.com/mac_find/

Если он вернет Microsoft, vmware и т. Д., То, вероятно, это виртуальный сервер.

12 голосов
/ 16 августа 2010

В VMware есть Механизмы, позволяющие определить, работает ли программное обеспечение на виртуальной машине VMware. Статья базы знаний с некоторым исходным кодом.

У Microsoft также есть страница на «Определение, установлен ли гипервизор» . MS излагает это требование гипервизора в разделе «ИСПЫТАНИЯ IsVM» их «Проверочного теста виртуализации сервера» документ

В документах VMware и MS упоминается использование инструкции CPUID для проверки присутствующего гипервизора бита (бит 31 регистра ECX)

У средства отслеживания ошибок RHEL есть один для ", следует установить бит ISVM (ECX: 31) для листа CPUID 0x00000001" , чтобы установить бит 31 регистра ECX под ядром Xen.

Так что, не вдаваясь в подробности поставщика, похоже, что вы можете использовать проверку CPUID, чтобы узнать, работает ли вы виртуально или нет.

11 голосов
/ 02 октября 2008

Я думаю, что в дальнейшем, опираясь на такие хитрости, как сломанная виртуализация SIDT, в действительности не поможет, так как аппаратные средства закрывают все дыры, которые оставила странная и грязная архитектура x86. Лучше всего было бы лоббировать поставщиков Vm стандартным способом сообщить, что вы находитесь на виртуальной машине - по крайней мере, в случае, когда пользователь явно разрешил это. Но если мы предположим, что мы явно разрешаем обнаружение виртуальной машины, мы также можем разместить там видимые маркеры, верно? Я бы предложил просто обновить диск на ваших виртуальных машинах файлом, сообщающим вам, что вы находитесь на виртуальной машине - например, небольшим текстовым файлом в корне файловой системы. Или проверьте MAC-адрес ETH0 и установите для него заданную известную строку.

11 голосов
/ 30 сентября 2008

Нет. Это невозможно обнаружить с полной точностью. Некоторые системы виртуализации, такие как QEMU , эмулируют всю машину вплоть до аппаратных регистров. Давайте перевернем это: что вы пытаетесь сделать? Может быть, мы можем помочь с этим.

8 голосов
/ 30 апреля 2014

В виртуальной коробке, если у вас есть контроль над гостевой виртуальной машиной и у вас есть dmidecode, вы можете использовать эту команду:

dmidecode -s bios-version

и он вернется

VirtualBox
7 голосов
/ 28 мая 2009

Я бы хотел порекомендовать статью, опубликованную в Usenix HotOS '07, Совместимость - это не прозрачность: мифы и реальность обнаружения VMM , в которой изложены несколько методов, позволяющих определить, работает ли приложение в виртуализированной среде. ,

Например, используйте инструкцию sidt, как это делает redpill (но эту инструкцию также можно сделать прозрачной с помощью динамического перевода), или сравните время выполнения cpuid с другими не виртуализированными инструкциями.

5 голосов
/ 14 августа 2015

Эта функция C обнаружит гостевую ОС VM:

(протестировано в Windows, скомпилировано с Visual Studio)

#include <intrin.h>

    bool isGuestOSVM()
    {
        unsigned int cpuInfo[4];
        __cpuid((int*)cpuInfo,1);
        return ((cpuInfo[2] >> 31) & 1) == 1;
    }
5 голосов
/ 15 января 2010

При установке новой версии Ubuntu я обнаружил пакет под названием imvirt. Посмотрите на это на http://micky.ibh.net/~liske/imvirt.html

5 голосов
/ 30 сентября 2008

Под Linux вы можете сообщить в / proc / cpuinfo. Если он в VMware, он обычно появляется не так, как на голом металле, но не всегда. Virtuozzo показывает проход к базовому оборудованию.

...