0

私は仮想マシンの世界の初心者で、ちょっとした質問があります。ソフトウェアが VM (VMware Player など) で実行されている場合、それが VM にインストールされていることをどのように認識しますか? ソフトウェアはオペレーティング システムから情報を取得しますか、それともソフトウェアとハ​​ードウェア (VMware Player) の間で直接通信しますか? 前もって感謝します

4

2 に答える 2

3

残念ながら、唯一の答えはありません。各仮想マシンには、使用できる一種のブリッジがありますが、検出する VM ごとに特定のチェックを記述する必要があります (例は VC++ 固有ですが、コンパイラに簡単に適応させることができます)。理論的には、VM の下で実行しているかどうかを判断できないことに注意してください。

VMウェア

VMWare はIN命令を使用して、ゲストからホストへの通信を処理します。通常、この命令はユーザーモードでは使用できず、例外がスローされますが、VM が処理します。例外をキャッチすると、VMWare で実行されていない (またはIN命令を実行する権限がある) ことがわかります。特権があるかどうか、または WMWare で実行しているかどうかを判断するための 2 番目のテストはほとんど役に立ちませんが、これは標準的な検出コードであり、完全を期すためにここに記述します (レジスタ内の予想される文字列 VMXhをチェックするだけEBXです。必要な値でいくつかのレジスタを初期化する必要があることに注意してください)。 .)

bool IsRunningInsideVmWare()
{
    bool flag = true;

    __try
    {
        __asm
        {
            push    edx
            push    ecx
            push    ebx

            mov     eax, 'VMXh'
            mov     ebx, 0
            mov     ecx, 10
            mov     edx, 'VX'

            in      eax, dx
            cmp     ebx, 'VMXh'
            setz    [flag]

            pop     ebx
            pop     ecx
            pop     edx
        }
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        flag = false;
    }

    return flag;
}

仮想 PC

ゲストは、存在しない命令0f3f070bを使用してホストと通信できます。次に、そのような命令を発行できます。VM はそれを正しく解釈しますが、物理 CPU は例外をスローします (問題のある命令をキャッチしてジャンプすることができます)。この例EBXでは、例外ハンドラーで既知の値に設定すると、このシナリオを検出できます。

DWORD __forceinline VpcExceptionFilter(LPEXCEPTION_POINTERS ep)
{
    ep->ContextRecord->ctx->Ebx = -1;
    ep->ContextRecord->ctx->Eip += 4;

    return EXCEPTION_CONTINUE_EXECUTION;
}

bool IsRunningInsideVpc()
{
    bool flag = false;

    __try
    {
        _asm
        {
            push    ebx

            mov     eax, 1
            mov     ebx, 0 

            __emit  0Fh
            __emit  3Fh
            __emit  07h
            __emit  0Bh

            test    ebx, ebx
            setz    [flag]

            pop     ebx
        }
    }
    __except(VpcExceptionFilter(GetExceptionInformation()))
    {
    }

    return flag;
}

VirtualBox

VirtualBox を検出するのは非常に簡単で、疑似デバイス\\.\VBoxMiniRdrDNが存在するかどうかを確認するだけです。

bool IsRunningInsideVirtualBox()
{
    HANDLE handle = CreateFile("\\\\.\\VBoxMiniRdrDN", GENERIC_READ, FILE_SHARE_READ, 
        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    if (handle != INVALID_HANDLE_VALUE)
    {
        CloseHandle(handle);
        return true;
    }

    return false;
}

WMI と次のクエリを使用して、もう少し一般的なことを行うことができます (Windows で実行していると仮定します)。

  • とのWin32_BaseBoard試合Nameで。(?i)(Hyper-V|Virtual Machine|Microsoft|VMware|VirtualBox|Parallels Virtual)
  • Win32_ComputerSystem試合ModelManufacturer対戦(?i)(Hyper-V|Virtual Machine|VMware|VirtualBox)で。
  • とのWin32_VideoController試合Nameで。(?i)Hyper-V

CPUID手順も役立ちます (これらの値がサポートされている場合)。

EAX0 ( Get vendor ID ) に設定すると、 と、CPU ベンダー名を含む ASCII 文字列が取得されます(EBX一覧EDXについてECXWikipediaを参照してください)。もちろん、VM は偽の名前を返すか、不明な VM である可能性があります。

VM で実行している場合、1 に設定すると ( Processor Info and Feature Bits ) ( hypervisor )のEAXビット31ECX1に設定されます。ここでも、VM は偽の結果を返す場合があります (一部の VM はこのビットを尊重しません)。


この問題に対処しなければならなかったとき、VM でサポートされていないハードウェアトリック/機能 (USB レガシー サポートなど)もチェックしようとしましたが、本番環境で使用するには信頼性が十分ではないことがわかりました。


コメントで、あなたは Android で実行していると言いました。それはまったく別の話ですが、一般的な手法は、WMI (または上記の組み合わせ) について述べたことと似ています。一般的な方法は、よく知られているエミュレーターのデバイス名文字列を確認することです。Android 7 以降では、特定のフラグがありro.kernel.qemuます。

それらの値を偽造できますか? はい、例を参照してください。エミュレーターで ro.kernel.qemu を 0 に設定する方法はありますか? . エミュレーションでの使用を阻止しようとする適切なアプリケーションは、複数の検出手法も使用することに注意してください ( Android: Get Hardware Information Programmaticallyも参照してください)。

于 2017-09-08T11:10:39.267 に答える