VM の下で実行していることを確認するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/39533

  •  09-06-2019
  •  | 
  •  

質問

コードが VM 内で実行されていることを VM 内から識別する方法はありますか?

特に VM にプロバイダーの拡張機能 (VirtualBox や VMWare など) がインストールされている場合、特定の VM システムを識別する簡単な方法は多かれ少なかれあると思います。しかし、CPU 上で直接実行されていないことを識別する一般的な方法はあるのでしょうか?

役に立ちましたか?

解決

これに関する研究の多くは、いわゆる「ブルーピル」攻撃、つまり検出を積極的に回避しようとする悪意のあるハイパーバイザーの検出に特化しています。

VM を検出する古典的なトリックは、ITLB にデータを設定し、次の命令を実行することです。 しなければならない 仮想化されたら (ハイパーバイザーに制御を渡すときに、プロセッサの状態は必ずクリアされます)、さらにコードを実行して、ITLB がまだ設定されているかどうかを検出します。それに関する最初の論文は次のとおりです。 ここ, と、かなりカラフルな説明があります。 研究者のブログ そして代替案 ブログ記事への Wayback Machine リンク (画像が壊れています).

これに関する議論の結論は、悪意のあるハイパーバイザーを検出する方法は常に存在し、隠蔽しようとしていないハイパーバイザーを検出する方がはるかに簡単であるということです。

他のヒント

Red Hat には、どの仮想化製品 (存在する場合) が実行されているかを検出するプログラムがあります。 virt-what.

サードパーティが管理するツールを使用することは、独自の検出ロジックを導入するよりも長期的には優れた戦略です。より多くの目 (より多くの仮想化製品に対するテスト) など。

より経験的なアプローチは、既知の VM デバイス ドライバーを確認することです。たとえば、VMware ディスプレイ アダプター、ディスク ドライブ、ネットワーク アダプターなどを見つけるための WMI クエリを作成できます。これは、環境内の既知の VM ホスト タイプのみを考慮すればよいことがわかっている場合に適しています。こちらです Perl でこれを行う例, 、選択した言語に移植できます。

それはあなたが何を求めているかによって異なります。

  • VM が意図的に隠れていない場合は、既知のフックを使用できます。たとえば、VmWare ドライバー、メモリ内の特定の文字列の存在、またはその他の特定の兆候を探します。

  • VM が実際に特別なことを実行してもらいたい場合は、プロセッサの ID を変更したり、それを検出するためにアクセスできる特殊なレジスタを追加したりするなど、明らかなフックが用意されています。または、メモリ内の既知の場所にある特別なデバイスです (世界の物理メモリ空間に直接アクセスできると仮定します)。IBM Power6 や Sun UltraSparc T1/T2 などの最新のマシン設計は、常にハイパーバイザーを実行するように設計されており、生のハードウェア上で直接実行することは決してないことに注意してください。OS が使用する「ハードウェア」へのインターフェイスは、実際にはハイパーバイザー ソフトウェア層のインターフェイスであり、それを回避する方法はありません。この場合、定数「はい」であるため、検出は簡単です。これは、オーバーヘッドに余裕のあるすべてのコンピュータ システムにとっておそらく将来の方向性です。たとえば、Freescale QorIQ P4080 チップ (www.freescale.com/qoriq) などの最近の設計でのサポートを見てください。

  • VM が意図的に隠そうとしているのに、その存在を追いかけている場合は、タイミングの乱れや VM の異なるパフォーマンス プロファイルにより、ほとんどの場合、VM がバレてしまうといういたちごっこになります。明らかに、これは VM の実装方法と、アーキテクチャ内でどの程度のハードウェア サポートが導入されているかによって異なります (zSeries メインフレームは、通常の x86 よりも、特定の OS の下で VM または VM スタックの存在を隠すのがはるかに優れていると思います)たとえば、マシンです)。見る http://jakob.engbloms.se/archives/97 このトピックに関する議論のために。VM として隠蔽しようとすることは可能ですが、十分に努力すれば検出が常に成功する可能性が非常に高くなります。

以前、VM 内にいるかどうかを示すアセンブリ コード スニペットに遭遇しました。Google で検索しましたが、元の記事は見つかりませんでした。

しかし、私はこれを見つけました: プログラムが仮想マシン内で実行されているかどうかを検出します.

それが役に立てば幸い。

ほとんどの場合、そうしようとすべきではありません。いくつかの特定の場合を除いて、誰かが VM でコードを実行していても気にする必要はありません。

