虛擬機檢測

下面資料比較老了,記錄下只爲增加下了解

虛擬機後門檢測(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);
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章