문제

내 응용 프로그램이 가상화 된 OS 인스턴스 내에서 실행 중인지 여부를 감지해야합니다.

내가 찾았 어 기사 주제에 대한 유용한 정보가 있습니다. 동일한 기사가 여러 곳에 나타납니다. 원래 소스는 확실하지 않습니다. VMware 특정 유효하지 않은 x86 명령을 구현하여 자신에 대한 정보를 반환하는 동안 virtualpc IN 명령이있는 마법 번호와 I/O 포트를 사용합니다.

이것은 실행 가능하지만 두 경우 모두 문서화되지 않은 행동으로 보입니다. VMware 또는 VirtualPC의 향후 릴리스가 메커니즘을 변경할 수 있다고 생각합니다. 더 좋은 방법이 있습니까? 두 제품에 대한 지원 메커니즘이 있습니까?

마찬가지로, 감지하는 방법이 있습니까? Xen 또는 가상 상자?

나는 플랫폼이 고의적으로 스스로 숨기려고하는 경우에 대해 걱정하지 않습니다. 예를 들어, 허니 팟은 가상화를 사용하지만 때로는 맬웨어가이를 감지하는 데 사용할 메커니즘을 가릴 때가 있습니다. 내 앱 이이 허니 팟에서 가상화되지 않았다고 생각하는 것은 신경 쓰지 않고 "최선의 노력"솔루션을 찾고 있습니다.

응용 프로그램은 대부분 Java이지만이 특정 기능에 기본 코드와 JNI를 사용할 것으로 기대합니다. Windows XP/Vista 지원이 가장 중요하지만, 참조 기사에 설명 된 메커니즘은 X86의 일반적인 특징이며 특정 OS 시설에 의존하지 않습니다.

도움이 되었습니까?

해결책

들어 보셨습니까? 블루 알약, 빨간 알약?. 가상 머신에서 실행 중인지 아닌지 확인하는 데 사용되는 기술입니다. 용어의 기원은 매트릭스 영화 NEO에 파란색 또는 빨간 알약이 제공되는 경우 (매트릭스 = 파란색 안에 머무르거나 '실제'세계 = 빨간색으로 들어가기 위해).

다음은 '매트릭스'내부에서 실행중인 Wheter를 감지하는 몇 가지 코드입니다.
(코드가 빌렸다 이 지역 여기에는 당면한 주제에 대한 좋은 정보가 포함되어 있습니다) :

 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이 반환됩니다.

다른 팁

Linux에서 나는 명령을 사용했습니다. dmidecode (Centos와 Ubuntu에 모두 가지고 있습니다)

남자로부터 :

DMIDECODE는 컴퓨터의 DMI (일부 SMBIOS) 테이블 내용을 사람이 읽을 수있는 형식으로 덤프하기위한 도구입니다.

그래서 나는 출력을 검색하고 아마도 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

또 다른 방법은 ETH0의 MAC 주소가 어떤 제조업체를 검색하는 것입니다. http://www.coffer.com/mac_find/

Microsoft, VMware 등을 반환하면 가상 서버 일 것입니다.

vmware에는 a 소프트웨어가 VMware 가상 머신에서 실행 중인지 확인하는 메커니즘 소스 코드가있는 지식베이스 기사.

Microsoft에는 페이지가 있습니다 "하이퍼 바이저가 설치되어 있는지 결정". MS는 ISVM 테스트에서 하이퍼 바이저 의이 요구 사항을 철자합니다. "서버 가상화 검증 테스트" 문서

VMware 및 MS DOCS는 CPUID 명령을 사용하여 하이퍼 바이저-프리젠트 비트를 확인하기 위해 언급합니다 (레지스터 ECX의 비트 31)

Rhel Bugtracker에는 하나가 있습니다 "CPUID 리프 0x00000001의 ISVM 비트 (ECX : 31)를 설정해야합니다." Xen 커널 아래에 레지스터 ecx의 비트 31을 설정합니다.

따라서 공급 업체 세부 사항에 들어 가지 않으면 CPUID 수표를 사용하여 실제로 실행 중인지 아닌지 알 수 있습니다.

아닙니다. 완전한 정확도로 감지하는 것은 불가능합니다. 일부 가상화 시스템 QEMU, 전체 기계를 하드웨어 레지스터로 모방하십시오. 이걸 돌리자 : 당신은 무엇을하려고합니까? 어쩌면 우리는 그것을 도울 수 있습니다.

