Detectar OS virtualizada de um aplicativo?
-
03-07-2019 - |
Pergunta
Eu preciso para detectar se meu aplicativo está sendo executado dentro de uma instância OS virtualizado ou não.
Eu encontrei um artigo com algumas informações úteis sobre o tema. O mesmo artigo aparece em vários lugares, eu tenho certeza da fonte original. VMware implementa um especial de instruções x86 inválida à informação de retorno sobre si mesmo, enquanto VirtualPC usa um número de magia e de porta I / o com uma instrução IN.
Este é viável, mas parece ser um comportamento em situação irregular em ambos os casos. Suponho que uma futura versão do VMWare ou VirtualPC pode alterar o mecanismo. Existe uma maneira melhor? Existe um mecanismo de suporte para um ou outro produto?
Da mesma forma, há uma maneira de detectar Xen ou VirtualBox ?
Eu não estou preocupado com os casos em que a plataforma está deliberadamente tentando esconder-se. Por exemplo, honeypots usar a virtualização, mas às vezes obscurecer os mecanismos que o malware usaria para detectá-lo. Eu não me importo que o meu aplicativo poderia pensar que não é virtualizado nestes honeypots, estou apenas à procura de um "melhor esforço" solução.
A aplicação é principalmente Java, embora eu estou esperando para usar código nativo mais JNI para esta função particular. suporte do Windows XP / Vista é mais importante, não que os mecanismos descritos no artigo referenciado são recursos genéricos de x86 e fazer confiar em qualquer instalação OS particular.
Solução
Você já ouviu falar sobre pílula azul, pílula vermelha? . É uma técnica usada para ver se você estiver executando em uma máquina virtual ou não. A origem do termo deriva filme matriz onde Neo é oferecido um azul ou uma pílula vermelha (a estadia no interior da matriz = azul, ou para entrar no mundo 'real' = vermelho).
O seguinte é um código que detecta wheter você estiver executando dentro 'The Matrix' ou não:
(Código emprestado neste site que também contém algumas informações agradável sobre o tópico em questão):
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;
}
A função retornará 1 quando você está executando dentro de uma máquina virutal e 0 caso contrário.
Outras dicas
No Linux eu usei o comando: dmidecode (eu tê-lo tanto no CentOS e Ubuntu)
do homem:
dmidecode é uma ferramenta para um de dumping DMI do computador (alguns dizem SMBIOS) mesa conteúdo em um formato legível.
Então eu procurei a saída e descobriu seu provavelmente Microsoft 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
Outra forma é procurar a qual fabricante o endereço MAC do eth0 está relacionada com: http://www.coffer.com/mac_find /
Se ele retornar Microsoft, VMware e etc .. então o seu provavelmente um servidor virtual.
VMware tem um Mecanismos para determinar se o software está sendo executado em uma máquina virtual VMware artigo da base de Conhecimento que tem algum código-fonte.
A Microsoft também tem uma página sobre "Determinar se Hypervisor está instalado ". MS explicita esta exigência de um hypervisor na seção "de sua "virtualização de Servidores Validation Test" documento
Os documentos VMware e MS ambos mencionam utilizando a instrução CPUID para verificar o bit hipervisor-presente (bit 31 do registo ECX)
O bugtracker RHEL tem um para "deve definir bit ISVM (ECX: 31) para CPUID folha 0x00000001" para conjunto de bits 31 do registo ECX sob o kernel Xen.
Assim, sem entrar em detalhes vendedor parece que você poderia usar a verificação CPUID de saber se você está rodando virtualmente ou não.
No. Isso é impossível de detectar com precisão absoluta. Alguns sistemas de virtualização, como QEMU , emular uma máquina inteira para baixo para os registros de hardware. Vamos virar esse jogo: o que é que você está tentando fazer? Talvez possamos ajudar com isso.
Eu acho que daqui para frente, contando com truques como a virtualização SIDT quebrado não está realmente indo para ajuda como o hardware conecta todos os buracos que a arquitetura x86 estranho e confuso não deixaram. O melhor seria para pressionar os fornecedores VM para uma forma padrão para dizer que você está em uma VM - pelo menos para o caso quando o usuário permitiu que explicitamente. Mas se assumirmos que estamos permitindo explicitamente a VM a ser detectado, que pode muito bem colocar marcadores visíveis lá, certo? Sugiro apenas atualizar o disco em seu VMs com um arquivo dizendo que você está em uma VM - um pequeno arquivo de texto na raiz do sistema de arquivos, por exemplo. Ou inspecionar o MAC de ETH0, e definir que uma determinada cadeia conhecido.
no VirtualBox, supondo que você tem controle sobre o convidado VM e você tem dmidecode, você pode usar este comando:
dmidecode -s bios-version
e ele irá retornar
VirtualBox
Eu gostaria de recomendar um artigo publicado na Usenix HotOS '07, Comptibility é Não Transparência: VMM Mitos e Realidades de detecção , que conclui várias técnicas para dizer se o aplicativo está sendo executado em um virtualizado meio Ambiente.
Por exemplo, a instrução uso SIDT como Redpill faz (mas esta instrução também pode ser feita transparente pela tradução do dinâmico), ou comparar o tempo de execução de cpuid contra outras instruções não-virtualizados.
No Linux, você pode denunciá-on / proc / cpuinfo. Se está em VMware, que normalmente vem-up diferente do que se é em metal nu, mas nem sempre. Virtuozzo mostra um pass-through para o hardware subjacente.
Ao instalar os newes Ubuntu eu descobri o pacote chamado imvirt. Ter um olhar para ele em http://micky.ibh.net/~liske/imvirt.html
Esta função C irá detectar VM Visitante OS:
(Testado em Windows, compilado com Visual Studio)
#include <intrin.h>
bool isGuestOSVM()
{
unsigned int cpuInfo[4];
__cpuid((int*)cpuInfo,1);
return ((cpuInfo[2] >> 31) & 1) == 1;
}
Verifique a ferramenta virt-o . Ele usa dmidecode mencionado anteriormente para determinar se você está em um host virtualizado e do tipo.
Eu uso essa classe C#
para detectar se o sistema operacional do cliente está sendo executado dentro de um ambiente virtual ( somente para Windows ):
sysInfo.cs
using System;
using System.Management;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
public class sysInfo
{
public static Boolean isVM()
{
bool foundMatch = false;
ManagementObjectSearcher search1 = new ManagementObjectSearcher("select * from Win32_BIOS");
var enu = search1.Get().GetEnumerator();
if (!enu.MoveNext()) throw new Exception("Unexpected WMI query failure");
string biosVersion = enu.Current["version"].ToString();
string biosSerialNumber = enu.Current["SerialNumber"].ToString();
try
{
foundMatch = Regex.IsMatch(biosVersion + " " + biosSerialNumber, "VMware|VIRTUAL|A M I|Xen", RegexOptions.IgnoreCase);
}
catch (ArgumentException ex)
{
// Syntax error in the regular expression
}
ManagementObjectSearcher search2 = new ManagementObjectSearcher("select * from Win32_ComputerSystem");
var enu2 = search2.Get().GetEnumerator();
if (!enu2.MoveNext()) throw new Exception("Unexpected WMI query failure");
string manufacturer = enu2.Current["manufacturer"].ToString();
string model = enu2.Current["model"].ToString();
try
{
foundMatch = Regex.IsMatch(manufacturer + " " + model, "Microsoft|VMWare|Virtual", RegexOptions.IgnoreCase);
}
catch (ArgumentException ex)
{
// Syntax error in the regular expression
}
return foundMatch;
}
}
}
Uso:
if (sysInfo.isVM()) {
Console.WriteLine("VM FOUND");
}
No linux systemd fornece um comando para detectar se o sistema está funcionando como uma máquina virtual ou não.
Comando:
$ systemd-detect-virt
Se o sistema é virtualizado o nome do virtuslization softwarwe / tecnologia que saídas.
Se não, então saídas none
Por exemplo, se o sistema está funcionando KVM então:
$ systemd-detect-virt
kvm
Você não precisa executá-lo como sudo.
Eu tentei uma abordagem diferente sugerida por minha corrida friend.Virtual Machines em VMWARE esquentar têm propriedade temperatura da CPU. ou seja eles não mostrar a temperatura da CPU. Eu estou usando CPU Termômetro Aplicação Para verificar a temperatura da CPU.
(Windows rodando em um real CPU)
Então eu Código Um pequeno programa C para detectar a temperatura Senser
#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.
}