SEBWIN-717: Merged changes & minor code cleanup.
This commit is contained in:
commit
b36df9ad5a
4 changed files with 144 additions and 125 deletions
|
@ -18,6 +18,11 @@ namespace SafeExamBrowser.SystemComponents.Contracts
|
|||
/// </summary>
|
||||
string BiosInfo { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the CPU.
|
||||
/// </summary>
|
||||
string CpuName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Reveals whether the computer system contains a battery.
|
||||
/// </summary>
|
||||
|
|
|
@ -229,7 +229,6 @@ namespace SafeExamBrowser.SystemComponents.Registry
|
|||
|
||||
try
|
||||
{
|
||||
logger.Info($"default(RegistryKey) == null: {key == null}");
|
||||
if (TryGetBaseKeyFromKeyName(keyName, out var baseKey, out var subKey))
|
||||
{
|
||||
key = baseKey.OpenSubKey(subKey);
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace SafeExamBrowser.SystemComponents
|
|||
public class SystemInfo : ISystemInfo
|
||||
{
|
||||
public string BiosInfo { get; private set; }
|
||||
public string CpuName { get; private set; }
|
||||
public bool HasBattery { get; private set; }
|
||||
public string MacAddress { get; private set; }
|
||||
public string Manufacturer { get; private set; }
|
||||
|
@ -33,6 +34,7 @@ namespace SafeExamBrowser.SystemComponents
|
|||
{
|
||||
InitializeBattery();
|
||||
InitializeBiosInfo();
|
||||
InitializeCpuName();
|
||||
InitializeMacAddress();
|
||||
InitializeMachineInfo();
|
||||
InitializeOperatingSystem();
|
||||
|
@ -79,6 +81,34 @@ namespace SafeExamBrowser.SystemComponents
|
|||
}
|
||||
}
|
||||
|
||||
private void InitializeCpuName()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Processor"))
|
||||
using (var results = searcher.Get())
|
||||
{
|
||||
foreach (var cpu in results)
|
||||
{
|
||||
using (cpu)
|
||||
{
|
||||
foreach (var property in cpu.Properties)
|
||||
{
|
||||
if (property.Name.Equals("Name"))
|
||||
{
|
||||
CpuName = Convert.ToString(property.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
CpuName = "";
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeMachineInfo()
|
||||
{
|
||||
var model = default(string);
|
||||
|
@ -192,7 +222,7 @@ namespace SafeExamBrowser.SystemComponents
|
|||
using (var searcher = new ManagementObjectSearcher("SELECT MACAddress FROM Win32_NetworkAdapterConfiguration WHERE DNSDomain IS NOT NULL"))
|
||||
using (var results = searcher.Get())
|
||||
{
|
||||
if (results != null && results.Count > 0)
|
||||
if (results != default && results.Count > 0)
|
||||
{
|
||||
using (var networkAdapter = results.Cast<ManagementObject>().First())
|
||||
{
|
||||
|
@ -226,11 +256,11 @@ namespace SafeExamBrowser.SystemComponents
|
|||
using (var searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT DeviceID FROM Win32_PnPEntity"))
|
||||
using (var results = searcher.Get())
|
||||
{
|
||||
foreach (ManagementObject queryObj in results)
|
||||
foreach (var device in results.Cast<ManagementObject>())
|
||||
{
|
||||
using (queryObj)
|
||||
using (device)
|
||||
{
|
||||
foreach (var property in queryObj.Properties)
|
||||
foreach (var property in device.Properties)
|
||||
{
|
||||
if (property.Name.Equals("DeviceID"))
|
||||
{
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
|
||||
using System.Linq;
|
||||
using System.Management;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.SystemComponents.Contracts;
|
||||
using SafeExamBrowser.SystemComponents.Contracts.Registry;
|
||||
|
@ -16,6 +15,7 @@ namespace SafeExamBrowser.SystemComponents
|
|||
{
|
||||
public class VirtualMachineDetector : IVirtualMachineDetector
|
||||
{
|
||||
private const string MANIPULATED = "000000000000";
|
||||
private const string QEMU_MAC_PREFIX = "525400";
|
||||
private const string VIRTUALBOX_MAC_PREFIX = "080027";
|
||||
|
||||
|
@ -52,176 +52,161 @@ namespace SafeExamBrowser.SystemComponents
|
|||
|
||||
public bool IsVirtualMachine()
|
||||
{
|
||||
var biosInfo = systemInfo.BiosInfo;
|
||||
var devices = systemInfo.PlugAndPlayDeviceIds;
|
||||
var isVirtualMachine = false;
|
||||
var macAddress = systemInfo.MacAddress;
|
||||
var manufacturer = systemInfo.Manufacturer;
|
||||
var model = systemInfo.Model;
|
||||
|
||||
isVirtualMachine |= HasVirtualDevice();
|
||||
isVirtualMachine |= HasVirtualMacAddress();
|
||||
isVirtualMachine |= IsVirtualCpu();
|
||||
isVirtualMachine |= IsVirtualRegistry();
|
||||
isVirtualMachine |= IsVirtualSystemInfo(biosInfo, manufacturer, model);
|
||||
isVirtualMachine |= IsVirtualWmi();
|
||||
|
||||
if (macAddress != null && macAddress.Count() > 2)
|
||||
{
|
||||
isVirtualMachine |= macAddress.StartsWith(QEMU_MAC_PREFIX);
|
||||
isVirtualMachine |= macAddress.StartsWith(VIRTUALBOX_MAC_PREFIX);
|
||||
isVirtualMachine |= macAddress.StartsWith("000000000000");
|
||||
}
|
||||
|
||||
foreach (var device in devices)
|
||||
{
|
||||
isVirtualMachine |= DeviceBlacklist.Any(d => device.ToLower().Contains(d.ToLower())) && DeviceWhitelist.All(d => !device.ToLower().Contains(d.ToLower()));
|
||||
}
|
||||
isVirtualMachine |= IsVirtualSystem(systemInfo.BiosInfo, systemInfo.Manufacturer, systemInfo.Model);
|
||||
|
||||
logger.Debug($"Computer '{systemInfo.Name}' appears {(isVirtualMachine ? "" : "not ")}to be a virtual machine.");
|
||||
|
||||
return isVirtualMachine;
|
||||
}
|
||||
|
||||
private bool IsVirtualSystemInfo(string biosInfo, string manufacturer, string model)
|
||||
private bool HasVirtualDevice()
|
||||
{
|
||||
var isVirtualMachine = false;
|
||||
var hasVirtualDevice = false;
|
||||
|
||||
foreach (var device in systemInfo.PlugAndPlayDeviceIds)
|
||||
{
|
||||
hasVirtualDevice |= DeviceBlacklist.Any(d => device.ToLower().Contains(d.ToLower())) && DeviceWhitelist.All(d => !device.ToLower().Contains(d.ToLower()));
|
||||
}
|
||||
|
||||
return hasVirtualDevice;
|
||||
}
|
||||
|
||||
private bool HasVirtualMacAddress()
|
||||
{
|
||||
var hasVirtualMacAddress = false;
|
||||
var macAddress = systemInfo.MacAddress;
|
||||
|
||||
if (macAddress != null && macAddress.Length > 2)
|
||||
{
|
||||
hasVirtualMacAddress |= macAddress.StartsWith(MANIPULATED);
|
||||
hasVirtualMacAddress |= macAddress.StartsWith(QEMU_MAC_PREFIX);
|
||||
hasVirtualMacAddress |= macAddress.StartsWith(VIRTUALBOX_MAC_PREFIX);
|
||||
}
|
||||
|
||||
return hasVirtualMacAddress;
|
||||
}
|
||||
|
||||
private bool IsVirtualCpu()
|
||||
{
|
||||
var isVirtualCpu = false;
|
||||
|
||||
isVirtualCpu |= systemInfo.CpuName.ToLower().Contains(" kvm ");
|
||||
|
||||
return isVirtualCpu;
|
||||
}
|
||||
|
||||
private bool IsVirtualRegistry()
|
||||
{
|
||||
var isVirtualRegistry = false;
|
||||
|
||||
isVirtualRegistry |= HasHistoricVirtualMachineHardwareConfiguration();
|
||||
isVirtualRegistry |= HasLocalVirtualMachineDeviceCache();
|
||||
|
||||
return isVirtualRegistry;
|
||||
}
|
||||
|
||||
private bool IsVirtualSystem(string biosInfo, string manufacturer, string model)
|
||||
{
|
||||
var isVirtualSystem = false;
|
||||
|
||||
biosInfo = biosInfo.ToLower();
|
||||
manufacturer = manufacturer.ToLower();
|
||||
model = model.ToLower();
|
||||
|
||||
isVirtualMachine |= biosInfo.Contains("hyper-v");
|
||||
isVirtualMachine |= biosInfo.Contains("virtualbox");
|
||||
isVirtualMachine |= biosInfo.Contains("vmware");
|
||||
isVirtualMachine |= biosInfo.Contains("ovmf");
|
||||
isVirtualMachine |= biosInfo.Contains("edk ii unknown");
|
||||
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");
|
||||
isVirtualMachine |= model.Contains("Q35 +");
|
||||
isVirtualSystem |= biosInfo.Contains("hyper-v");
|
||||
isVirtualSystem |= biosInfo.Contains("virtualbox");
|
||||
isVirtualSystem |= biosInfo.Contains("vmware");
|
||||
isVirtualSystem |= biosInfo.Contains("ovmf");
|
||||
isVirtualSystem |= biosInfo.Contains("edk ii unknown");
|
||||
isVirtualSystem |= manufacturer.Contains("microsoft corporation") && !model.Contains("surface");
|
||||
isVirtualSystem |= manufacturer.Contains("parallels software");
|
||||
isVirtualSystem |= manufacturer.Contains("qemu");
|
||||
isVirtualSystem |= manufacturer.Contains("vmware");
|
||||
isVirtualSystem |= model.Contains("virtualbox");
|
||||
isVirtualSystem |= model.Contains("Q35 +");
|
||||
|
||||
return isVirtualMachine;
|
||||
}
|
||||
|
||||
private bool IsVirtualRegistry()
|
||||
{
|
||||
var isVirtualMachine = false;
|
||||
|
||||
isVirtualMachine |= HasHistoricVirtualMachineHardwareConfiguration();
|
||||
isVirtualMachine |= HasLocalVirtualMachineDeviceCache();
|
||||
|
||||
return isVirtualMachine;
|
||||
return isVirtualSystem;
|
||||
}
|
||||
|
||||
private bool HasHistoricVirtualMachineHardwareConfiguration()
|
||||
{
|
||||
/**
|
||||
* scanned registry format:
|
||||
*
|
||||
* HKLM\SYSTEM\HardwareConfig\{configId=uuid}
|
||||
* - BIOSVendor
|
||||
* - SystemManufacturer
|
||||
* - ...
|
||||
* \ComputerIds
|
||||
* - {computerId=uuid}: {computerSummary=hardwareInfo}
|
||||
*
|
||||
*/
|
||||
const string HARDWARE_ROOT_KEY = "HKEY_LOCAL_MACHINE\\SYSTEM\\HardwareConfig";
|
||||
const string HARDWARE_ROOT_KEY = @"HKEY_LOCAL_MACHINE\SYSTEM\HardwareConfig";
|
||||
|
||||
var isVirtualMachine = false;
|
||||
var hasHistoricConfiguration = false;
|
||||
|
||||
if (!registry.TryGetSubKeys(HARDWARE_ROOT_KEY, out var hardwareConfigSubkeys))
|
||||
if (registry.TryGetSubKeys(HARDWARE_ROOT_KEY, out var hardwareConfigSubkeys))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var configId in hardwareConfigSubkeys)
|
||||
{
|
||||
var hardwareConfigKey = $"{HARDWARE_ROOT_KEY}\\{configId}";
|
||||
var didReadKeys = true;
|
||||
|
||||
didReadKeys &= registry.TryRead(hardwareConfigKey, "BIOSVendor", out var biosVendor);
|
||||
didReadKeys &= registry.TryRead(hardwareConfigKey, "BIOSVersion", out var biosVersion);
|
||||
didReadKeys &= registry.TryRead(hardwareConfigKey, "SystemManufacturer", out var systemManufacturer);
|
||||
didReadKeys &= registry.TryRead(hardwareConfigKey, "SystemProductName", out var systemProductName);
|
||||
|
||||
if (!didReadKeys)
|
||||
foreach (var configId in hardwareConfigSubkeys)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var hardwareConfigKey = $"{HARDWARE_ROOT_KEY}\\{configId}";
|
||||
var computerIdsKey = $"{hardwareConfigKey}\\ComputerIds";
|
||||
var success = true;
|
||||
|
||||
var biosInfo = $"{(string) biosVendor} {(string) biosVersion}";
|
||||
success &= registry.TryRead(hardwareConfigKey, "BIOSVendor", out var biosVendor);
|
||||
success &= registry.TryRead(hardwareConfigKey, "BIOSVersion", out var biosVersion);
|
||||
success &= registry.TryRead(hardwareConfigKey, "SystemManufacturer", out var systemManufacturer);
|
||||
success &= registry.TryRead(hardwareConfigKey, "SystemProductName", out var systemProductName);
|
||||
|
||||
isVirtualMachine |= IsVirtualSystemInfo(biosInfo, (string) systemManufacturer, (string) systemProductName);
|
||||
|
||||
var computerIdsKey = $"{hardwareConfigKey}\\ComputerIds";
|
||||
if (!registry.TryGetNames(computerIdsKey, out var computerIdNames))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var computerIdName in computerIdNames)
|
||||
{
|
||||
if (!registry.TryRead(computerIdsKey, computerIdName, out var computerSummary))
|
||||
if (success)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var biosInfo = $"{(string) biosVendor} {(string) biosVersion}";
|
||||
|
||||
isVirtualMachine |= IsVirtualSystemInfo((string) computerSummary, (string) systemManufacturer, (string) systemProductName);
|
||||
hasHistoricConfiguration |= IsVirtualSystem(biosInfo, (string) systemManufacturer, (string) systemProductName);
|
||||
|
||||
if (registry.TryGetNames(computerIdsKey, out var computerIdNames))
|
||||
{
|
||||
foreach (var computerIdName in computerIdNames)
|
||||
{
|
||||
if (registry.TryRead(computerIdsKey, computerIdName, out var computerSummary))
|
||||
{
|
||||
hasHistoricConfiguration |= IsVirtualSystem((string) computerSummary, (string) systemManufacturer, (string) systemProductName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return isVirtualMachine;
|
||||
return hasHistoricConfiguration;
|
||||
}
|
||||
|
||||
private bool HasLocalVirtualMachineDeviceCache()
|
||||
{
|
||||
const string DEVICE_CACHE_PARENT_KEY = "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\TaskFlow\\DeviceCache";
|
||||
const string DEVICE_CACHE_PARENT_KEY = @"HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\TaskFlow\DeviceCache";
|
||||
|
||||
var isVirtualMachine = false;
|
||||
var deviceName = System.Environment.GetEnvironmentVariable("COMPUTERNAME");
|
||||
var hasDeviceCache = false;
|
||||
var hasDeviceCacheKeys = registry.TryGetSubKeys(DEVICE_CACHE_PARENT_KEY, out var deviceCacheKeys);
|
||||
|
||||
if (deviceName != null && hasDeviceCacheKeys)
|
||||
if (deviceName != default && hasDeviceCacheKeys)
|
||||
{
|
||||
foreach (var cacheId in deviceCacheKeys)
|
||||
{
|
||||
var cacheIdKey = $"{DEVICE_CACHE_PARENT_KEY}\\{cacheId}";
|
||||
var cacheIdKey = $@"{DEVICE_CACHE_PARENT_KEY}\{cacheId}";
|
||||
var didReadKeys = true;
|
||||
|
||||
didReadKeys &= registry.TryRead(cacheIdKey, "DeviceName", out var cacheDeviceName);
|
||||
|
||||
if (!didReadKeys || deviceName.ToLower() != ((string) cacheDeviceName).ToLower())
|
||||
if (didReadKeys && deviceName.ToLower() == ((string) cacheDeviceName).ToLower())
|
||||
{
|
||||
continue;
|
||||
didReadKeys &= registry.TryRead(cacheIdKey, "DeviceMake", out var cacheDeviceManufacturer);
|
||||
didReadKeys &= registry.TryRead(cacheIdKey, "DeviceModel", out var cacheDeviceModel);
|
||||
|
||||
if (didReadKeys)
|
||||
{
|
||||
hasDeviceCache |= IsVirtualSystem("", (string) cacheDeviceManufacturer, (string) cacheDeviceModel);
|
||||
}
|
||||
}
|
||||
|
||||
didReadKeys &= registry.TryRead(cacheIdKey, "DeviceMake", out var cacheDeviceManufacturer);
|
||||
didReadKeys &= registry.TryRead(cacheIdKey, "DeviceModel", out var cacheDeviceModel);
|
||||
|
||||
if (!didReadKeys)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
isVirtualMachine |= IsVirtualSystemInfo("", (string) cacheDeviceManufacturer, (string) cacheDeviceModel);
|
||||
}
|
||||
}
|
||||
|
||||
return isVirtualMachine;
|
||||
}
|
||||
|
||||
private bool IsVirtualWmi()
|
||||
{
|
||||
var isVirtualMachine = false;
|
||||
var cpuObjSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_Processor");
|
||||
|
||||
foreach (var cpuObj in cpuObjSearcher.Get())
|
||||
{
|
||||
isVirtualMachine |= ((string) cpuObj["Name"]).ToLower().Contains(" kvm ");
|
||||
}
|
||||
|
||||
return isVirtualMachine;
|
||||
return hasDeviceCache;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue