|
2 | 2 |
|
3 | 3 | package vmdetect
|
4 | 4 |
|
| 5 | +import ( |
| 6 | + "fmt" |
| 7 | + "golang.org/x/sys/windows/registry" |
| 8 | + "os" |
| 9 | + "path" |
| 10 | + "strings" |
| 11 | +) |
| 12 | + |
| 13 | +func doesRegistryKeyExist(key string) bool { |
| 14 | + |
| 15 | + subkeyPrefix := "" |
| 16 | + |
| 17 | + // Handle trailing wildcard |
| 18 | + if key[len(key)-1:] == "*" { |
| 19 | + key, subkeyPrefix = path.Split(key) |
| 20 | + subkeyPrefix = subkeyPrefix[:len(subkeyPrefix)-1] // remove * |
| 21 | + } |
| 22 | + |
| 23 | + firstSeparatorIndex := strings.Index(key, string(os.PathSeparator)) |
| 24 | + keyTypeStr := key[:firstSeparatorIndex] |
| 25 | + keyPath := key[firstSeparatorIndex+1:] |
| 26 | + |
| 27 | + var keyType registry.Key |
| 28 | + switch keyTypeStr { |
| 29 | + case "HKLM": |
| 30 | + keyType = registry.LOCAL_MACHINE |
| 31 | + break |
| 32 | + case "HKCR": |
| 33 | + keyType = registry.CLASSES_ROOT |
| 34 | + break |
| 35 | + case "HKCU": |
| 36 | + keyType = registry.CURRENT_USER |
| 37 | + break |
| 38 | + case "HKU": |
| 39 | + keyType = registry.USERS |
| 40 | + break |
| 41 | + case "HKCC": |
| 42 | + keyType = registry.CURRENT_CONFIG |
| 43 | + break |
| 44 | + default: |
| 45 | + PrintError(fmt.Sprintf("Invalid keytype (%v)", keyTypeStr)) |
| 46 | + return false |
| 47 | + } |
| 48 | + |
| 49 | + keyHandle, err := registry.OpenKey(keyType, keyPath, registry.QUERY_VALUE) |
| 50 | + |
| 51 | + if err != nil { |
| 52 | + PrintError(fmt.Sprintf("Cannot open %v : %v", key, err)) |
| 53 | + return false |
| 54 | + } |
| 55 | + |
| 56 | + defer keyHandle.Close() |
| 57 | + |
| 58 | + // If a wildcard has been specified... |
| 59 | + if subkeyPrefix != "" { |
| 60 | + // ... we look for sub-keys to see if one exists |
| 61 | + subKeys, err := keyHandle.ReadSubKeyNames(0xFFFF) |
| 62 | + |
| 63 | + if err != nil { |
| 64 | + PrintError(err) |
| 65 | + return false |
| 66 | + } |
| 67 | + |
| 68 | + for _, subKeyName := range subKeys { |
| 69 | + if strings.HasPrefix(subKeyName, subkeyPrefix) { |
| 70 | + return true |
| 71 | + } |
| 72 | + } |
| 73 | + |
| 74 | + return false |
| 75 | + } else { |
| 76 | + // The key we were looking for has been found |
| 77 | + return true |
| 78 | + } |
| 79 | +} |
| 80 | + |
| 81 | +func checkRegistry() (bool, string) { |
| 82 | + |
| 83 | + hyperVKeys := []string{ |
| 84 | + `HKLM\SOFTWARE\Microsoft\Hyper-V`, |
| 85 | + `HKLM\SOFTWARE\Microsoft\VirtualMachine`, |
| 86 | + `HKLM\SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters`, |
| 87 | + `HKLM\SYSTEM\ControlSet001\Services\vmicheartbeat`, |
| 88 | + `HKLM\SYSTEM\ControlSet001\Services\vmicvss`, |
| 89 | + `HKLM\SYSTEM\ControlSet001\Services\vmicshutdown`, |
| 90 | + `HKLM\SYSTEM\ControlSet001\Services\vmicexchange`, |
| 91 | + } |
| 92 | + |
| 93 | + parallelsKeys := []string{ |
| 94 | + `HKLM\SYSTEM\CurrentControlSet\Enum\PCI\VEN_1AB8*`, |
| 95 | + } |
| 96 | + |
| 97 | + virtualBoxKeys := []string{ |
| 98 | + `HKLM\SYSTEM\CurrentControlSet\Enum\PCI\VEN_80EE*`, |
| 99 | + `HKLM\HARDWARE\ACPI\DSDT\VBOX__`, |
| 100 | + `HKLM\HARDWARE\ACPI\FADT\VBOX__`, |
| 101 | + `HKLM\HARDWARE\ACPI\RSDT\VBOX__`, |
| 102 | + `HKLM\SOFTWARE\Oracle\VirtualBox Guest Additions`, |
| 103 | + `HKLM\SYSTEM\ControlSet001\Services\VBoxGuest`, |
| 104 | + `HKLM\SYSTEM\ControlSet001\Services\VBoxMouse`, |
| 105 | + `HKLM\SYSTEM\ControlSet001\Services\VBoxService`, |
| 106 | + `HKLM\SYSTEM\ControlSet001\Services\VBoxSF`, |
| 107 | + `HKLM\SYSTEM\ControlSet001\Services\VBoxVideo`, |
| 108 | + } |
| 109 | + |
| 110 | + virtualPCKeys := []string{ |
| 111 | + `HKLM\SYSTEM\CurrentControlSet\Enum\PCI\VEN_5333*`, |
| 112 | + `HKLM\SYSTEM\ControlSet001\Services\vpcbus`, |
| 113 | + `HKLM\SYSTEM\ControlSet001\Services\vpc-s3`, |
| 114 | + `HKLM\SYSTEM\ControlSet001\Services\vpcuhub`, |
| 115 | + `HKLM\SYSTEM\ControlSet001\Services\msvmmouf`, |
| 116 | + } |
| 117 | + |
| 118 | + vmwareKeys := []string{ |
| 119 | + `HKLM\SYSTEM\CurrentControlSet\Enum\PCI\VEN_15AD*`, |
| 120 | + `HKCU\SOFTWARE\VMware, Inc.\VMware Tools`, |
| 121 | + `HKLM\SOFTWARE\VMware, Inc.\VMware Tools`, |
| 122 | + `HKLM\SYSTEM\ControlSet001\Services\vmdebug`, |
| 123 | + `HKLM\SYSTEM\ControlSet001\Services\vmmouse`, |
| 124 | + `HKLM\SYSTEM\ControlSet001\Services\VMTools`, |
| 125 | + `HKLM\SYSTEM\ControlSet001\Services\VMMEMCTL`, |
| 126 | + `HKLM\SYSTEM\ControlSet001\Services\vmware`, |
| 127 | + `HKLM\SYSTEM\ControlSet001\Services\vmci`, |
| 128 | + `HKLM\SYSTEM\ControlSet001\Services\vmx86`, |
| 129 | + `HKLM\SYSTEM\CurrentControlSet\Enum\IDE\CdRomNECVMWar_VMware_IDE_CD*`, |
| 130 | + `HKLM\SYSTEM\CurrentControlSet\Enum\IDE\CdRomNECVMWar_VMware_SATA_CD*`, |
| 131 | + `HKLM\SYSTEM\CurrentControlSet\Enum\IDE\DiskVMware_Virtual_IDE_Hard_Drive*`, |
| 132 | + `HKLM\SYSTEM\CurrentControlSet\Enum\IDE\DiskVMware_Virtual_SATA_Hard_Drive*`, |
| 133 | + } |
| 134 | + |
| 135 | + xenKeys := []string{ |
| 136 | + `HKLM\HARDWARE\ACPI\DSDT\xen`, |
| 137 | + `HKLM\HARDWARE\ACPI\FADT\xen`, |
| 138 | + `HKLM\HARDWARE\ACPI\RSDT\xen`, |
| 139 | + `HKLM\SYSTEM\ControlSet001\Services\xenevtchn`, |
| 140 | + `HKLM\SYSTEM\ControlSet001\Services\xennet`, |
| 141 | + `HKLM\SYSTEM\ControlSet001\Services\xennet6`, |
| 142 | + `HKLM\SYSTEM\ControlSet001\Services\xensvc`, |
| 143 | + `HKLM\SYSTEM\ControlSet001\Services\xenvdb`, |
| 144 | + } |
| 145 | + |
| 146 | + allKeys := [][]string{hyperVKeys, parallelsKeys, virtualBoxKeys, virtualPCKeys, vmwareKeys, xenKeys} |
| 147 | + |
| 148 | + for _, keys := range allKeys { |
| 149 | + for _, key := range keys { |
| 150 | + if doesRegistryKeyExist(key) { |
| 151 | + return true, key |
| 152 | + } |
| 153 | + } |
| 154 | + } |
| 155 | + |
| 156 | + return false, "none" |
| 157 | +} |
| 158 | + |
5 | 159 | /*
|
6 | 160 | Public function returning true if a VM is detected.
|
7 | 161 | If so, a non-empty string is also returned to tell how it was detected.
|
8 | 162 | */
|
9 | 163 | func IsRunningInVirtualMachine() (bool, string) {
|
| 164 | + /*if vmDetected, how := CommonChecks(); vmDetected { |
| 165 | + return vmDetected, how |
| 166 | + }*/ |
| 167 | + |
| 168 | + if vmDetected, registryKey := checkRegistry(); vmDetected { |
| 169 | + return vmDetected, fmt.Sprintf("Registry key (%v)", registryKey) |
| 170 | + } |
| 171 | + |
10 | 172 | return false, "nothing"
|
11 | 173 | }
|
0 commit comments