-
Notifications
You must be signed in to change notification settings - Fork 9
/
helpers.go
155 lines (131 loc) · 4.58 KB
/
helpers.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
154
155
// Copyright 2020 Jaume Martin
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package rules
import (
"io/ioutil"
"path/filepath"
"regexp"
"strings"
"github.com/hillu/go-yara/v4"
"github.com/mole-ids/mole/internal/nodes"
"github.com/mole-ids/mole/internal/types"
"github.com/mole-ids/mole/internal/utils"
"github.com/pkg/errors"
)
// GetRuleMetaInfo returns the rule metadata
func GetRuleMetaInfo(rule yara.Rule) (metarule types.MetaRule, err error) {
metarule = make(types.MetaRule)
for _, meta := range rule.Metas() {
if utils.InStrings(meta.Identifier, nodes.Keywords) {
// This will never generate an error becauses meta.Identifieris double
// checked in the previous conditional
metarule[meta.Identifier], _ = nodes.GetNodeValue(meta.Identifier, meta.Value)
}
}
for k, v := range metarule {
if v == nil {
return metarule, errors.Errorf(WrongMetadataFieldMsg, k)
}
}
for _, k := range nodes.Keywords {
if _, ok := metarule[k]; !ok {
return metarule, errors.Errorf(KeywordsNotMeetMsg, k)
}
}
return metarule, nil
}
// removeCStyleComments removes C-Style comments from a byte arry
func removeCStyleComments(content []byte) []byte {
// http://blog.ostermiller.org/find-comment
ccmt := regexp.MustCompile(`/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/`)
return ccmt.ReplaceAll(content, []byte(""))
}
// removeCppStyleComments removes C++-Style comments from a byte arry
func removeCppStyleComments(content []byte) []byte {
cppcmt := regexp.MustCompile(`//.*`)
return cppcmt.ReplaceAll(content, []byte(""))
}
// removeCAndCppCommentsFile removes either C-Style or C++Style comments from
// a file
func removeCAndCppCommentsFile(srcpath string) ([]byte, error) {
b, err := ioutil.ReadFile(srcpath)
if err != nil {
return b, errors.Wrap(err, WhileReadingFileMsg)
}
return removeCppStyleComments(removeCStyleComments(b)), nil
}
// removeCAndCppComments removes either C-Style or C++Style comments from
// a file
func removeCAndCppComments(src string) []byte {
return removeCppStyleComments(removeCStyleComments([]byte(src)))
}
// loadFiles loads files from path
func loadFiles(path string) ([]string, error) {
return filepath.Glob(filepath.Join(path, yaraFileGlob))
}
// cleanUpLine is a handy function for cleaning up include line from index file
func cleanUpLine(line string) string {
l := includeRe.ReplaceAllString(line, "")
return strings.ReplaceAll(l, "\"", "")
}
// parseRuleAndVars replace valiables by its final value
func parseRuleAndVars(rule string, vars map[string]string) (newRule string) {
// Pre-processing rule to replace some vars
rule = srcAnyPreprocRE.ReplaceAllString(rule, "src = \"$$any_addr\"")
rule = srcPortAnyPreprocRE.ReplaceAllString(rule, "sport = \"$$any_port\"")
rule = dstAnyPreprocRE.ReplaceAllString(rule, "dst = \"$$any_addr\"")
rule = dstPortAnyPreprocRE.ReplaceAllString(rule, "dport = \"$$any_port\"")
rule = protoCapPrepocRE.ReplaceAllStringFunc(rule, func(v string) string {
return protoCapPrepocInternalRE.ReplaceAllStringFunc(v, func(vv string) string {
return strings.ToLower(vv)
})
})
return varRe.ReplaceAllStringFunc(rule, func(v string) string {
var res string = v
if len(vars) > 0 {
if val, ok := vars[strings.ToLower(v)]; ok {
res = val
}
}
return res
})
}
// splitRules this utility splits Yara rules so it can be processed separately
func splitRules(rulesString string) []string {
// TODO: this need to be improved. At the moment this can be considered as
// a workarround. It should be a better way to split up the rules one by one
var rules, rulesTmp []string
var rulesTmpString string
rulesTmpString = string(removeCAndCppComments(rulesString))
rules = splitRE.Split(rulesTmpString, -1)
if len(rules) == 1 {
return rules
}
for idx, rule := range rules {
if idx == 0 {
// Add "}"
rule = rule + "}"
} else if idx == len(rules)-1 {
// Add "rule"
rule = "rule" + rule
} else {
rule = "rule" + rule + "}"
}
rulesTmp = append(rulesTmp, rule)
}
return rulesTmp
}
func getPathPrefix(b, p string) (string, error) {
if b == "" {
return filepath.Abs(p)
}
return filepath.Abs(filepath.Join(b, p))
}