Virtualbox 从应用程序检测虚拟化操作系统?
我需要检测我的应用程序是否在虚拟化操作系统实例中运行 我发现了一些关于这个话题的有用信息。同一篇文章出现在多个地方,我不确定原始来源。实现一条特定的无效x86指令,以返回有关其自身的信息,同时使用带IN指令的幻数和I/O端口 这是可行的,但在这两种情况下似乎都是未记录的行为。我认为VMWare或VirtualPC的未来版本可能会改变这种机制。有更好的办法吗?这两种产品都有支持的机制吗 类似地,有没有一种方法可以检测到或检测到错误 我不关心平台故意隐藏自己的情况。例如,蜜罐使用虚拟化,但有时会掩盖恶意软件用来检测它的机制。我不在乎我的应用程序会认为它在这些蜜罐中没有虚拟化,我只是在寻找一个尽力而为的解决方案Virtualbox 从应用程序检测虚拟化操作系统?,virtualbox,vmware,virtualization,xen,virtual-pc,Virtualbox,Vmware,Virtualization,Xen,Virtual Pc,我需要检测我的应用程序是否在虚拟化操作系统实例中运行 我发现了一些关于这个话题的有用信息。同一篇文章出现在多个地方,我不确定原始来源。实现一条特定的无效x86指令,以返回有关其自身的信息,同时使用带IN指令的幻数和I/O端口 这是可行的,但在这两种情况下似乎都是未记录的行为。我认为VMWare或VirtualPC的未来版本可能会改变这种机制。有更好的办法吗?这两种产品都有支持的机制吗 类似地,有没有一种方法可以检测到或检测到错误 我不关心平台故意隐藏自己的情况。例如,蜜罐使用虚拟化,但有时会掩盖
应用程序主要是Java,尽管我希望使用本机代码和JNI来实现这个特定的功能。Windows XP/Vista支持是最重要的,尽管参考文章中描述的机制是x86的通用功能,不依赖于任何特定的操作系统功能。在Linux下,您可以在/proc/cpuinfo上报告。如果是在VMware中,它的表现通常与在裸机上不同,但并不总是如此。Virtuozzo展示了对底层硬件的传递。尝试阅读结构,尤其是包含信息的结构
在Linux中,您可以使用该实用程序浏览信息。否。这是不可能完全准确地检测到的。一些虚拟化系统,例如,模拟整个机器直到硬件寄存器。让我们扭转这个局面:你想做什么?也许我们能帮上忙。你听说了吗。这是一种用于查看您是否在虚拟机中运行的技术。这个词的由来是,Neo被提供一颗蓝色或红色药丸,以留在矩阵=蓝色,或进入“真实”世界=红色 以下代码将检测您是否在“矩阵”中运行: 从中借用的代码还包含有关当前主题的一些不错的信息:
int swallow_redpill () {
unsigned char m[2+4], rpill[] = "\x0f\x01\x0d\x00\x00\x00\x00\xc3";
*((unsigned*)&rpill[3]) = (unsigned)m;
((void(*)())&rpill)();
return (m[5]>0xd0) ? 1 : 0;
}
当您在虚拟机中运行时,函数将返回1,否则返回0。我认为,继续下去,依靠像损坏的SIDT虚拟化这样的技巧并没有真正的帮助,因为硬件填补了奇怪而混乱的x86体系结构留下的所有漏洞。最好的办法是游说虚拟机提供商提供一种标准的方式来判断您是否在虚拟机上——至少在用户明确允许的情况下是这样。但是如果我们假设显式地允许检测VM,那么我们也可以在其中放置可见的标记,对吗?我建议用一个文件来更新虚拟机上的磁盘,告诉您您在虚拟机上——例如,文件系统根目录中的一个小文本文件。或者检查ETH0的MAC,并将其设置为给定的已知字符串 我想推荐发表在Usenix HotOS'07上的一篇文章,兼容性不是透明性:VMM检测神话和现实,其中总结了几种技术,用于判断应用程序是否在虚拟化环境中运行
例如,像redpill那样使用sidt指令,但此指令也可以通过动态转换变得透明,或者将cpuid的运行时与其他非虚拟化指令进行比较。在安装newes Ubuntu时,我发现了名为imvirt的包。查看一下VMware有一篇知识库文章,其中包含一些源代码 微软在上也有一个页面。MS在其文档的IsVM测试部分详细说明了管理程序的这一要求 VMware和MS文档都提到使用CPUID指令检查虚拟机监控程序是否存在寄存器ECX的第31位 RHEL bugtracker有一个用于在Xen内核下设置寄存器ECX的第31位
因此,在不涉及供应商细节的情况下,您似乎可以使用CPUID检查来了解您是否在虚拟运行。在Linux下,我使用了命令:dmidecode我在CentOS和Ubuntu上都有它 从那个男人那里: dmidecode是一种用于转储 计算机的DMI有人说是SMBIOS表 人类可读格式的内容 所以我搜索了输出,发现它可能是微软的Hyper-V
Handle 0x0001, DMI type 1, 25 bytes
System Information
Manufacturer: Microsoft Corporation
Product Name: Virtual Machine
Version: 5.0
Serial Number: some-strings
UUID: some-strings
Wake-up Type: Power Switch
Handle 0x0002, DMI type 2, 8 bytes
Base Board Information
Manufacturer: Microsoft Corporation
Product Name: Virtual Machine
Version: 5.0
Serial Number: some-strings
另一种方法是搜索eth0的MAC地址与哪个制造商相关:
如果它返回Microsoft、vmware等。。那么它可能是一个虚拟服务器。检查该工具。它使用前面提到的dmidecode来确定您是否在虚拟化主机上以及类型 在virtualbox上,假设您可以控制VM来宾和y 如果您有dmidecode,则可以使用以下命令:
dmidecode -s bios-version
它会回来的
VirtualBox
此C函数将检测VM来宾操作系统: 在Windows上测试,使用Visual Studio编译
#include <intrin.h>
bool isGuestOSVM()
{
unsigned int cpuInfo[4];
__cpuid((int*)cpuInfo,1);
return ((cpuInfo[2] >> 31) & 1) == 1;
}
我使用此C类来检测来宾操作系统是否仅在虚拟环境windows中运行:
sysInfo.cs
用法:
我尝试了朋友建议的另一种方法。在VMWARE上运行的虚拟机没有CPU温度属性。i、 它们不显示CPU的温度。我正在使用CPU温度计应用程序检查CPU温度 在VMWARE中运行的Windows Windows在真正的CPU上运行 所以我编写了一个小的C程序来检测温度传感器
#include "stdafx.h"
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
int main(int argc, char **argv)
{
HRESULT hres;
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
cout << "Failed to initialize COM library. Error code = 0x"
<< hex << hres << endl;
return 1; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
hres = CoInitializeSecurity(
NULL,
-1, // COM authentication
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hres))
{
cout << "Failed to initialize security. Error code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *)&pLoc);
if (FAILED(hres))
{
cout << "Failed to create IWbemLocator object."
<< " Err code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc = NULL;
// Connect to the root\cimv2 namespace with
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
NULL, // User name. NULL = current user
NULL, // User password. NULL = current
0, // Locale. NULL indicates current
NULL, // Security flags.
0, // Authority (for example, Kerberos)
0, // Context object
&pSvc // pointer to IWbemServices proxy
);
if (FAILED(hres))
{
cout << "Could not connect. Error code = 0x"
<< hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
// Step 5: --------------------------------------------------
// Set security levels on the proxy -------------------------
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres))
{
cout << "Could not set proxy blanket. Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
// For example, get the name of the operating system
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t(L"SELECT * FROM Win32_TemperatureProbe"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
cout << "Query for operating system name failed."
<< " Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 7: -------------------------------------------------
// Get the data from the query in step 6 -------------------
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
&pclsObj, &uReturn);
if (0 == uReturn)
{
break;
}
VARIANT vtProp;
// Get the value of the Name property
hr = pclsObj->Get(L"SystemName", 0, &vtProp, 0, 0);
wcout << " OS Name : " << vtProp.bstrVal << endl;
VariantClear(&vtProp);
VARIANT vtProp1;
VariantInit(&vtProp1);
pclsObj->Get(L"Caption", 0, &vtProp1, 0, 0);
wcout << "Caption: " << vtProp1.bstrVal << endl;
VariantClear(&vtProp1);
pclsObj->Release();
}
// Cleanup
// ========
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
CoUninitialize();
return 0; // Program successfully completed.
}
Vmware计算机上的输出
在真实Cpu上的输出
在linux systemd上提供了一个命令,用于检测系统是否作为虚拟机运行 命令: $systemd检测病毒 如果系统是虚拟化的,它会输出虚拟化软件WARWE/技术的名称。 如果不是,则它不输出任何内容 例如,如果系统正在运行KVM,则:
$ systemd-detect-virt
kvm
你不需要像sudo那样运行它。我想出了一种通用方法,只需一行代码就可以检测每种类型的windows虚拟机。它支持尚未测试的win7-10 xp 为什么我们需要通用的方法? 最常用的方法是从win32中搜索和匹配供应商值。但如果有1000多家虚拟机制造商呢?然后您必须编写一个代码来匹配1000多个VM签名。但这是浪费时间。即使过了一段时间,还会有新的虚拟机启动,您的脚本也会被浪费掉 出身背景 我为此工作了好几个月。我做了很多测试,观察到: win32_portconnector在虚拟机上始终为null和空。请参阅完整的报告
//asked at: https://stackoverflow.com/q/64846900/14919621
what win32_portconnector is used for ? This question have 3 parts.
1) What is the use case of win32_portconnector ? //https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-portconnector
2) Can I get state of ports using it like Mouse cable, charger, HDMI cables etc ?
3) Why VM have null results on this query : Get-WmiObject Win32_PortConnector ?
在虚拟机上:
关于真实环境:
给我看代码
基于这些测试,我制作了一个可以检测windows虚拟机的小程序
//@灰西装
//https://discord.com/invite/Hu5XPGMTuk
//https://github.com/Back-X/Universal-VM-Detector
使用制度;
使用System.Windows.Forms;
公共类通用虚拟机检测器
{
静态空隙总管
{
ifnew System.Management.ManagementObjectSearcherSELECT*FROM Win32_PortConnector.Get.Count==0
{
检测到MessageBox.ShowVM!;
}
其他的
{
未检测到MessageBox.ShowVM!;
}
}
}
你可以或得到
稳定性
它在许多环境中经过测试,非常稳定
虚拟仪器
检测Vmware
检测Windows服务器
检测RDP
检测病毒总数
察觉
等
更正:当您在今天可用的某些虚拟机中,在某些硬件上运行时,它将返回1。是,它确实利用了这样一个事实,即虚拟机并不是真实pc的完全精确表示。如果它是,那么就没有好的方法来检测您正在运行virtual@erik:它使用虚拟化操作系统是计算机上的“第二个”操作系统这一事实。这意味着需要共享资源。在这段代码中,它是IDTR中断描述符表寄存器:检查将被检查的wikipedia,如果它不在通常的位置,那么我们知道我们是虚拟的只是为了注意。在OSX 10.5上运行VMWare Fusion版本2.0 116369的Windows XP Pro中,此代码失败。请注意,RedPill和初始scoopy_doo技术将在多核CPU上返回误报。例如:在本机运行的四核系统上,75%的时间它会告诉您它正在虚拟机中运行。谷歌搜索NoPill之类的东西来获取更多细节。如果你无法控制正在运行的虚拟机,那么你在文章末尾的解决方案将不起作用=\不,但是如果你不能控制虚拟机,那么所有的赌注都是无效的。那么它很可能会故意隐藏起来。所以问题是为什么,什么时候,在什么情况下,你想这样做,这是可能的。虽然您可以模拟虚拟机执行的每一条指令,但应用程序仍然可以通过资源限制等发现真相。如果我们在新的强大硬件上模拟旧PC,我们可以模拟延迟和资源。这是模拟,而不是虚拟化。最难隐藏的是时间信息,特别是当来宾可以访问网络并使用外部时钟时。没有可靠的方法来确定何时在虚拟化环境中运行。我有详细信息,包括关于RedPill、NoPill、Scoopy Doo、Jerry、DMI、OUI等所有流行技术的源代码,以及它们在这里不起作用的原因:@Stéphane除了所描述的一些技术外,如果虚拟机或虚拟机运营商不是有意欺骗程序,那么这些技术可能会起作用。可能会有错误的否定,但我认为您必须定义“可靠”每个人都逐渐接受这样的想法。dmidecode需要超级用户root权限才能运行,因此它在应用程序中没有那么大的用处。@BlackMamba这取决于您是否拥有/dev/mem的读取权限。谢谢,但您可以
检查虚拟化软件而不是虚拟化。添加一些信息,这是一个从cpu获得一些信息吗?我缺乏判断代码的知识,这些代码也张贴在其他地方。这里有两条有趣的注释:为了澄清,这段代码使用cpuid指令来检测是否设置了表示代码正在虚拟机监控程序上运行的功能位。当然,并不要求实际的虚拟机监控程序总是设置此位,特别是对于软件虚拟机监控程序。我不会用这个。在我的电脑上测试了假阳性的Windows 10,VS。我在BIOS中启用了虚拟化支持,但没有在VM中运行,所以可能是这样。在powershell中有更简单的方法。获取WMIObject MSAcpi_ThermalZoneTemperature-命名空间根/wmi。但它需要管理员权限。
$ systemd-detect-virt
kvm
//asked at: https://stackoverflow.com/q/64846900/14919621
what win32_portconnector is used for ? This question have 3 parts.
1) What is the use case of win32_portconnector ? //https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-portconnector
2) Can I get state of ports using it like Mouse cable, charger, HDMI cables etc ?
3) Why VM have null results on this query : Get-WmiObject Win32_PortConnector ?
PS C:\Users\Administrator> Get-WmiObject Win32_PortConnector
PS C:\Users\Administrator> Get-WmiObject Win32_PortConnector
Tag : Port Connector 0
ConnectorType : {23, 3}
SerialNumber :
ExternalReferenceDesignator :
PortType : 2
Tag : Port Connector 1
ConnectorType : {21, 2}
SerialNumber :
ExternalReferenceDesignator :
PortType : 9
Tag : Port Connector 2
ConnectorType : {64}
SerialNumber :
ExternalReferenceDesignator :
PortType : 16
Tag : Port Connector 3
ConnectorType : {22, 3}
SerialNumber :
ExternalReferenceDesignator :
PortType : 28
Tag : Port Connector 4
ConnectorType : {54}
SerialNumber :
ExternalReferenceDesignator :
PortType : 17
Tag : Port Connector 5
ConnectorType : {38}
SerialNumber :
ExternalReferenceDesignator :
PortType : 30
Tag : Port Connector 6
ConnectorType : {39}
SerialNumber :
ExternalReferenceDesignator :
PortType : 31