diff options
author | We-unite <3205135446@qq.com> | 2024-07-26 17:23:53 +0800 |
---|---|---|
committer | We-unite <3205135446@qq.com> | 2024-07-26 17:23:53 +0800 |
commit | ec260a31927ef77295eaa07ba370b58b416f47f5 (patch) | |
tree | 317dcc68bbeb095af71e5135bf57caefff0bd123 | |
parent | b765715b4795ce4bc8940c7b1a1092a78550de94 (diff) | |
download | godo-ec260a31927ef77295eaa07ba370b58b416f47f5.tar.gz godo-ec260a31927ef77295eaa07ba370b58b416f47f5.zip |
Fix execve before fork & Fix regex to match "exit"
There's 2 bugs from ancestor commits:
- In the 'things_left' tag commit(the grandpa of this commit), we
add a function that allows execve comes before fork, but when it
happens, I forget to insert the basic info (pid, ppid, etc.), as a
result of which it doesn't work in the designed way. Now it is well,
insert execve with pid and ppid, so that the fork event can find it
and finish other info. However, we shouldn't make start_stamp in
this case, so that it's also a flag. I've not removed the unused
execve info, waiting for the future.
- In the parent commit, the syscallRegex is changed, because when we
add more syscalls to be watched, we need more info about their params
but not only the first one. Instead of keeping using single a0 to get
the first param, i use argsRegex for all the params. But this change
causes mismatch of syscallRegex. Now it's fixed.
-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) |