Чтиво Как обнаруживают виртуальные машины

Тема в разделе "Компьютеры, Интернет, IT-новости", создана пользователем segmentoid, 4 янв 2014.

  1. segmentoid

    segmentoid Свой

    Регистрация:
    8 май 2013
    Сообщения:
    254
    Симпатии:
    96
    Взято с

    Для просмотра ссылок зарегистрируйтесь или авторизуйтесь на сайте.


    Если не актуально или не совсем верно, дополняйте.

    Как распознать виртуальную машину?
    Во-первых, любая виртуальная машина несет на своем борту какое-нибудь специфическое оборудование. Это касается видеоадаптера, жесткого диска, идентификатора процессора, версии BIOS, MAC-адреса сетевой карты.

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

    В-третьих, если как следует покопаться в реестре виртуальной машины, там можно найти много всяких интересных ключей, характерных только для виртуальных машин.

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

    Что же касается общих признаков наличия виртуальной машины, предложенных в свое время госпожой Рутковской (характерное расположение таблиц IDT, GDT и LDT, а также время выполнения операций процессором), то в настоящий момент все эти признаки трудно поддаются анализу и приведению к какому-нибудь общему знаменателю, главным образом из-за многоядерности и многоликости современных процессоров.

    Анализируем оборудование
    Начнем, пожалуй, с жесткого диска. Если посмотреть идентификатор жесткого диска в диспетчере устройств на виртуальной машине, то в его составе можно увидеть интересные строчки:

    DiskVirtual для VirtualPC
    DiskVBOX_HARDDISK для Virtual Box
    Prod_VMware_Virtual для VMware Workstation
    Самый простой способ узнать наименование жесткого диска — прочитать значение ключа с именем «0» в ветке реестра HKLM\HARDWARE\SYSTEM\CurrentControlSet\Services\Disk\Enum.

    В этом месте перечисляются все дисковые накопители в системе, и первым, как раз в ключе с именем «0», будет тот диск, с которого произошла загрузка системы.

    [​IMG]
    Идентификатор жесткого диска VirtualBox в реестре
    Как читать реестр, я думаю, ты знаешь. Используем сначала API RegOpenKeyEx для открытия нужного ключа, далее с помощью RegQueryValueEx читаем значение. Выглядеть это должно примерно вот так:

    ...
    // Открывем нужный ключ реестра
    RegOpenKeyExA(HKEY_LOCAL_MACHINE,
    "HARDWARE\\SYSTEM\\
    CurrentControlSet\\
    Services\\Disk\\Enum",
    0,
    KEY_QUERY_VALUE,
    &rKey);
    // Читаем значение
    RegQueryValueExA(rKey,
    "0",
    NULL,
    &Type,
    (LPBYTE)RegKey,
    &RegPath);
    // Закрываем все, что открыли ранее
    RegCloseKey(rKey);
    ...
    Далее все просто — используем strstr для поиска нужных нам строк в считанном значении и, в зависимости от результата сравнения, делаем вывод. Версия BIOS содержится в ключе «SystemProductName» в ветке HKLM\HARDWARE\DESCRIPTION\System\BIOS. К примеру, для VMware там будет лежать строка «VMware Virtual Platform», а для VirtualBox — «VBOX –1».

    Прочитать это все можно с помощью все тех же API — RegOpenKeyEx и RegQueryValueEx.

    [​IMG]
    Версия BIOS Parallels Workstation в реестре
    Данные о видеоадаптере можно подглядеть в HKLM\System\CarrentControlSet\Enum\PCI. В этой ветке перечислено все, что подключено к шине PCI, в том числе и видеокарта. Для VirtualPC это строчка вида VEN_5333&DEV_8811&SUBSYS_00000000&REV_00, которая определяет видеоадаптер S3 Trio 32/64, эмулируемый виртуалкой от Microsoft — на реальном железе такое оборудование нынче днем с огнем не сыскать (а у меня такая была в конце прошлого века. — Прим. ред.). Для VirtualBox видеокарта описана последовательностью VEN_80EE&DEV_BEEF&SUBSYS_00000000&REV_00, что расшифровывается как «VirtualBox Display», а у Parallels Workstation — строка VEN_1AB8&DEV_4005&SUBSYS_04001AB8&REV_00 определяет видеоадаптер «Parallels Display».

    Помимо этого, в VirtualBox можно найти строку VEN_80EE&DEV_CAFE&SUBSYS_00000000&REV_00, определяющую некий «VirtualBox Device», а у Parallels Workstation строки VEN_1AB8&DEV_4000&SUBSYS_04001AB8&REV_00 и VEN_1AB8&DEV_4006&SUBSYS_04061AB8&REV_00, определяющие «Parallels Tools Device» и «Parallels Memory Controller» соответственно.

    Алгоритм действий следующий: пытаемся открыть нужный нам ключ, и если он открывается успешно, то оборудование, описанное этим ключом, в наличии и можно делать вывод о присутствии какой-либо виртуальной машины:

    ...
    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
    L"SYSTEM\\CurrentControlSet\\
    Enum\\PCI\\VEN_5333&DEV_8811&
    SUBSYS_00000000&REV_00",
    0,
    KEY_QUERY_VALUE,
    &rKey) == ERROR_SUCCESS)
    {
    RegCloseKey(rKey);
    // Мы под VirtualPC
    return true;
    }
    ...
    Идентификатор процессора определяется с помощью команды cpuid. Благодаря ей можно получить много всякой полезной информации об установленном процессоре. Вид выдаваемой этой командой информации зависит от содержимого регистра EAX. Результат работы команды записывается в регистры EBX, ECX и EDX. Подробно про эту команду можно почитать в любой книге по программированию на ассемблере. Для наших целей мы будем использовать эту инструкцию, предварительно положив в регистр EAX значение 0x40000000:

    ...
    _asm
    {
    mov eax, 0x40000000
    cpuid
    mov ID_1, ebx
    mov ID_2, ecx
    mov ID_3, edx
    }
    ...
    После выполнения этого кода на VMware Workstation в переменных ID_1, ID_2 и ID_3 будут записаны значения 0x61774d56, 0x4d566572 и 0x65726177 соответственно (в символьном представлении это не что иное, как «VMwareVMware»), на VirtualBox в ID_1 и в ID_2 будет лежать значение 0x00000340, а на Parallels Workstation в ID_1 0x70726c20, в ID_2 — 0x68797065 и в ID_3 — 0x72762020 (что соответствует строке «prl hyperv»).

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

    Ты наверняка знаешь, что первые три байта MAC-адреса сетевой карты определяют ее производителя. Производители виртуальных машин в этом плане не исключение:

    VMware (VMware Workstation)
    00:05:69
    00:0c:29
    00:1c:14
    00:50:56
    Microsoft (Virtual PC)
    00:03:ff
    00:0d:3a
    00:50:f2
    7c:1e:52
    00:12:5a
    00:15:5d
    00:17:fa
    28:18:78
    7c:ed:8d
    00:1d:d8
    00:22:48
    00:25:ae
    60:45:bd
    Dc:b4:c4
    Oracle (VirtualBox)
    08:00:20
    Parallels (Parallels Workstation)
    00:1c:42
    Вытащить эти первые три байта из MAC-адреса нам поможет API-функция GetAdaptersInfo:

    // Подключаем либу, в которой
    // содержится нужная нам функция
    #include <iphlpapi.h>
    #pragma comment(lib, "IPHLPAPI.lib")
    ...
    // Определяем размер буфера под данные,
    // возвращаемые функцией
    GetAdaptersInfo(AdapterInfo, &OutBufLen);
    // Выделяем память под данные об адаптере
    AdapterInfo = (PIP_ADAPTER_INFO) new(char[OutBufLen]);
    // Получаем информацию об адаптере
    GetAdaptersInfo(AdapterInfo, &OutBufLen);
    // Сравниваем первые три байта MAC-адреса
    // с 00:1c:42 (Parallels Workstation)
    if (((BYTE)AdapterInfo->Address[0] == 0x00) &&
    ((BYTE)AdapterInfo->Address[1] == 0x1c) &&
    ((BYTE)AdapterInfo->Address[2] == 0x42))
    {
    delete(AdapterInfo);
    // Мы под Parallels Workstation
    return true;
    }
    else
    {
    delete(AdapterInfo);
    return false;
    }
    ...
    Вспомогательные процессы, окна и другие «подозрительные» объекты
    Для нормальной работы практически все виртуальные машины требуют установки дополнений к гостевой операционной системе, например VBoxGuestAddition для VirtualBox или Parallels Tools для Parallels Workstation. Без этих дополнений работа с виртуальной машиной несколько затруднительна (ни тебе нормального разрешения экрана и полноэкранного режима, ни взаимодействия с USB-девайсами, ни нормальной настройки сетевых подключений). В общем, все производители виртуалок не рекомендуют использовать их без этих дополнений. А эти самые дополнения оставляют очень заметный след в виде запущенных процессов:

    VirtualBox
    VBoxTray.exe
    VBoxService.exe
    Parallels Workstation
    prl_cc.exe
    prl_tools.exe
    SharedIntApp.exe
    Virtual PC
    vmusrvc.exe
    vmsrvc.exe
    VMware Workstation
    vmtoolsd.exe
    Для поиска процесса по имени мы воспользуемся функциями CreateToolhelp32Snapshot, Process32First и Process32Next:

    #include <Tlhelp32.h>
    ...
    ...
    // К примеру, ищем процесс vmtoolsd.exe
    wchar_t VMwareProcessName[] = {L"vmtoolsd.exe"};
    PROCESSENTRY32 pe;
    HANDLE hSnapShot;
    hSnapShot = CreateToolhelp32Snapshot
    (TH32CS_SNAPPROCESS, 0);
    ZeroMemory (&pe, sizeof(PROCESSENTRY32W));
    pe.dwSize = sizeof(PROCESSENTRY32W);
    Process32First(hSnapShot, &pe);
    do
    {
    if (memcmp(pe.szExeFile, VMwareProcessName, 24) == 0)
    // Мы под VMware
    return true;
    }
    while (Process32Next(hSnapShot, &pe));
    ...

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

    VirtualBox
    VBoxTrayToolWndClass
    Parallels Workstation
    CPInterceptor
    DesktopUtilites
    Virtual PC
    {0843FD01-1D28-44a3-B11D-E3A93A85EA96}
    VMware Workstation
    VMSwitchUserControlClass


    [​IMG]
    Открытые окна для VMware (красным выделено окно класса VMSwitchUserControlClass)
    Найти окно по имени класса очень просто — для этого есть функция FindWindow:

    ...
    // К примеру, ищем окно для VMware
    HWND VMwareWindow = FindWindowA("VMSwitchUserControlClass", NULL);
    if(VMwareWindow != NULL)
    // Мы под VMware Workstation
    return true;
    ...


    Помимо процессов и окон, указывающих на наличие ВМ, можно найти и другие «подозрительные» объекты — например, если покопаться в гостевой ОС виртуальной машины утилитой WinObj или какой-нибудь аналогичной, то можно найти вот такие объекты:

    VirtualBox
    \Device\VBoxMiniRdrDN
    \Device\VBoxGuest
    Parallels Workstation
    \Device\prl_pv
    \Device\prl_tg
    \Device\prl_time
    \Device\PrlMemDev
    \Device\PrlMemDevPci
    \Device\PrlMemDev
    Virtual PC
    \Device\VirtualMachineServices


    [​IMG]
    «Подозрительные» объекты в VirtualBox
    Проверить наличие «подозрительного» объекта очень просто, достаточно попытаться открыть его с помощью CreateFile:

    ...
    // К примеру, проверяем VirtualBox
    if ((CreateFile(L"\\\\.\\VBoxMiniRdrDN",
    0,0,0,OPEN_EXISTING,0,0)
    !=INVALID_HANDLE_VALUE)||
    (CreateFile(L"\\\\.\\VBoxGuest",
    0,0,0,OPEN_EXISTING,0,0)
    !=INVALID_HANDLE_VALUE))
    // Мы под VirtualBox
    return true;
    ...


    Что еще «подозрительного» можно найти в реестре?
    Помимо признаков наличия специфического оборудования, в реестре можно увидеть и другие следы, оставляемые виртуальными машинами. Некоторые из них базируются в ветке HKLM\HARDWARE\ACPI\DSDT. Достаточно в этом месте проверить наличие таких вот ключей:

    VirtualBox
    VBOX__
    Parallels Workstation
    PRLS__
    Virtual PC
    AMIBI
    VMware Workstation
    PTLTD__


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

    [​IMG]
    Ключ PRLS__ в реестре Parallels Workstation
    Возможности, заложенные производителем
    Некоторые производители (в частности, VMware и Microsoft) специально реализуют возможности управления своими продуктами, которые можно использовать для наших целей.

    В Virtual PC используются инвалидные (не «инвалидные», а «альтернативно одаренные». И вообще-то они «недействительные». — Прим. ред.) команды процессора с опкодами 0x0F, 0x3F, 0x07 и 0x0B, попытка выполнения которых на реальном процессоре вызовет исключение, в то время как на Virtual PC все пройдет нормально. С помощью этих команд можно достаточно просто задетектить виртуалку от Microsoft:

    ...
    __try
    {
    __asm
    {
    xor ebx, ebx
    mov eax, 1
    __emit(0x0F)
    __emit(0x3F)
    __emit(0x07)
    __emit(0x0B)
    }
    // Мы под Virtual PC
    return true;
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    return false;
    ...


    В VMware Workstation для взаимодействия гостевой и основной ОС реализован небольшой бэкдор в виде порта с номером 0x5658. Для его использования необходимо в EAX положить «магическое» число 0x564d5868 (в символьном представлении — «VMXh»), а в ECX записать одну из команд взаимодействия гостевой и основной ОС (например, команда 0x0A возвращает версию установленной VMware Workstation). Короче, выглядит все это приблизительно так:

    ...
    __try
    {
    __asm
    {
    mov eax, 0x564d5868
    mov ecx, 0x0A
    mov edx, 0x5658
    in eax, dx
    }
    // Мы под VMware
    return true;
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    return false;
    ...
     
    one и Limuzin нравится это.
Загрузка...
Похожие темы - Как обнаруживают виртуальные
  1. illara
    Ответов:
    0
    Просмотров:
    39
  2. redloop
    Ответов:
    2
    Просмотров:
    155
  3. mariobros
    Ответов:
    0
    Просмотров:
    188
  4. redloop
    Ответов:
    0
    Просмотров:
    176
  5. Голубевод
    Ответов:
    0
    Просмотров:
    35
  6. Nellin
    Ответов:
    1
    Просмотров:
    158
  7. Солнце ясное
    Ответов:
    0
    Просмотров:
    74