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
|
package main
import (
"regexp"
"strconv"
"strings"
"github.com/elastic/go-libaudit/v2"
"github.com/elastic/go-libaudit/v2/auparse"
)
func orgnaze() {
defer wg.Done()
defer close(cookedChan)
// 接收信息
var raw interface{}
var ok bool
var rawEvent libaudit.RawAuditMessage
// 事件信息
var eventId, argc int
var err [6]error
var event, cooked Event
// 为每个事务id存储其信息,事务id在操作系统运行期间是唯一的
eventTable := make(map[int]*Event)
// 要用的正则匹配列表
syscallRegex := regexp.MustCompile(`audit\((\d+\.\d+):(\d+)\).*?syscall=(\d+).*?ppid=(\d+) pid=(\d+).*?$`)
execveRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): argc=(\d+)`)
argsRegex := regexp.MustCompile(`a\d+=("(.*?)"|([0-9a-fA-F]+))`)
cwdRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): cwd="(.*?)"`)
proctitleRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): proctitle=("(.*?)"|([0-9a-fA-F]+))$`)
eoeRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\)`)
for {
raw, ok = <-rawChan
if !ok {
break
}
rawEvent = raw.(libaudit.RawAuditMessage)
// type Event struct {
// timestamp time.Time
// pid, ppid int
// syscall int
// argc int
// args []string
// cwd string
// }
switch rawEvent.Type {
case auparse.AUDIT_SYSCALL:
if syscallRegex.Match(rawEvent.Data) {
match := syscallRegex.FindSubmatch(rawEvent.Data)
event.timestamp, err[0] = getTimeFromStr(string(match[1]))
eventId, err[1] = strconv.Atoi(string(match[2]))
event.syscall, err[2] = strconv.Atoi(string(match[3]))
event.ppid, err[3] = strconv.Atoi(string(match[4]))
event.pid, err[4] = strconv.Atoi(string(match[5]))
eventTable[eventId] = &Event{
timestamp: event.timestamp,
syscall: event.syscall,
ppid: event.ppid,
pid: event.pid,
argc: 0,
argv: make([]string, 0),
cwd: "",
}
}
case auparse.AUDIT_EXECVE:
if execveRegex.Match(rawEvent.Data) {
match := execveRegex.FindSubmatch(rawEvent.Data)
eventId, err[0] = strconv.Atoi(string(match[1]))
argc, err[1] = strconv.Atoi(string(match[2]))
if err[0] == nil && err[1] == nil && argsRegex.Match(rawEvent.Data) {
match := argsRegex.FindAllSubmatch(rawEvent.Data, -1)
for i := 0; i < argc; i++ {
if len(match[i][2]) == 0 {
// 代表着匹配到的是十六进制数
str := hexToAscii(string(match[i][3]))
eventTable[eventId].argv = append(eventTable[eventId].argv, str)
} else {
eventTable[eventId].argv = append(eventTable[eventId].argv, string(match[i][2]))
}
}
eventTable[eventId].argc = argc
}
}
// case auparse.AUDIT_PATH:
case auparse.AUDIT_CWD:
if cwdRegex.Match(rawEvent.Data) {
match := cwdRegex.FindSubmatch(rawEvent.Data)
eventId, err[0] = strconv.Atoi(string(match[1]))
eventTable[eventId].cwd = string(match[2])
}
case auparse.AUDIT_PROCTITLE:
if proctitleRegex.Match(rawEvent.Data) {
var cmdline string
var pEvent *Event
match := proctitleRegex.FindSubmatch(rawEvent.Data)
eventId, err[0] = strconv.Atoi(string(match[1]))
pEvent = eventTable[eventId]
if pEvent.argc == 0 {
// 只有等于0,才证明没经过EXECVE提取参数,才允许使用PROCTITLE提取参数
if match[3] == nil {
// PROCTITLE写的是十六进制,转换为字符串
cmdline = hexToAscii(string(match[4]))
} else {
cmdline = string(match[3])
}
pEvent.argv = strings.Split(cmdline, " ")
pEvent.argc = len(eventTable[eventId].argv)
}
}
case auparse.AUDIT_EOE:
if eoeRegex.Match(rawEvent.Data) {
match := eoeRegex.FindSubmatch(rawEvent.Data)
eventId, err[0] = strconv.Atoi(string(match[1]))
// ATTENTION: 事件整理完毕,即刻发出,是否合理呢?
cooked = *eventTable[eventId] // 应当采用深拷贝吗?有待实验
cookedChan <- cooked
delete(eventTable, eventId) //发出之后就从信息表扔掉,死人别占地
}
default:
// ATTENTION: 这里也需要做防护
}
}
}
|