forked from dreadl0ck/netcap
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlayer.go
146 lines (123 loc) · 3.87 KB
/
layer.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
/*
* NETCAP - Traffic Analysis Framework
* Copyright (c) 2017 Philipp Mieden <dreadl0ck [at] protonmail [dot] ch>
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package label
import (
"io"
"log"
"os"
"path/filepath"
"strings"
"sync"
"github.com/dreadl0ck/netcap"
"github.com/dreadl0ck/netcap/types"
"github.com/dreadl0ck/netcap/utils"
pb "gopkg.in/cheggaaa/pb.v1"
)
// CollectLabels indicates whether labels should be collected
var CollectLabels bool
// Layer labels packets of a given gopacket.LayerType string.
func Layer(wg *sync.WaitGroup, file string, typ string, labelMap map[string]*SuricataAlert, labels []*SuricataAlert, outDir, separator, selection string) *pb.ProgressBar {
var (
fname = filepath.Join(outDir, file)
total = netcap.Count(fname)
labelsTotal = 0
outFileName = filepath.Join(outDir, typ+"_labeled.csv")
progress = pb.New(int(total)).Prefix(utils.Pad(utils.TrimFileExtension(file), 25))
)
go func() {
// open layer data file
r, err := netcap.Open(fname, netcap.DefaultBufferSize)
if err != nil {
panic(err)
}
// read netcap header
header := r.ReadHeader()
// create outfile handle
f, err := os.Create(outFileName)
if err != nil {
panic(err)
}
var (
record = netcap.InitRecord(header.Type)
ok bool
p types.AuditRecord
)
// check if we can decode it as CSV
if p, ok = record.(types.AuditRecord); !ok {
panic("type does not implement types.AuditRecord interface:" + typ)
}
// run selection
types.Select(record, selection)
// write header
_, err = f.WriteString(strings.Join(p.CSVHeader(), separator) + separator + "result" + "\n")
if err != nil {
panic(err)
}
for {
err := r.Next(record)
if err == io.EOF || err == io.ErrUnexpectedEOF {
break
} else if err != nil {
panic(err)
}
if UseProgressBars {
progress.Increment()
}
// collect labels for layer
// e.g: there are two alerts for the same timestamp with different classifications
// they label will then contain both separated by a pipe symbol
if CollectLabels {
var label string
// check if flow has a source or destination adress matching an alert
// if not label it as normal
for _, a := range labels {
// if the layer audit record has a timestamp of an alert
if a.Timestamp == p.Time() {
// only if it is not already part of the label
if !strings.Contains(label, a.Classification) {
if label == "" {
label = a.Classification
} else {
label += " | " + a.Classification
}
}
}
}
if len(label) != 0 {
if strings.HasPrefix(label, " |") {
log.Fatal("invalid label: ", label)
}
// add label
f.WriteString(strings.Join(p.CSVRecord(), separator) + separator + label + "\n")
labelsTotal++
} else {
// label as normal
f.WriteString(strings.Join(p.CSVRecord(), separator) + separator + "normal\n")
}
} else {
// layers are mapped by timestamp
// this preserves only the first label seen for each timestamp
if a, ok := labelMap[p.Time()]; ok {
// add label
f.WriteString(strings.Join(p.CSVRecord(), separator) + separator + a.Classification + "\n")
labelsTotal++
} else {
// label as normal
f.WriteString(strings.Join(p.CSVRecord(), separator) + separator + "normal\n")
}
}
}
finish(wg, r, f, labelsTotal, outFileName, progress)
}()
return progress
}