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.

Foi útil?

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;
    }

Tente lendo os SMBIOS estruturas, especialmente as estruturas com o BIOS informações.

No Linux, você pode usar o utilitário dmidecode para procurar as informações.

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 no VMware) enter descrição da imagem aqui

(Windows rodando em um real CPU) enter descrição da imagem aqui

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.

}

Saída em uma máquina Vmware enter descrição da imagem aqui

saída em uma CPU real enter descrição da imagem aqui

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top