下面資料比較老了,記錄下只爲增加下了解
虛擬機後門檢測(IN)
__try
{
__asm
{
push edx
push ecx
push ebx
mov eax, 'VMXh'
mov ebx, 0 // 將ebx設置爲非幻數’VMXH’的其它值
mov ecx, 10 // 指定功能號,用於獲取VMWare版本,當它爲x14時用於獲取VMware內存大小
mov edx, 'VX' // 端口號
in eax, dx // 從端口dx讀取VMware版本到eax
//若上面指定功能號爲x14時,可通過判斷eax中的值是否大於,若是則說明處於虛擬機中
cmp ebx, 'VMXh' // 判斷ebx中是否包含VMware版本’VMXh’,若是則在虛擬機中
setz [rc] // 設置返回值
pop ebx
pop ecx
pop edx
}
rc = true;
}
__except(EXCEPTION_EXECUTE_HANDLER) //如果未處於VMware中,則觸發此異常
{
rc = false;
} 虛擬機中IN讀取指定端口不會異常,如果異常了爲真實機。
時間戳指令檢測
__asm
{
push eax
RDTSC
mov ifirst,eax
RDTSC
mov isecond,eax
pop eax
}
isub = isecond - ifirst;
if (isub > 0x0ff) //判斷兩次之差是否大於0xff
{
MessageBox(L"IN VM",L"Check VM",MB_OK);
}
else
{
MessageBox(L"Not in VM",L"Check VM",MB_OK);
}
MAC地址檢測
虛擬機中MAC地址的頭兩個字節是000c或者0005
ULONG uInfo = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
pMac01 = (BYTE)pAdapterInfo->Address[0];
pMac02 = (BYTE)pAdapterInfo->Address[1];
if (pMac01 == 0x00 && (pMac02 == 0x0c || pMac02 == 0x05) )
MessageBox(L"IN VM",L"Check VM",MB_OK);
else
MessageBox(L"Not in VM",L"Check VM",MB_OK);
進程檢測
vmtoolsd.exe,vmtoolsd.exe,VMwareTray.exe,vmacthlp.exe,VMUpgradeHelper.exe虛擬機中存在的進程。
枚舉方式可以有多種:
1.創建進程快照(CreateToolhelp32Snapshot)
2. 枚舉進程和枚舉進程模塊,
EnumProcesses和EnumProcessModules
3.通過WMI接口查詢進程。
文件檢測
通過打開虛擬機相關的文件進行判斷
例如:
C:\\Program Files\\VMware\\VMware Tools\\vmtoolsd.exe
char *szFile = "C:\\Program Files\\VMware\\VMware Tools\\vmtoolsd.exe";
HANDLE hVmFile = CreateFileA(szFile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
if (hVmFile != INVALID_HANDLE_VALUE)
MessageBox(L"In VM",L"Check VM",MB_OK);
else
MessageBox(L"Not In VM",L"Check VM",MB_OK);
CloseHandle(hVmFile);
註冊表檢測
註冊表裏對應的虛擬機的信息非常多,由此可以操作判斷虛擬機。
HKEY hKey = NULL;
WCHAR * szSubKey = L"SOFTWARE\\VMware, Inc.\\VMware Tools";
ULONG uReg=RegOpenKeyEx(HKEY_LOCAL_MACHINE,szSubKey ,0,KEY_READ,&hKey);
if (uReg == ERROR_SUCCESS)
MessageBox(L"In VM",L"Check VM",MB_OK);
else
MessageBox(L"Not In VM",L"Check VM",MB_OK);
RegCloseKey(hKey);
磁盤型號Model Number
Disk Serial Number : "WD-WMA9N2077672“
Disk Model Number : "WDC WD80EB-28CGH1 “
Disk Serial Numbe : 硬盤序列號
Disk Model Number : 硬盤型號
我本機的Model Number是:ST350041CC66
虛擬機中的Model Number:VMware,VMware Virtual S1.0
顯示卡檢測
虛擬機的顯示卡名稱是VMware SVGA II
if (EnumDisplayDevices(NULL, nDeviceIndex, &DispDev, 0))
{
hr = StringCchCopy((STRSAFE_LPWSTR)lpszMonitorInfo, 0x100, (STRSAFE_LPWSTR)DispDev.DeviceString);
if (FAILED(hr))
{
return FALSE;
}
}
else
{
bRet = FALSE;
}
系統設備檢測
虛擬機中存在通訊接口設備和磁盤設備
VMware VMCI Bus Device
VMware, VMware Virtual S SCSI Disk Device
通過枚舉系統所有設備信息
如果發現VMCI Device或者DISK Device就是在虛擬機中了
IDT基址檢測
typedef struct
{
WORD IDTLimit; // IDT的大小
WORD LowIDTbase; // IDT的低位地址
WORD HiIDTbase; // IDT的高位地址
} IDTINFO;
Redpill作者(?不是bulepill麼)在VMware上發現虛擬機系統上的IDT地址通常位於0xFFXXXXXX,而Virtual PC通常位於0xE8XXXXXX,而在真實主機上位於0x80xxxxxx。Redpill僅僅是通過判斷執行SIDT指令後返回的第一字節是否大於0xD0,若是則說明它處於虛擬機,否則處於真實主機中。
typedef struct
{
WORD IDTLimit; // IDT的大小
WORD LowIDTbase; // IDT的低位地址
WORD HiIDTbase; // IDT的高位地址
} IDTINFO;
Redpill作者在VMware上發現虛擬機系統上的IDT地址通常位於0xFFXXXXXX,而Virtual PC通常位於0xE8XXXXXX,而在真實主機上位於0x80xxxxxx。Redpill僅僅是通過判斷執行SIDT指令後返回的第一字節是否大於0xD0,若是則說明它處於虛擬機,否則處於真實主機中。
LDT和GDT基址檢測
在保護模式下,所有的內存訪問都要通過全局描述符表(GDT)或者本地描述符表(LDT)才能進行。這些表包含有段描述符的調用入口。各個段描述符都包含有各段的基址,訪問權限,類型和使用信息,而且每個段描述符都擁有一個與之相匹配的段選擇子,各個段選擇子都爲軟件程序提供一個GDT或LDT索引(與之相關聯的段描述符偏移量),一個全局/本地標誌(決定段選擇子是指向GDT還是LDT),以及訪問權限信息。 若想訪問段中的某一字節,必須同時提供一個段選擇子和一個偏移量。段選擇子(寄存器)爲段提供可訪問的段描述符地址(在GDT 或者LDT 中)。 GDT的線性基址被保存在GDT寄存器(GDTR)中,而LDT的線性基址被保存在LDT寄存器(LDTR)中。
當LDT基址位於0x0000(只有兩字節)時爲真實主機,否則爲虛擬 機,而當GDT基址位於0xFFXXXXXX時說明處於虛擬機中,否則爲真實主機
unsigned short ldt_addr = 0;
unsigned char ldtr[2] = {0};
__asm
{
sldt ldtr
}
ldt_addr = *((unsigned short *)&ldtr);
if(ldt_addr != 0x0000)
{
MessageBox(L"IN VM",L"Check VM",MB_OK);
}
else
{
MessageBox(L"Not in VM",L"Check VM",MB_OK);
}
GDT基址位於0xFFXXXXXX處於虛擬機中,真實機在x80XXXXXX
unsigned int gdt_addr = 0;
unsigned char gdtr[4];
_asm sgdt gdtr
gdt_addr = *((unsigned int *)&gdtr[2]);
printf("GDT BaseAddr:0x%x\n", gdt_addr);
if((gdt_addr >> 24) == 0xff)
{
MessageBox(L"IN VM",L"Check VM",MB_OK);
}
else
{
MessageBox(L"Not in VM",L"Check VM",MB_OK);
}
STR檢測
在保護模式下運行的所有程序在切換任務時,對於當前任務中指向TSS的段選擇器將會被存儲在任務寄存器中,TSS中包含有當前任務的可執行環境狀態,包括各種寄存器狀態等等,當任務再次被執行時,處理器就會保存原先的任務狀態。每項任務均有其自己的TSS,而我們可以通過STR指令來獲取指向當前任務中TSS的段選擇器。這裏STR(Store task register)指令是用於將任務寄存器 (TR) 中的段選擇器存儲到目標操作數,目標操作數可以是通用寄存器或內存位置,使用此指令存儲的段選擇器指向當前正在運行的任務的任務狀態段 (TSS)。在虛擬機和真實主機之中,通過STR讀取的地址是不同的,當地址等於0x0040xxxx時,說明處於虛擬機中,否則爲真實主機。
Str將任務寄存器(TR) 中的段選擇器存儲到目標操作數
當地址等於x0040xxxx時,說明處於虛擬機中,否則爲真實機
unsigned char mem[2] = {0};
__asm str mem;
if ( (mem[0]==0x00) && (mem[1]==0x40))
{
MessageBox(L"IN VM",L"Check VM",MB_OK);
}
else
{
MessageBox(L"Not in VM",L"Check VM",MB_OK);
}