Skip to content

Commit 3fb6fe1

Browse files
author
hippwn
committed
Merge branch 'master' of github.com:ShellCode33/VM-Detection
2 parents b9098d4 + bc01855 commit 3fb6fe1

File tree

4 files changed

+234
-5
lines changed

4 files changed

+234
-5
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Then see [main.go](https://github.com/ShellCode33/VM-Detection/blob/master/main.
1818
To build the paper, be sure to have Docker installed and run the following command inside the paper directory:
1919

2020
```bash
21-
$ docker run
21+
$ docker run --rm -it -v "$(pwd):/pandoc" dalibo/pandocker --pdf-engine=xelatex --template=eisvogel --listings --highlight-style espresso *.md -o paper.pdf
2222
```
2323

2424
## GNU/Linux techniques

vmdetect/common.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@ package vmdetect
33
import (
44
"bufio"
55
"fmt"
6+
"github.com/klauspost/cpuid"
7+
"github.com/shirou/gopsutil/mem"
68
"io"
9+
"net"
710
"os"
11+
"runtime"
812
"strings"
913
)
1014

@@ -48,3 +52,68 @@ func DoesFileContain(file *os.File, stringsToBeFound ...string) bool {
4852
}
4953
}
5054
}
55+
56+
/*
57+
Tries to detect a VM using its network configuration.
58+
*/
59+
func checkNetworking() (bool, string) {
60+
61+
blacklistedMacAddressPrefixes := []string{
62+
"00:1C:42", // Parallels
63+
"08:00:27", // VirtualBox
64+
"00:05:69", // |
65+
"00:0C:29", // | > VMWare
66+
"00:1C:14", // |
67+
"00:50:56", // |
68+
"00:16:E3", // Xen
69+
}
70+
71+
interfaces, err := net.Interfaces()
72+
73+
if err != nil {
74+
return false, err.Error()
75+
}
76+
77+
for _, iface := range interfaces {
78+
79+
macAddr := iface.HardwareAddr.String()
80+
if macAddr != "" {
81+
for _, prefix := range blacklistedMacAddressPrefixes {
82+
if strings.HasPrefix(macAddr, prefix) {
83+
return true, fmt.Sprintf("Known MAC address prefix (%v)", prefix)
84+
}
85+
}
86+
}
87+
88+
if iface.Name == "Vmware" {
89+
return true, "Vmware found as network interface name"
90+
}
91+
}
92+
93+
return false, ""
94+
}
95+
96+
/*
97+
Tries to detect VMs using cross-platform techniques.
98+
*/
99+
func CommonChecks() (bool, string) {
100+
101+
// https://lwn.net/Articles/301888/
102+
if cpuid.CPU.VM() {
103+
return true, "CPU Vendor (cpuid space)"
104+
}
105+
106+
if vmDetected, how := checkNetworking(); vmDetected {
107+
return true, how
108+
}
109+
110+
vmStat, err := mem.VirtualMemory()
111+
112+
if err != nil {
113+
PrintError(err)
114+
} else if runtime.NumCPU() < 3 && vmStat.Total < 3072000000 {
115+
return true, fmt.Sprintf("Low resources detected (%v CPU and %v bytes of RAM", runtime.NumCPU(), vmStat.Total)
116+
}
117+
118+
return false, "nothing"
119+
}

vmdetect/linux.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ package vmdetect
44

55
import (
66
"bytes"
7-
"github.com/klauspost/cpuid"
87
"io/ioutil"
98
"os"
109
"os/user"
@@ -175,9 +174,8 @@ func IsRunningInVirtualMachine() (bool, string) {
175174
PrintWarning("Unprivileged user detected, some techniques might not work")
176175
}
177176

178-
// https://lwn.net/Articles/301888/
179-
if cpuid.CPU.VM() {
180-
return true, "CPU Vendor (cpuid space)"
177+
if vmDetected, how := CommonChecks(); vmDetected {
178+
return vmDetected, how
181179
}
182180

183181
if checkKernelModules() {

vmdetect/windows.go

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,172 @@
22

33
package vmdetect
44

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+
5159
/*
6160
Public function returning true if a VM is detected.
7161
If so, a non-empty string is also returned to tell how it was detected.
8162
*/
9163
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+
10172
return false, "nothing"
11173
}

0 commit comments

Comments
 (0)