diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | src/deal.go | 226 | ||||
-rw-r--r-- | src/global.go | 3 | ||||
-rw-r--r-- | src/organize.go | 47 |
4 files changed, 156 insertions, 122 deletions
@@ -8,3 +8,5 @@ old/go.* | |||
8 | */*.log | 8 | */*.log |
9 | */*.json | 9 | */*.json |
10 | !logs/*.log | 10 | !logs/*.log |
11 | |||
12 | __debug_bin* | ||
diff --git a/src/deal.go b/src/deal.go index db6fc26..a9861a5 100644 --- a/src/deal.go +++ b/src/deal.go | |||
@@ -16,32 +16,18 @@ const ( | |||
16 | var mongoMutex sync.Mutex | 16 | var mongoMutex sync.Mutex |
17 | var pidCol mongoClient | 17 | var pidCol mongoClient |
18 | 18 | ||
19 | var docRes []bson.M | ||
20 | var err error | ||
21 | |||
19 | func deal() { | 22 | func deal() { |
20 | defer wg.Done() | 23 | defer wg.Done() |
21 | var cooked Event | 24 | var cooked Event |
22 | var ok bool | 25 | var ok bool |
23 | 26 | ||
24 | var err error | 27 | if err = initMongo(); err != nil { |
25 | var res []bson.M | 28 | fmt.Printf("Error while initing the mongodb: %v\n", err) |
26 | |||
27 | if err = pidCol.Connect(dbName, pidColName); err != nil { | ||
28 | fmt.Printf("Error connecting the mongodb: %v\n", err) | ||
29 | } | ||
30 | if err = pidCol.Drop(); err != nil { | ||
31 | fmt.Printf("Error drop the mongodb: %v\n", err) | ||
32 | } | ||
33 | |||
34 | err = pidCol.InsertOne(bson.M{ | ||
35 | "ppid": 1, | ||
36 | "pid": containerdPid, | ||
37 | "cwd": "/", | ||
38 | "children": bson.M{}, | ||
39 | }) | ||
40 | if err != nil { | ||
41 | fmt.Printf("Err containerd: %v", err) | ||
42 | return | 29 | return |
43 | } | 30 | } |
44 | fmt.Printf("Containerd: %d\n", containerdPid) | ||
45 | defer pidCol.Disconnect() | 31 | defer pidCol.Disconnect() |
46 | 32 | ||
47 | for { | 33 | for { |
@@ -50,91 +36,12 @@ func deal() { | |||
50 | break | 36 | break |
51 | } | 37 | } |
52 | 38 | ||
53 | switch syscallTable[cooked.syscall] { | 39 | switch cooked.tag { |
54 | case "clone": | 40 | case NEWPID: |
55 | // 有无父进程在观察中 | 41 | dealNewPid(cooked) |
56 | res, err = pidCol.Finddoc(bson.M{"pid": cooked.ppid}) | 42 | case EXECVE: |
57 | if err != nil || len(res) != 1 { | 43 | dealExecve(cooked) |
58 | break | 44 | case PIDEXIT: |
59 | } | ||
60 | |||
61 | // 自身是否已经记录 | ||
62 | res, err = pidCol.Finddoc(bson.M{"pid": cooked.pid}) | ||
63 | if err != nil { | ||
64 | fmt.Printf("Err finding: %v\n", err) | ||
65 | break | ||
66 | } | ||
67 | mongoMutex.Lock() | ||
68 | if len(res) != 0 { | ||
69 | // 进程原本就存在,换言之别的消息先到了 | ||
70 | // 所有先行抵达的消息必须保留execve/children字段 | ||
71 | // 此处不再更新 | ||
72 | // 以防把原有信息更没了 | ||
73 | pidCol.UpdateOne(bson.M{"pid": cooked.pid}, bson.M{ | ||
74 | "start_timestamp": cooked.timestamp, | ||
75 | "ppid": cooked.ppid, | ||
76 | "pid": cooked.pid, | ||
77 | "cwd": cooked.cwd, | ||
78 | // "execve": []bson.M{}, | ||
79 | "args": cooked.argv, | ||
80 | // "children": []bson.M{}, | ||
81 | }) | ||
82 | } else { | ||
83 | // 这进程本是新修的 | ||
84 | pidCol.InsertOne(bson.M{ | ||
85 | "start_timestamp": cooked.timestamp, | ||
86 | "ppid": cooked.ppid, | ||
87 | "pid": cooked.pid, | ||
88 | "cwd": cooked.cwd, | ||
89 | "execve": []bson.M{}, | ||
90 | "args": cooked.argv, | ||
91 | "children": []bson.M{}, | ||
92 | }) | ||
93 | } | ||
94 | |||
95 | pidCol.UpdateOne(bson.M{"pid": cooked.ppid}, bson.M{ | ||
96 | "$push": bson.M{ | ||
97 | "children": cooked.pid, | ||
98 | }, | ||
99 | }) | ||
100 | mongoMutex.Unlock() | ||
101 | case "execve": | ||
102 | // 父进程在不在?不在扔 | ||
103 | res, err = pidCol.Finddoc(bson.M{"pid": cooked.ppid}) | ||
104 | if err != nil || len(res) != 1 { | ||
105 | break | ||
106 | } | ||
107 | |||
108 | // 首先检查进程是否存在,如不存在则为之创建 | ||
109 | res, err = pidCol.Finddoc(bson.M{"pid": cooked.pid}) | ||
110 | if err != nil { | ||
111 | break | ||
112 | } | ||
113 | mongoMutex.Lock() | ||
114 | if len(res) == 1 { | ||
115 | // 自身已在,直接记录 | ||
116 | pidCol.UpdateOne(bson.M{"pid": cooked.pid}, bson.M{ | ||
117 | "$push": bson.M{ | ||
118 | "execve": bson.M{ | ||
119 | "timestamp": cooked.timestamp, | ||
120 | "args": cooked.argv, | ||
121 | }, | ||
122 | }, | ||
123 | }) | ||
124 | } else { | ||
125 | // 先fork抵达,插入 | ||
126 | pidCol.InsertOne(bson.M{ | ||
127 | "children": []bson.M{}, | ||
128 | "exe_args": []bson.M{ | ||
129 | { | ||
130 | "timestamp": cooked.timestamp, | ||
131 | "execve": cooked.argv, | ||
132 | }, | ||
133 | }, | ||
134 | }) | ||
135 | } | ||
136 | mongoMutex.Unlock() | ||
137 | case "exit", "exit_group": | ||
138 | go deletePid(cooked) | 45 | go deletePid(cooked) |
139 | } | 46 | } |
140 | } | 47 | } |
@@ -163,3 +70,114 @@ func deletePid(cooked Event) { | |||
163 | }) | 70 | }) |
164 | mongoMutex.Unlock() | 71 | mongoMutex.Unlock() |
165 | } | 72 | } |
73 | |||
74 | func initMongo() error { | ||
75 | var err error | ||
76 | if err = pidCol.Connect(dbName, pidColName); err != nil { | ||
77 | return err | ||
78 | } | ||
79 | if err = pidCol.Drop(); err != nil { | ||
80 | return err | ||
81 | } | ||
82 | |||
83 | err = pidCol.InsertOne(bson.M{ | ||
84 | "ppid": 1, | ||
85 | "pid": containerdPid, | ||
86 | "cwd": "/", | ||
87 | "children": bson.M{}, | ||
88 | }) | ||
89 | if err != nil { | ||
90 | return err | ||
91 | } | ||
92 | fmt.Printf("Containerd: %d\n", containerdPid) | ||
93 | return nil | ||
94 | } | ||
95 | |||
96 | func dealNewPid(cooked Event) { | ||
97 | // 有无父进程在观察中 | ||
98 | docRes, err = pidCol.Finddoc(bson.M{"pid": cooked.ppid}) | ||
99 | if err != nil || len(docRes) != 1 { | ||
100 | return | ||
101 | } | ||
102 | |||
103 | // 自身是否已经记录 | ||
104 | docRes, err = pidCol.Finddoc(bson.M{"pid": cooked.pid}) | ||
105 | if err != nil { | ||
106 | fmt.Printf("Err finding: %v\n", err) | ||
107 | return | ||
108 | } | ||
109 | mongoMutex.Lock() | ||
110 | if len(docRes) != 0 { | ||
111 | // 进程原本就存在,换言之别的消息先到了 | ||
112 | // 所有先行抵达的消息必须保留execve/children字段 | ||
113 | // 此处不再更新 | ||
114 | // 以防把原有信息更没了 | ||
115 | pidCol.UpdateOne(bson.M{"pid": cooked.pid}, bson.M{ | ||
116 | "start_timestamp": cooked.timestamp, | ||
117 | "ppid": cooked.ppid, | ||
118 | "pid": cooked.pid, | ||
119 | "cwd": cooked.cwd, | ||
120 | // "execve": []bson.M{}, | ||
121 | "args": cooked.argv, | ||
122 | // "children": []bson.M{}, | ||
123 | }) | ||
124 | } else { | ||
125 | // 这进程本是新修的 | ||
126 | pidCol.InsertOne(bson.M{ | ||
127 | "start_timestamp": cooked.timestamp, | ||
128 | "ppid": cooked.ppid, | ||
129 | "pid": cooked.pid, | ||
130 | "cwd": cooked.cwd, | ||
131 | "execve": []bson.M{}, | ||
132 | "args": cooked.argv, | ||
133 | "children": []bson.M{}, | ||
134 | }) | ||
135 | } | ||
136 | |||
137 | pidCol.UpdateOne(bson.M{"pid": cooked.ppid}, bson.M{ | ||
138 | "$push": bson.M{ | ||
139 | "children": cooked.pid, | ||
140 | }, | ||
141 | }) | ||
142 | mongoMutex.Unlock() | ||
143 | } | ||
144 | |||
145 | func dealExecve(cooked Event) { | ||
146 | // 父进程在不在?不在扔 | ||
147 | docRes, err = pidCol.Finddoc(bson.M{"pid": cooked.ppid}) | ||
148 | if err != nil || len(docRes) != 1 { | ||
149 | return | ||
150 | } | ||
151 | |||
152 | // 首先检查进程是否存在,如不存在则为之创建 | ||
153 | docRes, err = pidCol.Finddoc(bson.M{"pid": cooked.pid}) | ||
154 | if err != nil { | ||
155 | return | ||
156 | } | ||
157 | mongoMutex.Lock() | ||
158 | if len(docRes) == 1 { | ||
159 | // 自身已在,直接记录 | ||
160 | pidCol.UpdateOne(bson.M{"pid": cooked.pid}, bson.M{ | ||
161 | "$push": bson.M{ | ||
162 | "execve": bson.M{ | ||
163 | "timestamp": cooked.timestamp, | ||
164 | "execArgs": cooked.argv, | ||
165 | }, | ||
166 | }, | ||
167 | }) | ||
168 | } else { | ||
169 | // 先fork抵达,插入 | ||
170 | pidCol.InsertOne(bson.M{ | ||
171 | "ppid": cooked.ppid, | ||
172 | "pid": cooked.pid, | ||
173 | "children": []bson.M{}, | ||
174 | "execve": []bson.M{ | ||
175 | { | ||
176 | "timestamp": cooked.timestamp, | ||
177 | "execArgs": cooked.argv, | ||
178 | }, | ||
179 | }, | ||
180 | }) | ||
181 | } | ||
182 | mongoMutex.Unlock() | ||
183 | } | ||
diff --git a/src/global.go b/src/global.go index 3ddbc79..7401dc5 100644 --- a/src/global.go +++ b/src/global.go | |||
@@ -10,6 +10,7 @@ type eventType int | |||
10 | const ( | 10 | const ( |
11 | NEWPID eventType = iota | 11 | NEWPID eventType = iota |
12 | PIDEXIT | 12 | PIDEXIT |
13 | EXECVE | ||
13 | FILEOPEN | 14 | FILEOPEN |
14 | FILEWRITE | 15 | FILEWRITE |
15 | TYPENUM | 16 | TYPENUM |
@@ -29,7 +30,7 @@ type Event struct { | |||
29 | } | 30 | } |
30 | 31 | ||
31 | func (et eventType) String() string { | 32 | func (et eventType) String() string { |
32 | names := []string{"newPid", "pidExit", "open", "write", "typeNum"} | 33 | names := []string{"NEWPID", "PIDEXIT", "EXECVE", "FILEOPEN", "FILEWRITE", "TYPENUM"} |
33 | if et < NEWPID || et > TYPENUM { | 34 | if et < NEWPID || et > TYPENUM { |
34 | return "Unknown" | 35 | return "Unknown" |
35 | } | 36 | } |
diff --git a/src/organize.go b/src/organize.go index 679f361..2489961 100644 --- a/src/organize.go +++ b/src/organize.go | |||
@@ -21,11 +21,11 @@ var ok bool | |||
21 | var event Event | 21 | var event Event |
22 | var pEvent *Event | 22 | var pEvent *Event |
23 | var eventId, argc int | 23 | var eventId, argc int |
24 | var err [6]error | 24 | var errs [6]error |
25 | 25 | ||
26 | // 要用的正则匹配列表 | 26 | // 要用的正则匹配列表 |
27 | var ( | 27 | var ( |
28 | syscallRegex = regexp.MustCompile(`audit\((\d+\.\d+):(\d+)\).*?syscall=(\d+).*?(exit=([-+]?\d+))?.*?ppid=(\d+) pid=(\d+).*?$`) | 28 | syscallRegex = regexp.MustCompile(`audit\((\d+\.\d+):(\d+)\).*?syscall=(\d+)(?:.*?exit=([-+]?\d+))?.*?ppid=(\d+) pid=(\d+).*?$`) |
29 | execveRegex = regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): argc=(\d+)`) | 29 | execveRegex = regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): argc=(\d+)`) |
30 | argsRegex = regexp.MustCompile(`a\d+=("(.*?)"|([0-9a-fA-F]+))`) | 30 | argsRegex = regexp.MustCompile(`a\d+=("(.*?)"|([0-9a-fA-F]+))`) |
31 | pathRegex = regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\):.*?name="(.*?)"`) | 31 | pathRegex = regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\):.*?name="(.*?)"`) |
@@ -76,17 +76,17 @@ func syscallRaw(rawEvent libaudit.RawAuditMessage) { | |||
76 | var a [4]uint64 | 76 | var a [4]uint64 |
77 | // 捕获基础信息 | 77 | // 捕获基础信息 |
78 | match := syscallRegex.FindSubmatch(rawEvent.Data) | 78 | match := syscallRegex.FindSubmatch(rawEvent.Data) |
79 | event.timestamp, err[0] = getTimeFromStr(string(match[1])) | 79 | event.timestamp, errs[0] = getTimeFromStr(string(match[1])) |
80 | eventId, err[1] = strconv.Atoi(string(match[2])) | 80 | eventId, errs[1] = strconv.Atoi(string(match[2])) |
81 | event.syscall, err[2] = strconv.Atoi(string(match[3])) | 81 | event.syscall, errs[2] = strconv.Atoi(string(match[3])) |
82 | if string(match[5]) == "" { | 82 | if string(match[4]) == "" { |
83 | // exit没捕获到 | 83 | // exit没捕获到 |
84 | exit = 0 | 84 | exit = 0 |
85 | } else { | 85 | } else { |
86 | exit, err[3] = strconv.Atoi(string(match[5])) | 86 | exit, errs[3] = strconv.Atoi(string(match[4])) |
87 | } | 87 | } |
88 | event.ppid, err[4] = strconv.Atoi(string(match[6])) | 88 | event.ppid, errs[4] = strconv.Atoi(string(match[5])) |
89 | event.pid, err[5] = strconv.Atoi(string(match[7])) | 89 | event.pid, errs[5] = strconv.Atoi(string(match[6])) |
90 | 90 | ||
91 | // 捕获参数 | 91 | // 捕获参数 |
92 | if !argsRegex.Match(rawEvent.Data) { | 92 | if !argsRegex.Match(rawEvent.Data) { |
@@ -95,7 +95,7 @@ func syscallRaw(rawEvent libaudit.RawAuditMessage) { | |||
95 | } | 95 | } |
96 | argsMatch := argsRegex.FindAllSubmatch(rawEvent.Data, -1) | 96 | argsMatch := argsRegex.FindAllSubmatch(rawEvent.Data, -1) |
97 | for i := 0; i < 4; i++ { | 97 | for i := 0; i < 4; i++ { |
98 | a[i], err[0] = strconv.ParseUint(string(argsMatch[i][2]), 16, 64) | 98 | a[i], errs[0] = strconv.ParseUint(string(argsMatch[i][2]), 16, 64) |
99 | } | 99 | } |
100 | 100 | ||
101 | switch syscallTable[event.syscall] { | 101 | switch syscallTable[event.syscall] { |
@@ -136,6 +136,18 @@ func syscallRaw(rawEvent libaudit.RawAuditMessage) { | |||
136 | syscallParam: a, | 136 | syscallParam: a, |
137 | pathName: "", | 137 | pathName: "", |
138 | }) | 138 | }) |
139 | case "execve": | ||
140 | eventTable.Store(eventId, &Event{ | ||
141 | tag: EXECVE, | ||
142 | timestamp: event.timestamp, | ||
143 | syscall: event.syscall, | ||
144 | exit_code: a[0], | ||
145 | ppid: event.ppid, | ||
146 | pid: event.pid, | ||
147 | argc: 0, | ||
148 | argv: make([]string, 0), | ||
149 | cwd: "", | ||
150 | }) | ||
139 | case "exit", "exit_group": | 151 | case "exit", "exit_group": |
140 | eventTable.Store(eventId, &Event{ | 152 | eventTable.Store(eventId, &Event{ |
141 | tag: PIDEXIT, | 153 | tag: PIDEXIT, |
@@ -157,14 +169,14 @@ func execve(rawEvent libaudit.RawAuditMessage) { | |||
157 | } | 169 | } |
158 | 170 | ||
159 | match := execveRegex.FindSubmatch(rawEvent.Data) | 171 | match := execveRegex.FindSubmatch(rawEvent.Data) |
160 | eventId, err[0] = strconv.Atoi(string(match[1])) | 172 | eventId, errs[0] = strconv.Atoi(string(match[1])) |
161 | argc, err[1] = strconv.Atoi(string(match[2])) | 173 | argc, errs[1] = strconv.Atoi(string(match[2])) |
162 | tmp, ok = eventTable.Load(eventId) | 174 | tmp, ok = eventTable.Load(eventId) |
163 | if !ok { | 175 | if !ok { |
164 | return | 176 | return |
165 | } | 177 | } |
166 | pEvent = tmp.(*Event) | 178 | pEvent = tmp.(*Event) |
167 | if err[0] == nil && err[1] == nil && argsRegex.Match(rawEvent.Data) { | 179 | if errs[0] == nil && errs[1] == nil && argsRegex.Match(rawEvent.Data) { |
168 | match := argsRegex.FindAllSubmatch(rawEvent.Data, -1) | 180 | match := argsRegex.FindAllSubmatch(rawEvent.Data, -1) |
169 | for i := 0; i < argc; i++ { | 181 | for i := 0; i < argc; i++ { |
170 | if len(match[i][2]) == 0 { | 182 | if len(match[i][2]) == 0 { |
@@ -185,7 +197,7 @@ func cwd(rawEvent libaudit.RawAuditMessage) { | |||
185 | } | 197 | } |
186 | 198 | ||
187 | match := cwdRegex.FindSubmatch(rawEvent.Data) | 199 | match := cwdRegex.FindSubmatch(rawEvent.Data) |
188 | eventId, err[0] = strconv.Atoi(string(match[1])) | 200 | eventId, errs[0] = strconv.Atoi(string(match[1])) |
189 | tmp, ok = eventTable.Load(eventId) | 201 | tmp, ok = eventTable.Load(eventId) |
190 | if !ok { | 202 | if !ok { |
191 | return | 203 | return |
@@ -200,7 +212,7 @@ func proctitle(rawEvent libaudit.RawAuditMessage) { | |||
200 | 212 | ||
201 | var cmdline string | 213 | var cmdline string |
202 | match := proctitleRegex.FindSubmatch(rawEvent.Data) | 214 | match := proctitleRegex.FindSubmatch(rawEvent.Data) |
203 | eventId, err[0] = strconv.Atoi(string(match[1])) | 215 | eventId, errs[0] = strconv.Atoi(string(match[1])) |
204 | tmp, ok = eventTable.Load(eventId) | 216 | tmp, ok = eventTable.Load(eventId) |
205 | if !ok { | 217 | if !ok { |
206 | return | 218 | return |
@@ -225,13 +237,14 @@ func eoe(rawEvent libaudit.RawAuditMessage) { | |||
225 | } | 237 | } |
226 | 238 | ||
227 | match := eoeRegex.FindSubmatch(rawEvent.Data) | 239 | match := eoeRegex.FindSubmatch(rawEvent.Data) |
228 | eventId, err[0] = strconv.Atoi(string(match[1])) | 240 | eventId, errs[0] = strconv.Atoi(string(match[1])) |
229 | tmp, ok = eventTable.Load(eventId) | 241 | tmp, ok = eventTable.Load(eventId) |
230 | if !ok { | 242 | if !ok { |
231 | return | 243 | return |
232 | } | 244 | } |
233 | cooked := *(tmp.(*Event)) | 245 | cooked := *(tmp.(*Event)) |
234 | cookedChan <- cooked | 246 | cookedChan <- cooked |
247 | fmt.Printf("Send: %10d\t%v\t%7d\t%7d\n", eventId, cooked.tag, cooked.ppid, cooked.pid) | ||
235 | eventTable.Delete(eventId) // 死人别占地 | 248 | eventTable.Delete(eventId) // 死人别占地 |
236 | } | 249 | } |
237 | 250 | ||
@@ -240,7 +253,7 @@ func path(rawEvent libaudit.RawAuditMessage) { | |||
240 | return | 253 | return |
241 | } | 254 | } |
242 | match := pathRegex.FindSubmatch(rawEvent.Data) | 255 | match := pathRegex.FindSubmatch(rawEvent.Data) |
243 | eventId, err[0] = strconv.Atoi(string(match[1])) | 256 | eventId, errs[0] = strconv.Atoi(string(match[1])) |
244 | name := string(match[2]) | 257 | name := string(match[2]) |
245 | 258 | ||
246 | tmp, ok = eventTable.Load(eventId) | 259 | tmp, ok = eventTable.Load(eventId) |