必要に応じて、Linux で最も一般的な方法は、 /sys/devices/virtual/dmi/id/product_name, 、ほとんどの実システムではラップトップ/メインボードの名前がリストされ、ほとんどの仮想システムではハイパーバイザーの名前がリストされます。 dmidecode | grep Product も一般的な方法ですが、root アクセスが必要だと思います。

がここにあります (Java + Windows) 基盤となるマシンが物理か仮想かを識別するソリューション。

仮想マシンの例:

メーカー

  • ゼン
  • マイクロソフト
  • イノテック社
  • レッドハット
  • ヴイエムウェア株式会社

モデル

  • HVM ドーム
  • 仮想マシン
  • バーチャルボックス
  • KVM
  • VMware仮想プラットフォーム

    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    import java.util.List;
    
    public abstract class OSUtil {
    
    public static final List<String> readCmdOutput(String command) {
        List<String> result = new ArrayList<>();
    
        try {
            Process p=Runtime.getRuntime().exec("cmd /c " + command);
            p.waitFor();
            BufferedReader reader=new BufferedReader(
                    new InputStreamReader(p.getInputStream())
                    );
            String line;
            while((line = reader.readLine()) != null) {
                if(line != null && !line.trim().isEmpty()) {
                    result.add(line);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    
        return result;
    }
    
    public static final String readCmdOutput(String command, int lineNumber) {
        List<String> result = readCmdOutput(command);
        if(result.size() < lineNumber) {
            return null;
        }
    
        return result.get(lineNumber - 1);
    }
    
    public static final String getBiosSerial() {
        return readCmdOutput("WMIC BIOS GET SERIALNUMBER", 2);
    }
    
    public static final String getHardwareModel() {
        return readCmdOutput("WMIC COMPUTERSYSTEM GET MODEL", 2);
    }
    
    public static final String getHardwareManufacturer() {
        return readCmdOutput("WMIC COMPUTERSYSTEM GET MANUFACTURER", 2);
    }
    
    public static void main(String[] args) {
        System.out.println("BIOS Serial: " + getBiosSerial());
        System.out.println("Hardware Model: " + getHardwareModel());
        System.out.println("Hardware Manufacturer: " + getHardwareManufacturer());
    }
    }
    

出力を使用して、それが VM であるか物理マシンであるかを判断できます。

物理マシンの出力:

BIOS シリアル:2HC3J12
ハードウェアモデル:インスパイロン 7570
ハードウェアメーカー:デル株式会社

仮想マシンの出力:

BIOS シリアル:0
ハードウェアモデル:イノテックGmBH
ハードウェアメーカー:バーチャルボックス

良い例の 1 つは、マザーボードの製造元に対して WMI クエリを実行しているようで、「Microsoft」が返された場合、VM 内にいることです。これは VMWare だけのものだと思います。VM ホスト ソフトウェアごとに異なる方法がある可能性があります。

この記事はこちら http://blogs.technet.com/jhoward/archive/2005/07/26/407958.aspx には、VM (少なくとも VMWare と VirtualPC) 内にいるかどうかを検出するためのいくつかの良い提案とリンクが含まれています。

ネットワーク接続の MAC アドレスを調べることで、仮想マシン内にいるかどうかを識別できる場合があります。たとえば、Xen では通常、特定の範囲のアドレス 00:16:3e:xx:xx:xx を使用することを推奨します。

どの MAC アドレスを指定するかはシステム管理者次第であるため、これは保証されません。

Linux システムでは、/proc で共通ファイルの検索を試みることができます。

たとえば、/proc/vz/ の存在は OpenVZ であることを示します。

VM の環境を検出するための完全なガイドは次のとおりです Linux では「丸薬を飲む」必要はありません:)

TrapKIT は、VMware 識別用ツール ScoopyNG を提供します -- 回避テクニックを回避しようとしますが、必ずしも VMware 以外の仮想化ソフトウェアをターゲットにするわけではありません。ソースとバイナリの両方が利用可能です。

VM が適切に機能する場合、仮想化されていることはクライアントには見えないはずです。ただし、他の手がかりに注目することもできます。

VM 環境に固有の既知のドライバーまたはソフトウェアを探すのが最善の方法だと思います。

たとえば、Windows を実行している VMWare クライアントでは、vmxnet.sys がネットワーク ドライバーとなり、VMware アクセラレーション AMD PCNet アダプターとして表示されます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top