하드웨어가 이상하고 지저분한 X86 아키텍처가 남은 모든 구멍을 막기 때문에 깨진 SIDT 가상화와 같은 트릭에 의존하는 것은 실제로 도움이되지 않는다고 생각합니다. 최선의 방법은 VM 제공 업체에게 VM에 있다고 말할 수있는 표준 방법으로 로비하는 것입니다. 최소한 사용자가 명시 적으로 허용 한 경우. 그러나 VM을 명시 적으로 감지 할 수 있다고 가정하면 눈에 보이는 마커를 배치 할 수 있습니다. 예를 들어 파일 시스템의 루트에있는 작은 텍스트 파일 인 VM에 있음을 알려주는 파일로 VM의 디스크를 업데이트하는 것이 좋습니다. 또는 ETH0의 Mac을 검사하고 주어진 알려진 문자열로 설정하십시오.

VirtualBox에서 VM 게스트를 제어하고 DMIDECODE가 있다고 가정하면이 명령을 사용할 수 있습니다.

dmidecode -s bios-version

그리고 그것은 돌아올 것입니다

VirtualBox

Usenix Hotos '07에 게시 된 논문을 추천하고 싶습니다. Comptibility는 투명성이 아닙니다 : VMM 탐지 신화 및 현실, 이는 응용 프로그램이 가상화 된 환경에서 실행 중인지 여부를 알리는 몇 가지 기술을 마무리합니다.

예를 들어, SIDT 명령어를 RedPill과 같이 사용하거나 (이 명령어는 동적 번역으로 투명하게 만들 수도 있음) CPUID의 런타임을 다른 비 계약 지침과 비교하십시오.

Linux에서는 /proc /cpuinfo를보고 할 수 있습니다. VMware에있는 경우 일반적으로 베어 메탈에있는 경우와는 다른 것은 아니지만 항상 그런 것은 아닙니다. Virtuozzo는 기본 하드웨어에 대한 통과를 보여줍니다.

Newes Ubuntu를 설치하는 동안 Imvirt라는 패키지를 발견했습니다. 그것을 살펴보십시오 http://micky.ibh.net/~liske/imvirt.html

이 C 함수는 VM 게스트 OS를 감지합니다.

(Windows에서 테스트, Visual Studio로 컴파일)

#include <intrin.h>

    bool isGuestOSVM()
    {
        unsigned int cpuInfo[4];
        __cpuid((int*)cpuInfo,1);
        return ((cpuInfo[2] >> 31) & 1) == 1;
    }

읽어서 시도하십시오 smbios 구조, 특히 구조 바이오스 정보.

Linux에서는 사용할 수 있습니다 dmidecode 정보를 탐색하는 유틸리티.

도구를 확인하십시오 미덕. 이전에 언급 된 DMIDECODE를 사용하여 가상화 된 호스트와 유형에 있는지 확인합니다.

나는 이것을 사용한다 C# 게스트 OS가 가상 환경 내에서 실행 중인지 감지하는 클래스 (창문 만):

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

}

용법:

        if (sysInfo.isVM()) { 
            Console.WriteLine("VM FOUND");
        }

Linux SystemD는 시스템이 가상 머신으로 실행 중인지 여부를 감지하기위한 명령을 제공합니다.

명령:
$ systemd-detect-virt

시스템이 가상화되면 IT 출력 소프트웨어/기술의 IT 출력 이름. 그렇지 않다면 출력이 발생합니다 none

예를 들어 시스템이 KVM을 실행중인 경우 :

$ systemd-detect-virt
kvm

당신은 그것을 sudo로 실행할 필요가 없습니다.

친구가 제안한 다른 접근법을 시도했습니다. VMware에서 실행되는 Virtual Machines에는 CPU 온도 속성이 없습니다. 즉 그들은 CPU의 온도를 보여주지 않습니다. CPU 온도를 확인하기 위해 CPU 온도계 응용 프로그램을 사용하고 있습니다.

(VMware에서 실행되는 Windows) enter image description here

(실제 CPU에서 실행되는 Windows) enter image description here

그래서 나는 온도 센서를 감지하기 위해 작은 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 시스템의 출력 enter image description here

실제 CPU의 출력 enter image description here

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top