Skip to content

Commit 71d175e

Browse files
committed
Two new techniques + refacto
1 parent 2423a70 commit 71d175e

File tree

2 files changed

+77
-24
lines changed

2 files changed

+77
-24
lines changed

vmdetect/common.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
package vmdetect
22

3-
import "fmt"
3+
import (
4+
"bufio"
5+
"fmt"
6+
"io"
7+
"os"
8+
"strings"
9+
)
410

511
func PrintError(loggee interface{}) {
612
fmt.Printf("[x] %v\n", loggee)
@@ -9,3 +15,26 @@ func PrintError(loggee interface{}) {
915
func PrintWarning(loggee interface{}) {
1016
fmt.Printf("[!] %v\n", loggee)
1117
}
18+
19+
func DoesFileContain(file *os.File, stringToBeFound string) bool {
20+
reader := bufio.NewReader(file)
21+
22+
for {
23+
line, err := reader.ReadString('\n')
24+
25+
if err != nil {
26+
27+
if err == io.EOF {
28+
PrintError(file.Name() + " didn't match")
29+
} else if !os.IsTimeout(err) {
30+
PrintError(err)
31+
}
32+
33+
return false
34+
}
35+
36+
if strings.Contains(line, stringToBeFound) {
37+
return true
38+
}
39+
}
40+
}

vmdetect/linux.go

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
package vmdetect
44

55
import (
6-
"bufio"
76
"bytes"
87
"github.com/klauspost/cpuid"
98
"io/ioutil"
@@ -12,7 +11,7 @@ import (
1211
)
1312

1413
/*
15-
Checks if the DMI table contains vendor strings of known VMs.
14+
Checks if the DMI table contains vendor strings of known VMs.
1615
*/
1716
func checkDMITable() bool {
1817

@@ -58,15 +57,14 @@ func checkDMITable() bool {
5857
return true
5958
}
6059
}
61-
6260
}
6361

6462
return false
6563
}
6664

6765
/*
68-
Checks printk messages to see if Linux detected an hypervisor.
69-
https://github.com/torvalds/linux/blob/31cc088a4f5d83481c6f5041bd6eb06115b974af/arch/x86/kernel/cpu/hypervisor.c#L79
66+
Checks printk messages to see if Linux detected an hypervisor.
67+
https://github.com/torvalds/linux/blob/31cc088a4f5d83481c6f5041bd6eb06115b974af/arch/x86/kernel/cpu/hypervisor.c#L79
7068
*/
7169
func checkKernelRingBuffer() bool {
7270

@@ -85,42 +83,68 @@ func checkKernelRingBuffer() bool {
8583
return false
8684
}
8785

88-
reader := bufio.NewReader(file)
86+
return DoesFileContain(file, "Hypervisor detected")
87+
}
8988

90-
for {
91-
line, _, err := reader.ReadLine()
89+
/*
90+
Checks if UML is being used
91+
https://en.wikipedia.org/wiki/User-mode_Linux
92+
*/
93+
func checkUML() bool {
9294

93-
if err != nil {
94-
if !os.IsTimeout(err) {
95-
PrintError(err)
96-
}
95+
file, err := os.Open("/proc/cpuinfo")
9796

98-
return false
99-
}
97+
if err != nil {
98+
PrintError(err)
99+
return false
100+
}
100101

101-
// Lowercase comparison to prevent false negatives
102-
if bytes.Contains(bytes.ToLower(line), []byte("hypervisor detected")) {
103-
return true
104-
}
102+
defer file.Close()
103+
104+
return DoesFileContain(file, "User Mode Linux")
105+
}
106+
107+
/*
108+
Some GNU/Linux distributions expose /proc/sysinfo containing potential VM info
109+
https://www.ibm.com/support/knowledgecenter/en/linuxonibm/com.ibm.linux.z.lhdd/lhdd_t_sysinfo.html
110+
*/
111+
func checkSysInfo() bool {
112+
file, err := os.Open("/proc/sysinfo")
113+
114+
if err != nil {
115+
PrintError(err)
116+
return false
105117
}
118+
119+
defer file.Close()
120+
121+
return DoesFileContain(file, "VM00")
106122
}
107123

108124
/*
109-
Public function returning true if a VM is detected.
110-
If so, a non-empty string is also returned to tell how it was detected.
125+
Public function returning true if a VM is detected.
126+
If so, a non-empty string is also returned to tell how it was detected.
111127
*/
112128
func IsRunningInVirtualMachine() (bool, string) {
113129

114130
if cpuid.CPU.VM() {
115-
return true, "CPU Vendor"
131+
return true, "CPU Vendor (assembly instructions)"
132+
}
133+
134+
if checkUML() {
135+
return true, "CPU Vendor (/proc/cpuinfo)"
136+
}
137+
138+
if checkSysInfo() {
139+
return true, "System Information (/proc/sysinfo)"
116140
}
117141

118142
if checkDMITable() {
119-
return true, "DMI Table"
143+
return true, "DMI Table (/sys/class/dmi/id/*)"
120144
}
121145

122146
if checkKernelRingBuffer() {
123-
return true, "Kernel Ring Buffer"
147+
return true, "Kernel Ring Buffer (/dev/kmsg)"
124148
}
125149

126150
return false, "nothing"

0 commit comments

Comments
 (0)