Друзья огромня просба, если статья вам помогла кликните на рекламный банер... Зарание спасибо
Сегодня я раскажу как детектировать виртуалку... Очень часто при удаленном подключении может понадобиться знать на реальном или виртуальном хосте мы находимся...Анализируем оборудование
Начнем, пожалуй, с жесткого диска. Если посмотреть идентификатор жесткого диска в диспетчере устройств на виртуальной машине, то в его составе можно увидеть интересные строчки:DiskVirtual для VirtualPC
DiskVBOX_HARDDISK для Virtual Box
Prod_VMware_Virtual для VMware Workstation
Самый простой способ узнать наименование жесткого диска — прочитать
значение ключа с именем «0» в ветке реестра
HKLM\HARDWARE\SYSTEM\CurrentControlSet\Services\Disk\Enum.В этом месте перечисляются все дисковые накопители в системе, и первым, как раз в ключе с именем «0», будет тот диск, с которого произошла загрузка системы.

...
// Открывем нужный ключ реестра
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.

Помимо этого, в 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
#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
...
...
// К примеру, ищем процесс 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

...
// К примеру, ищем окно для 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

...
// К примеру, проверяем 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__
Проверку реализуем так же, как мы проверяли наличие определенного
оборудования. Просто делаем попытку открыть нужный нам ключ и, в случае
успеха, делаем вывод о наличии ВМ. 
Возможности, заложенные производителем
Некоторые производители (в частности, 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;
...
Комментариев нет:
Отправить комментарий