#include <windows.h>
// строковые константы
#define VM "vmware"
#define VM_DETECTED "detected"
#define VM_NOT_DETECTED "not detected"
#define VM_NOT_RECOGNZD "detected, but not recognized"
// под vm-ware функция возвращает версию vm-ware в регистре eax
// (нуль - это не vm-ware или версия неопознана),
// без vm-ware возбуждается исключение
__declspec(naked) get_vm() // "голая" функция без пролога и эпилога
{
__asm {
; подготавливаем аргументы и магические пирожки
mov ecx, 0Ah ; номер команды - определение версии
mov eax, 564d5868h ; 'VMXh' - магический номер типа "пирожок"
mov edx, 00005658h ; '..VX' - магический порт back-door интерфейса
; дергаем за "веревочку"
in eax, dx ; вызываем команду по back-door интерфейсу
; возвращенные параметры помещаются в EAX/EBX/ECX
; внимание!
; в среде чистой Windows без vm-ware при обращении к порту ввода-вывода
; произойдет исключение и управление будет передано SEH-обработчику,
; который должен быть заранее установлен (иначе выполнение программы
; будет завершено системой)
; если же мы еще здесь, следовательно, исключения не произошло
; и либо какой-то хитрый драйвер открыл порты ввода-вывода,
; либо мы находимся под управлением непатченной vm-ware
; или чего-то очень на нее похожего
cmp ebx, 'VMXh' ; анализируем возвращенный магический пирожок
je under_VMware ; если пирожок возвращен, мы под vm-ware
xor eax,eax ; возвращаем ноль в знак того, что мы не под vm-ware!
ret ; выходим из функции
under_VMware:
ret ; мы под непатченной vm-ware, в eax - номер версии
}
}
main()
{
// вызываем функцию get_vm из блока __try,
// чтобы отлавливать возникающие исключения;
// для простоты и наглядности версия vm-ware, возвращенная get_vm,
// не выводится на экран и сообщается лишь о том, был ли обнаружен
// непатченный эмулятор или нет (если исключения не произошло,
// vm-ware считается обнаруженной)
__try { printf("%s %s\n", VM, (get_vm()) ? VM_DETECTED : VM_NOT_RECOGNZD);}
// обработчик исключения, получающий управление при выполнении программы
// в среде чистой Windows, под патченной vm-ware или на другом эмуляторе
__except(1) {printf("%s %s\n", VM, VM_NOT_DETECTED);}
}