最近在项目中遇到一个虚拟机检测的问题,需要检测当前程序是否在虚拟机中运行。
刚遇到这个问题时感觉就是一头雾水,一脸懵逼的有没有?咱又不是开发虚拟机的不是,怎么知道要怎么检测是不是虚拟机呢?何况现在主流的虚拟机有好几个,有没有通用的方法呢?相信很多朋友也会有同样的问题。但可以肯定的是,既然是虚拟机,肯定有和物理机不一样的东西,只要找到这些不一样的固有属性,用程序加以判断,肯定有可以检测出来。那么具体有些什么区别?又该如何检测呢?充分利用互联网的优势,先百度谷歌再说。
不查不知道,一查吓一跳,看来遇到这个问题的人还是挺多的。发现比较好的博文都是在CSND上有木有?这里要好好感谢一下CSDN,不但有各种高水平技术贴,据说还可以用来做SEO的有木有啊?不过现在CSDN可不允许你随便做SEO了,人家要审核你的文章了,这也真是烦人,好不容易晚上有时间来发个文章,写完以后要等到第二天人工审核才能过,你说这心都凉了半截有木有?。
言规正这里经过本人的一一查看和总结,发现比较可行的方法就是某位大牛总结的几种方法。这里就不多解释了,直接上链接,感兴趣的同学可以自己去了解一下:http://blog.csdn.net/whatday/article/details/10393325,这里介绍了7种方法,都有代码,同时还有反检测。我没有一一测试,需要的同学可在实践测试一下,我直接采用了第一种方法,并且找到了第一种方法的完整原码。只需要调用IsVirtualMachine即可判断是否是虚拟机中,是不是很方便呢有木有? 原码的下载地址:https://www.codeproject.com/Articles/9823/Detect-if-your-program-is-running-inside-a-Virtual
上面的方法可以检测出 Vmware 和 virtualPC,但是没有告诉我们怎么检测XGenServer 虚拟机。如果要检测XGenServer呢要怎么办?
继续百度谷歌,结果关于这个虚拟机检测的方法,反正我是没有在网上找了半天没有发现,心凉了半截有木有?好吧,没有就自己想办法了,这里我想到的办法是获取硬件信息了,虚拟机的硬件都是虚拟出来的,比如网卡,磁盘啊。首先验证一下这个方法有没有效啊。查硬件信息用设备管理器。如下图所示:
果然有亮点。再来一个:msinfo32看看:
海阔天空啊,就你了。经验证VMWARE 上也一样有亮点哦, 这里不贴图了。大家自己去看下就知道了,都是VMware开头的。接下来就是获取这些信息了,这个用WMI就可以获取到这里贴上获取信息的源码供大家使用:
TClient.h
#pragma once
#include<atlbase.h>
#include<objbase.h>
#include<WbemIdl.h>
#include<WbemCli.h>
#include<comdef.h>
#pragma comment(lib,"wbemuuid.lib")
#pragma comment(lib,"ole32.lib")
#define DEF_MAX_WBEMOBJ 20
#define DEF_MAX_PATH 260
class TClientDMI
{
public:
TClientDMI();
~TClientDMI();
public:
CString getDMIInformation(TCHAR *pWin32_ClassName, TCHAR *pUniqueCaption,TCHAR *pUniqueValue, TCHAR *pTargetCaption);
private:
HRESULT _initDMI();
private:
BSTR m_strNameSpace;
BOOL m_blDMIInit; //DMI init flag
private:
IWbemLocator* m_pIWbemLocator;
IWbemServices* m_pIWbemServices;
IEnumWbemClassObject* m_pIEnumWbem;
IWbemClassObject* m_szIWbemObject[DEF_MAX_WBEMOBJ];
BSTR m_strClassName;
};
TClient.cpp
#include "stdafx.h"
#include "TClientDMI.h"
TClientDMI::TClientDMI()
{
m_blDMIInit = FALSE;
m_strNameSpace = NULL;
m_pIWbemLocator = NULL;
m_pIWbemServices= NULL;
m_pIEnumWbem = NULL;
m_strClassName = NULL;
for (int i=0;i<DEF_MAX_WBEMOBJ;i++)
{
m_szIWbemObject[i] = NULL;
}
}
TClientDMI::~TClientDMI()
{
if (m_pIEnumWbem != NULL)
{
m_pIEnumWbem->Release();
m_pIEnumWbem = NULL;
}
if (m_strClassName != NULL)
{
SysFreeString(m_strClassName);
m_strClassName = NULL;
}
if (m_strNameSpace != NULL)
{
SysFreeString(m_strNameSpace);
m_strNameSpace = NULL;
}
if (m_pIWbemServices != NULL)
{
m_pIWbemServices->Release();
m_pIWbemServices = NULL;
}
if (m_pIWbemLocator != NULL)
{
m_pIWbemLocator->Release();
m_pIWbemLocator = NULL;
}
CoUninitialize();
}
//////////////////////////////////////////////////////////////////////////
//
// init DMI interface
//
//////////////////////////////////////////////////////////////////////////
HRESULT TClientDMI::_initDMI()
{
HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hr))
{
return hr;
}
hr = CoInitializeSecurity(NULL, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL, EOAC_SECURE_REFS, NULL);
if (FAILED(hr))
{
return hr;
}
hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID*)&m_pIWbemLocator);
if (FAILED(hr))
{
return hr;
}
m_strNameSpace = SysAllocString(_T("\\\\.\\root\\cimv2"));
hr = m_pIWbemLocator->ConnectServer(m_strNameSpace, NULL, NULL, 0L, 0L, NULL, NULL, &m_pIWbemServices);
if (FAILED(hr))
{
return hr;
}
m_blDMIInit = TRUE;
return hr;
}
//////////////////////////////////////////////////////////////////////////
// common query process
//step1. Init DMI interface
//step2. Get ClassInformation
//step3. Get Instance
//step4. Get the property of Instance
//////////////////////////////////////////////////////////////////////////
CString TClientDMI::getDMIInformation(TCHAR *pWin32_ClassName, TCHAR *pUniqueCaption, TCHAR *pUniqueValue, TCHAR *pTargetCaption)
{
CString strRet = _T("");
// TCHAR szTarget[MAX_PATH] = { 0 };
HRESULT hr = S_OK;
if (!m_blDMIInit)
{
hr= _initDMI();
}
if (SUCCEEDED(hr))
{
VARIANT var;
ULONG uReturned;
HRESULT hr;
VariantInit(&var);
m_pIEnumWbem = NULL;
m_strClassName = NULL;
m_strClassName = SysAllocString(pWin32_ClassName);
if (!m_strClassName)
{
return strRet;
}
hr = m_pIWbemServices->CreateInstanceEnum(m_strClassName, 0, NULL, &m_pIEnumWbem);
if (FAILED(hr))
{
return strRet;
}
uReturned = 1;
hr = m_pIEnumWbem->Next(2000 * DEF_MAX_WBEMOBJ, DEF_MAX_WBEMOBJ, m_szIWbemObject, &uReturned);
if (FAILED(hr))
{
return strRet;
}
VariantClear(&var);
UINT i = 0;
for (i = 0; i < uReturned; i++)
{
if (m_szIWbemObject[i] != NULL)
{
VariantClear(&var);
var.bstrVal = NULL;
if (pUniqueCaption != NULL)
{
hr = m_szIWbemObject[i]->Get(pUniqueCaption, 0, &var, NULL, NULL);
if (hr != WBEM_S_NO_ERROR)
{
return strRet;
}
}
if (pUniqueCaption == NULL || var.bstrVal!=NULL &&
_tcsncmp((V_BSTR(&var)),pUniqueValue, _tcslen(pUniqueValue)) == 0)
{
VariantClear(&var);
var.bstrVal = NULL;
hr = m_szIWbemObject[i]->Get(pTargetCaption, 0, &var, NULL, NULL);
if (var.vt != VT_NULL)
{
SAFEARRAY *pArr = nullptr;
BSTR vbStr = nullptr;
pArr = V_ARRAY(&var);
if (SafeArrayGetDim(pArr)!=1)
{
strRet = var.bstrVal;
}
else
{
LONG lLeft = 0;
LONG lRight = 0;
SafeArrayGetLBound(pArr, 1, &lLeft);
SafeArrayGetUBound(pArr, 1, &lRight);
LONG arrayCount = lLeft;
while (arrayCount<=lRight)
{
if (SafeArrayGetElement(pArr,&arrayCount,&vbStr) == S_OK)
{
strRet += vbStr;
strRet += _T(" ");
}
arrayCount++;
}
}
if (vbStr!=nullptr)
{
SysFreeString(vbStr);
vbStr = nullptr;
}
break;
}
}
}
}
VariantClear(&var);
}
return strRet;
}
DetectVM.cpp
#include "stdafx.h"
#include "DetectVM.h"
#include <windows.h>
#include "TClientDMI.h"
static CString strManufacturer;
static CString strModel;
static CString strDiskDrive;
static bool bInit = false;
void init()
{
if(!bInit)
{
TClientDMI DMI = TClientDMI();
strManufacturer = DMI.getDMIInformation(_T("Win32_ComputerSystem"), NULL, NULL, _T("Manufacturer"));
strManufacturer.MakeLower();
strModel = DMI.getDMIInformation(_T("Win32_ComputerSystem"), NULL, NULL, _T("Model"));
strModel.MakeLower();
strDiskDrive = DMI.getDMIInformation(_T("Win32_DiskDrive"), NULL, NULL, _T("Model"));
strDiskDrive.MakeLower();
bInit = true;
}
/* MessageBox(NULL, strManufacturer,strManufacturer,MB_OK);
MessageBox(NULL, strModel,strModel,MB_OK);
MessageBox(NULL, strDiskDrive,strDiskDrive,MB_OK);*/
}
bool IsInsideVirtualMachine()
{
return IsInsideVMWare() || IsInsideXenServer();
}
bool IsInsideVMWare()
{
if(!bInit)
init();
if(strManufacturer.Find(_T("vmware")) >= 0)
return true;
if(strModel.Find(_T("vmware")) >= 0)
return true;
return false;
}
bool IsInsideXenServer()
{
if(!bInit)
init();
// 检测系统制造商为XGen 系统模式为 HVM domU
if(strDiskDrive.Find(_T("qemu harddisk")) == 0)
return true;
if(strManufacturer == _T("xen"))
return true;
if(strModel.Find(_T("hvm domu")) == 0)
return true;
return false;
}