forked from jheise/yarascanner
-
Notifications
You must be signed in to change notification settings - Fork 0
/
scanner.go
130 lines (104 loc) · 2.37 KB
/
scanner.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
package main
import (
// standard
"os"
"strings"
// external
"github.com/hillu/go-yara"
"github.com/jheise/yaramsg"
)
// struct to hold multiple matches
type Response struct {
Filename string
Matches []*yaramsg.Match
}
// struct to make requests to the scanner
const (
ScanRequest = iota
NameSpaceList = iota
RuleList = iota
)
type Request struct {
RequestType int
RequestQuery string
}
// struct to hold compiler and channels
type Scanner struct {
compiler *yara.Compiler
requests chan *Request
responses chan *Response
}
// load rule and process directory
func loadIndex(compiler *yara.Compiler, indexpath string) error {
filehandle, err := os.Open(indexpath)
if err != nil {
return err
}
defer filehandle.Close()
// generate namespace
fields := strings.Split(indexpath, "/")
filename := fields[len(fields)-1]
namespace := strings.Split(filename, "_")[0]
err = compiler.AddFile(filehandle, namespace)
if err != nil {
elog.Println(err)
return err
}
return nil
}
func scan(compiler *yara.Compiler, filename string) (*Response, error) {
response := new(Response)
response.Filename = filename
var err error
var matches []*yaramsg.Match
rules, err := compiler.GetRules()
if err != nil {
return response, err
}
filepath := uploads_dir + "/" + filename
output, err := rules.ScanFile(filepath, 0, 300)
if err != nil {
return response, err
}
for _, resp := range output {
match := new(yaramsg.Match)
match.Rule = resp.Rule
match.Namespace = resp.Namespace
match.Tags = resp.Tags
matches = append(matches, match)
}
response.Matches = matches
return response, err
}
func NewScanner(req chan *Request, resp chan *Response) (*Scanner, error) {
scanner := new(Scanner)
scanner.requests = req
scanner.responses = resp
compiler, err := yara.NewCompiler()
if err != nil {
return nil, err
}
scanner.compiler = compiler
return scanner, nil
}
func (scanner *Scanner) LoadIndex(indexPath string) error {
err := loadIndex(scanner.compiler, indexPath)
if err != nil {
elog.Println(err)
return err
}
return nil
}
func (scanner *Scanner) Run() {
info.Println("Waiting for scan requests")
for request := range scanner.requests {
switch request.RequestType {
case ScanRequest:
response, err := scan(scanner.compiler, request.RequestQuery)
if err != nil {
elog.Println(err)
}
scanner.responses <- response
}
}
}