summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWe-unite <3205135446@qq.com>2024-07-26 17:23:53 +0800
committerWe-unite <3205135446@qq.com>2024-07-26 17:23:53 +0800
commitec260a31927ef77295eaa07ba370b58b416f47f5 (patch)
tree317dcc68bbeb095af71e5135bf57caefff0bd123
parentb765715b4795ce4bc8940c7b1a1092a78550de94 (diff)
downloadgodo-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--.gitignore2
-rw-r--r--src/deal.go226
-rw-r--r--src/global.go3
-rw-r--r--src/organize.go47
4 files changed, 156 insertions, 122 deletions
diff --git a/.gitignore b/.gitignore
index 9fe8ea9..bfe22fb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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 (
16var mongoMutex sync.Mutex 16var mongoMutex sync.Mutex
17var pidCol mongoClient 17var pidCol mongoClient
18 18
19var docRes []bson.M
20var err error
21
19func deal() { 22func 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
74func 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
96func 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
145func 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
10const ( 10const (
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
31func (et eventType) String() string { 32func (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
21var event Event 21var event Event
22var pEvent *Event 22var pEvent *Event
23var eventId, argc int 23var eventId, argc int
24var err [6]error 24var errs [6]error
25 25
26// 要用的正则匹配列表 26// 要用的正则匹配列表
27var ( 27var (
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)