-
Notifications
You must be signed in to change notification settings - Fork 7
/
windowsregistry.go
153 lines (129 loc) · 3.52 KB
/
windowsregistry.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package main
import (
"fmt"
"strings"
"time"
"github.com/hillu/go-yara/v4"
"golang.org/x/sys/windows/registry"
)
// RegistryValue describe a regkey value in a structure
type RegistryValue struct {
key registry.Key
subKey string
valueName string
value string
}
// RegistryAnalysisRoutine analyse registry persistence keys every 15 seconds
func RegistryAnalysisRoutine(pQuarantine string, pKill bool, pNotifications bool, pVerbose bool, pInfiniteLoop bool, rules *yara.Rules) {
for {
values, errors := EnumRegistryPeristence()
if pVerbose {
for _, err := range errors {
logMessage(LOG_ERROR, "[ERROR]", err)
}
}
for _, k := range values {
paths := FormatPathFromComplexString(k.value)
for _, p := range paths {
FileAnalysis(p, pQuarantine, pKill, pNotifications, pVerbose, rules, "REGISTRY")
}
}
if !pInfiniteLoop {
wg.Done()
break
} else {
time.Sleep(15 * time.Second)
}
}
}
// EnumRegistryPeristence get all the potential registry values used for persistence
func EnumRegistryPeristence() (values []RegistryValue, errors []error) {
keys := []registry.Key{registry.USERS, registry.LOCAL_MACHINE}
subkeys := []string{`SOFTWARE\Microsoft\Windows\CurrentVersion\Run`, `SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce`}
for _, k := range keys {
for _, s := range subkeys {
v, err := EnumRegHivePersistence(k, s)
if err != nil {
errMsg := fmt.Errorf("%s\\%s - %s", GetRegistryHiveNameFromConst(k), s, err)
errors = append(errors, errMsg)
}
for _, value := range v {
values = append(values, value)
}
}
}
return values, errors
}
// GetRegistryHiveNameFromConst format registry.Key hive name as a string
func GetRegistryHiveNameFromConst(key registry.Key) string {
if key == registry.CLASSES_ROOT {
return "HKEY_CLASSES_ROOT"
} else if key == registry.CURRENT_CONFIG {
return "HKEY_CURRENT_CONFIG"
} else if key == registry.CURRENT_USER {
return "HKEY_CURRENT_USER"
} else if key == registry.USERS {
return "HKEY_USERS"
} else if key == registry.LOCAL_MACHINE {
return "HKEY_LOCAL_MACHINE"
} else {
return ""
}
}
// EnumRegHivePersistence parse the specified key and subkey and return all string key/value in a []RegistryValue
func EnumRegHivePersistence(key registry.Key, subkey string) (values []RegistryValue, err error) {
k, err := registry.OpenKey(key, "", registry.READ)
if err != nil {
return nil, err
}
defer k.Close()
subkeys, err := k.ReadSubKeyNames(0)
if err != nil {
return nil, err
}
if key == registry.USERS {
for _, s := range subkeys {
if len(s) > 10 && !strings.HasSuffix(s, "_Classes") {
v, err := enumRegSubKey(key, s+`\`+subkey)
if err != nil {
return nil, err
}
for _, item := range v {
values = append(values, item)
}
}
}
} else {
v, err := enumRegSubKey(key, subkey)
if err != nil {
return nil, err
}
for _, item := range v {
values = append(values, item)
}
}
return values, nil
}
// enumRegSubKey format subkey values in []RegistryValue
func enumRegSubKey(key registry.Key, subkey string) (values []RegistryValue, err error) {
var (
sk registry.Key
sv []string
)
sk, err = registry.OpenKey(key, subkey, registry.READ)
if err != nil {
return nil, err
}
sv, err = sk.ReadValueNames(0)
if err != nil {
return nil, err
}
for _, item := range sv {
v, _, _ := sk.GetStringValue(item)
if len(v) > 0 {
var result = RegistryValue{key: key, subKey: subkey, valueName: item, value: v}
values = append(values, result)
}
}
return values, nil
}