3
3
package vmdetect
4
4
5
5
import (
6
+ "errors"
6
7
"fmt"
7
8
"golang.org/x/sys/windows/registry"
8
9
"os"
9
10
"path"
11
+ "path/filepath"
10
12
"strings"
11
13
)
12
14
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 :]
15
+ func extractKeyTypeFrom (registryKey string ) (registry.Key , string , error ) {
16
+ firstSeparatorIndex := strings .Index (registryKey , string (os .PathSeparator ))
17
+ keyTypeStr := registryKey [:firstSeparatorIndex ]
18
+ keyPath := registryKey [firstSeparatorIndex + 1 :]
26
19
27
20
var keyType registry.Key
28
21
switch keyTypeStr {
@@ -42,14 +35,62 @@ func doesRegistryKeyExist(key string) bool {
42
35
keyType = registry .CURRENT_CONFIG
43
36
break
44
37
default :
45
- PrintError (fmt .Sprintf ("Invalid keytype (%v)" , keyTypeStr ))
38
+ return keyType , "" , errors .New (fmt .Sprintf ("Invalid keytype (%v)" , keyTypeStr ))
39
+ }
40
+
41
+ return keyType , keyPath , nil
42
+ }
43
+
44
+ func doesRegistryKeyContain (registryKey string , expectedSubString string ) bool {
45
+
46
+ keyType , keyPath , err := extractKeyTypeFrom (registryKey )
47
+
48
+ if err != nil {
49
+ PrintError (err )
50
+ return false
51
+ }
52
+
53
+ keyPath , keyName := filepath .Split (keyPath )
54
+
55
+ keyHandle , err := registry .OpenKey (keyType , keyPath , registry .QUERY_VALUE )
56
+
57
+ if err != nil {
58
+ PrintError (fmt .Sprintf ("Cannot open %v : %v" , registryKey , err ))
59
+ return false
60
+ }
61
+
62
+ defer keyHandle .Close ()
63
+
64
+ valueFound , _ , err := keyHandle .GetStringValue (keyName )
65
+
66
+ if err != nil {
67
+ PrintError (err )
68
+ }
69
+
70
+ return strings .Contains (valueFound , expectedSubString )
71
+ }
72
+
73
+ func doesRegistryKeyExist (registryKey string ) bool {
74
+
75
+ subkeyPrefix := ""
76
+
77
+ // Handle trailing wildcard
78
+ if registryKey [len (registryKey )- 1 :] == "*" {
79
+ registryKey , subkeyPrefix = path .Split (registryKey )
80
+ subkeyPrefix = subkeyPrefix [:len (subkeyPrefix )- 1 ] // remove *
81
+ }
82
+
83
+ keyType , keyPath , err := extractKeyTypeFrom (registryKey )
84
+
85
+ if err != nil {
86
+ PrintError (err )
46
87
return false
47
88
}
48
89
49
90
keyHandle , err := registry .OpenKey (keyType , keyPath , registry .QUERY_VALUE )
50
91
51
92
if err != nil {
52
- PrintError (fmt .Sprintf ("Cannot open %v : %v" , key , err ))
93
+ PrintError (fmt .Sprintf ("Cannot open %v : %v" , registryKey , err ))
53
94
return false
54
95
}
55
96
@@ -73,7 +114,7 @@ func doesRegistryKeyExist(key string) bool {
73
114
74
115
return false
75
116
} else {
76
- // The key we were looking for has been found
117
+ // The registryKey we were looking for has been found
77
118
return true
78
119
}
79
120
}
@@ -143,6 +184,35 @@ func checkRegistry() (bool, string) {
143
184
`HKLM\SYSTEM\ControlSet001\Services\xenvdb` ,
144
185
}
145
186
187
+ // TODO : fill with https://evasions.checkpoint.com/techniques/registry.html#check-if-keys-contain-strings
188
+ blacklistedValuesPerKeyPerVendor := map [string ]map [string ]string {
189
+ "Anubis" : {
190
+ `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\ProductID` : "76487-337-8429955-22614" ,
191
+ `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductID` : "76487-337-8429955-22614" ,
192
+ },
193
+ "QEMU" : {
194
+ `HKLM\HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0\Identifier` : "QEMU" ,
195
+ `HKLM\HARDWARE\Description\System\SystemBiosVersion` : "QEMU" ,
196
+ `HKLM\HARDWARE\Description\System\VideoBiosVersion` : "QEMU" ,
197
+ `HKLM\HARDWARE\Description\System\BIOS\SystemManufacturer` : "QEMU" ,
198
+ },
199
+ "VirtualBox" : {
200
+ `HKLM\HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0\Identifier` : "VBOX" ,
201
+ `HKLM\HARDWARE\DEVICEMAP\Scsi\Scsi Port 1\Scsi Bus 0\Target Id 0\Logical Unit Id 0\Identifier` : "VBOX" ,
202
+ `HKLM\HARDWARE\DEVICEMAP\Scsi\Scsi Port 2\Scsi Bus 0\Target Id 0\Logical Unit Id 0\Identifier` : "VBOX" ,
203
+ `HKLM\HARDWARE\Description\System\SystemBiosVersion` : "VBOX" ,
204
+ `HKLM\HARDWARE\Description\System\VideoBiosVersion` : "VIRTUALBOX" ,
205
+ `HKLM\HARDWARE\Description\System\BIOS\SystemProductName` : "VIRTUAL" ,
206
+ `HKLM\SYSTEM\ControlSet001\Services\Disk\Enum\DeviceDesc` : "VBOX" ,
207
+ `HKLM\SYSTEM\ControlSet001\Services\Disk\Enum\FriendlyName` : "VBOX" ,
208
+ `HKLM\SYSTEM\ControlSet002\Services\Disk\Enum\DeviceDesc` : "VBOX" ,
209
+ `HKLM\SYSTEM\ControlSet002\Services\Disk\Enum\FriendlyName` : "VBOX" ,
210
+ `HKLM\SYSTEM\ControlSet003\Services\Disk\Enum\DeviceDesc` : "VBOX" ,
211
+ `HKLM\SYSTEM\ControlSet003\Services\Disk\Enum\FriendlyName` : "VBOX" ,
212
+ `HKLM\SYSTEM\CurrentControlSet\Control\SystemInformation\SystemProductName` : "VIRTUAL" ,
213
+ },
214
+ }
215
+
146
216
allKeys := [][]string {hyperVKeys , parallelsKeys , virtualBoxKeys , virtualPCKeys , vmwareKeys , xenKeys }
147
217
148
218
for _ , keys := range allKeys {
@@ -153,18 +223,25 @@ func checkRegistry() (bool, string) {
153
223
}
154
224
}
155
225
226
+ for /*vendor*/ _ , registryValuesPerPath := range blacklistedValuesPerKeyPerVendor {
227
+ for registryPath , expectedValue := range registryValuesPerPath {
228
+ if doesRegistryKeyContain (registryPath , expectedValue ) {
229
+ return true , registryPath + " contains " + expectedValue
230
+ }
231
+ }
232
+ }
233
+
156
234
return false , "none"
157
235
}
158
236
159
- func checkFileSystem () bool {
237
+ func checkFileSystem () ( bool , string ) {
160
238
// check for known path on the filesystem, either files or directories
161
239
generalPath := []string {
162
240
`c:\take_screenshot.ps1` ,
163
241
`c:\loaddll.exe` ,
164
242
`c:\symbols\aagmmc.pdb` ,
165
243
}
166
244
167
-
168
245
prlPath := []string {
169
246
`c:\windows\system32\drivers\prleth.sys` ,
170
247
`c:\windows\system32\drivers\prlfs.sys` ,
@@ -201,26 +278,25 @@ func checkFileSystem() bool {
201
278
`c:\windows\system32\drivers\vmxnet.sys` ,
202
279
`c:\windows\system32\drivers\vmhgfs.sys` ,
203
280
`c:\windows\system32\drivers\vmx86.sys` ,
204
- `c:\windows\system32\drivers\hgfs.sys`
281
+ `c:\windows\system32\drivers\hgfs.sys` ,
205
282
}
206
283
207
284
virtualpcPath := []string {
208
285
`c:\windows\system32\drivers\vmsrvc.sys` ,
209
- `c:\windows\system32\drivers\vpc-s3.sys`
286
+ `c:\windows\system32\drivers\vpc-s3.sys` ,
210
287
}
211
288
212
289
allPath := [][]string {virtualpcPath , prlPath , vmwarePath , vboxPath , generalPath }
213
290
214
291
for _ , paths := range allPath {
215
- for _ , path := range paths {
216
- if DoesFileExist (path ) {
217
- return true , path
292
+ for _ , p := range paths {
293
+ if DoesFileExist (p ) {
294
+ return true , p
218
295
}
219
296
}
220
297
}
221
298
222
299
return false , "none"
223
-
224
300
}
225
301
226
302
/*
@@ -236,8 +312,8 @@ func IsRunningInVirtualMachine() (bool, string) {
236
312
return vmDetected , fmt .Sprintf ("Registry key (%v)" , registryKey )
237
313
}
238
314
239
- if vmDetected , path := checkFileSystem (); vmDetected {
240
- return vmDetected , fmt .Sprintf ("Path (%v)" , path )
315
+ if vmDetected , filePath := checkFileSystem (); vmDetected {
316
+ return vmDetected , fmt .Sprintf ("Known path found (%v)" , filePath )
241
317
}
242
318
243
319
return false , "nothing"
0 commit comments