-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathmessages.go
133 lines (108 loc) · 3.17 KB
/
messages.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
package evtx
import (
"fmt"
"regexp"
"strconv"
"github.com/Velocidex/ordereddict"
)
var (
expansion_re = regexp.MustCompile(`\%[0-9ntr]+`)
parameter_re = regexp.MustCompile(`^\%\%([0-9]+)`)
system_root_re = regexp.MustCompile("(?i)%?SystemRoot%?")
windir_re = regexp.MustCompile("(?i)%windir%")
programfiles_re = regexp.MustCompile("(?i)%programfiles%")
system32_re = regexp.MustCompile(`(?i)\\System32\\`)
)
type MessageResolver interface {
GetMessage(provider, channel string, event_id int, number_of_expansions int) string
GetParameter(provider, channel string, parameter_id int) string
Close()
}
type NullResolver struct{}
func (self NullResolver) GetMessage(provider, channel string, event_id, number_of_expansions int) string {
return ""
}
func (self NullResolver) GetParameter(provider, channel string, parameter_id int) string {
return ""
}
func (self NullResolver) Close() {}
func flatten(dict *ordereddict.Dict) []interface{} {
result := []interface{}{}
if dict == nil {
return result
}
for _, k := range dict.Keys() {
value, _ := dict.Get(k)
switch t := value.(type) {
case *ordereddict.Dict:
result = append(result, flatten(t)...)
case []string:
for _, item := range t {
result = append(result, item)
}
default:
result = append(result, value)
}
}
return result
}
func maybeExpandObjects(provider, channel string,
item interface{}, resolver MessageResolver) string {
item_str, ok := item.(string)
if !ok {
return fmt.Sprintf("%v", item)
}
matches := parameter_re.FindStringSubmatch(item_str)
if len(matches) < 2 {
return fmt.Sprintf("%v", item)
}
param_id, err := strconv.Atoi(matches[1])
if err != nil {
return fmt.Sprintf("%v", item)
}
return resolver.GetParameter(provider, channel, param_id)
}
func ExpandMessage(
event *ordereddict.Dict, resolver MessageResolver) string {
// Now get and flatten the user data or event data
data, pres := ordereddict.GetMap(event, "UserData")
if !pres {
data, _ = ordereddict.GetMap(event, "EventData")
}
expansions := flatten(data)
provider, _ := ordereddict.GetString(event, "System.Provider.Name")
provider_guid, _ := ordereddict.GetString(event, "System.Provider.Guid")
channel, _ := ordereddict.GetString(event, "System.Channel")
event_id, _ := ordereddict.GetInt(event, "System.EventID.Value")
// Get the raw message. First try using the GUID then using the
// name if possible.
message := resolver.GetMessage(provider_guid, channel, event_id, len(expansions))
if message == "" {
message = resolver.GetMessage(provider, channel, event_id, len(expansions))
if message == "" {
// No raw message string, just return.
return message
}
} else {
provider = provider_guid
}
// Replace expansions in the message with the user data.
return expansion_re.ReplaceAllStringFunc(message, func(match string) string {
switch match {
case "%n":
return "\n"
case "%r":
return ""
case "%t":
return "\t"
}
number, _ := strconv.Atoi(match[1:])
// Regex expansions start at 1
number -= 1
if number >= 0 && number < len(expansions) {
return maybeExpandObjects(
provider, channel, expansions[number], resolver)
}
return match
})
}