/* * Copyright (c) 2023 ETH Zürich, Educational Development and Technology (LET) * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ using System.Linq; using SafeExamBrowser.Logging.Contracts; using SafeExamBrowser.SystemComponents.Contracts; namespace SafeExamBrowser.SystemComponents { public class VirtualMachineDetector : IVirtualMachineDetector { private const string QEMU_MAC_PREFIX = "525400"; private const string VIRTUALBOX_MAC_PREFIX = "080027"; private static readonly string[] DeviceBlacklist = { // Hyper-V "PROD_VIRTUAL", "HYPER_V", // QEMU "qemu", "ven_1af4", "ven_1b36", "subsys_11001af4", // VirtualBox "vbox", "vid_80ee", // VMware "PROD_VMWARE", "VEN_VMWARE", "VMWARE_IDE" }; private static readonly string[] DeviceWhitelist = { // Microsoft Virtual Disk Device "PROD_VIRTUAL_DISK", // Microsoft Virtual DVD Device "PROD_VIRTUAL_DVD" }; private readonly ILogger logger; private readonly ISystemInfo systemInfo; public VirtualMachineDetector(ILogger logger, ISystemInfo systemInfo) { this.logger = logger; this.systemInfo = systemInfo; } public bool IsVirtualMachine() { var biosInfo = systemInfo.BiosInfo.ToLower(); var isVirtualMachine = false; var macAddress = systemInfo.MacAddress; var manufacturer = systemInfo.Manufacturer.ToLower(); var model = systemInfo.Model.ToLower(); var devices = systemInfo.PlugAndPlayDeviceIds; isVirtualMachine |= biosInfo.Contains("hyper-v"); isVirtualMachine |= biosInfo.Contains("virtualbox"); isVirtualMachine |= biosInfo.Contains("vmware"); isVirtualMachine |= manufacturer.Contains("microsoft corporation") && !model.Contains("surface"); isVirtualMachine |= manufacturer.Contains("parallels software"); isVirtualMachine |= manufacturer.Contains("qemu"); isVirtualMachine |= manufacturer.Contains("vmware"); isVirtualMachine |= model.Contains("virtualbox"); if (macAddress != null && macAddress.Count() > 2) { isVirtualMachine |= macAddress.StartsWith(QEMU_MAC_PREFIX) || macAddress.StartsWith(VIRTUALBOX_MAC_PREFIX); } foreach (var device in devices) { isVirtualMachine |= DeviceBlacklist.Any(d => device.ToLower().Contains(d.ToLower())) && DeviceWhitelist.All(d => !device.ToLower().Contains(d.ToLower())); } logger.Debug($"Computer '{systemInfo.Name}' appears {(isVirtualMachine ? "" : "not ")}to be a virtual machine."); return isVirtualMachine; } } }