diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/audit.go | 84 | ||||
-rw-r--r-- | src/basefunc.go | 129 | ||||
-rw-r--r-- | src/deal.go | 265 | ||||
-rw-r--r-- | src/global.go | 49 | ||||
-rw-r--r-- | src/go.mod | 26 | ||||
-rw-r--r-- | src/go.sum | 96 | ||||
-rw-r--r-- | src/go.work | 6 | ||||
-rw-r--r-- | src/go.work.sum | 4 | ||||
-rw-r--r-- | src/godo.go | 164 | ||||
-rw-r--r-- | src/mongo.go | 98 | ||||
m--------- | src/netlink | 0 | ||||
-rw-r--r-- | src/organize.go | 291 | ||||
-rw-r--r-- | src/receive.go | 29 |
13 files changed, 0 insertions, 1241 deletions
diff --git a/src/audit.go b/src/audit.go deleted file mode 100644 index ed48691..0000000 --- a/src/audit.go +++ /dev/null | |||
@@ -1,84 +0,0 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "io" | ||
6 | "log" | ||
7 | "os" | ||
8 | |||
9 | "github.com/elastic/go-libaudit/v2" | ||
10 | ) | ||
11 | |||
12 | func read() error { | ||
13 | // Write netlink response to a file for further analysis or for writing | ||
14 | // tests cases. | ||
15 | var diagWriter io.Writer | ||
16 | if *diag != "" { | ||
17 | f, err := os.OpenFile(*diag, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0o600) | ||
18 | if err != nil { | ||
19 | return err | ||
20 | } | ||
21 | defer f.Close() | ||
22 | diagWriter = f | ||
23 | } | ||
24 | |||
25 | log.Println("starting netlink client") | ||
26 | |||
27 | var err error | ||
28 | var client *libaudit.AuditClient | ||
29 | if *receiveOnly { | ||
30 | client, err = libaudit.NewMulticastAuditClient(diagWriter) | ||
31 | if err != nil { | ||
32 | return fmt.Errorf("failed to create receive-only audit client: %w", err) | ||
33 | } | ||
34 | defer client.Close() | ||
35 | } else { | ||
36 | client, err = libaudit.NewAuditClient(diagWriter) | ||
37 | if err != nil { | ||
38 | return fmt.Errorf("failed to create audit client: %w", err) | ||
39 | } | ||
40 | defer client.Close() | ||
41 | |||
42 | status, err := client.GetStatus() | ||
43 | if err != nil { | ||
44 | return fmt.Errorf("failed to get audit status: %w", err) | ||
45 | } | ||
46 | log.Printf("received audit status=%+v", status) | ||
47 | |||
48 | if status.Enabled == 0 { | ||
49 | log.Println("enabling auditing in the kernel") | ||
50 | if err = client.SetEnabled(true, libaudit.WaitForReply); err != nil { | ||
51 | return fmt.Errorf("failed to set enabled=true: %w", err) | ||
52 | } | ||
53 | } | ||
54 | |||
55 | if status.RateLimit != uint32(*rate) { | ||
56 | log.Printf("setting rate limit in kernel to %v", *rate) | ||
57 | if err = client.SetRateLimit(uint32(*rate), libaudit.NoWait); err != nil { | ||
58 | return fmt.Errorf("failed to set rate limit to unlimited: %w", err) | ||
59 | } | ||
60 | } | ||
61 | |||
62 | if status.BacklogLimit != uint32(*backlog) { | ||
63 | log.Printf("setting backlog limit in kernel to %v", *backlog) | ||
64 | if err = client.SetBacklogLimit(uint32(*backlog), libaudit.NoWait); err != nil { | ||
65 | return fmt.Errorf("failed to set backlog limit: %w", err) | ||
66 | } | ||
67 | } | ||
68 | |||
69 | if status.Enabled != 2 && *immutable { | ||
70 | log.Printf("setting kernel settings as immutable") | ||
71 | if err = client.SetImmutable(libaudit.NoWait); err != nil { | ||
72 | return fmt.Errorf("failed to set kernel as immutable: %w", err) | ||
73 | } | ||
74 | } | ||
75 | |||
76 | log.Printf("sending message to kernel registering our PID (%v) as the audit daemon", os.Getpid()) | ||
77 | if err = client.SetPID(libaudit.NoWait); err != nil { | ||
78 | return fmt.Errorf("failed to set audit PID: %w", err) | ||
79 | } | ||
80 | } | ||
81 | |||
82 | coroutine(client) | ||
83 | return nil | ||
84 | } | ||
diff --git a/src/basefunc.go b/src/basefunc.go deleted file mode 100644 index 2f39507..0000000 --- a/src/basefunc.go +++ /dev/null | |||
@@ -1,129 +0,0 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "bufio" | ||
5 | "fmt" | ||
6 | "os" | ||
7 | "os/exec" | ||
8 | "path/filepath" | ||
9 | "strconv" | ||
10 | "strings" | ||
11 | "time" | ||
12 | ) | ||
13 | |||
14 | func figureOutSyscalls() error { | ||
15 | cmd := exec.Command("ausyscall", "--dump") | ||
16 | stdout, err := cmd.StdoutPipe() | ||
17 | if err != nil { | ||
18 | return err | ||
19 | } | ||
20 | |||
21 | if err := cmd.Start(); err != nil { | ||
22 | return err | ||
23 | } | ||
24 | |||
25 | scanner := bufio.NewScanner(stdout) | ||
26 | for i := 0; scanner.Scan(); i++ { | ||
27 | if i == 0 { | ||
28 | continue | ||
29 | } | ||
30 | line := scanner.Text() | ||
31 | parts := strings.Split(line, "\t") | ||
32 | if len(parts) != 2 { | ||
33 | return fmt.Errorf("invalid ausyscall format") | ||
34 | } | ||
35 | num, err := strconv.Atoi(parts[0]) | ||
36 | if err != nil { | ||
37 | return err | ||
38 | } | ||
39 | syscallTable[num] = parts[1] | ||
40 | } | ||
41 | |||
42 | if err := scanner.Err(); err != nil { | ||
43 | return err | ||
44 | } | ||
45 | if err := cmd.Wait(); err != nil { | ||
46 | return err | ||
47 | } | ||
48 | return nil | ||
49 | } | ||
50 | |||
51 | func getPid() (int, error) { | ||
52 | // 指定要搜索的关键词 | ||
53 | keyword := "/usr/bin/containerd" | ||
54 | |||
55 | // 获取/proc目录下的所有子目录 | ||
56 | procDir, err := filepath.Glob("/proc/*") | ||
57 | if err != nil { | ||
58 | return 0, err | ||
59 | } | ||
60 | |||
61 | // 遍历子目录,查找包含关键词的进程 | ||
62 | for _, dir := range procDir { | ||
63 | pid, err := strconv.Atoi(filepath.Base(dir)) | ||
64 | if err != nil { | ||
65 | continue // 跳过非PID的目录 | ||
66 | } | ||
67 | |||
68 | // 检查进程是否包含关键词 | ||
69 | if containsKeyword(pid, keyword) { | ||
70 | return pid, nil | ||
71 | } | ||
72 | } | ||
73 | err = fmt.Errorf("Error: no containerd process found.") | ||
74 | return 0, err | ||
75 | } | ||
76 | |||
77 | func containsKeyword(pid int, keyword string) bool { | ||
78 | // 构造完整的进程命令路径 | ||
79 | cmdPath := fmt.Sprintf("/proc/%d/cmdline", pid) | ||
80 | |||
81 | // 打开文件 | ||
82 | file, err := os.Open(cmdPath) | ||
83 | if err != nil { | ||
84 | return false | ||
85 | } | ||
86 | defer file.Close() | ||
87 | |||
88 | // 读取文件内容 | ||
89 | scanner := bufio.NewScanner(file) | ||
90 | scanner.Split(bufio.ScanLines) | ||
91 | for scanner.Scan() { | ||
92 | line := scanner.Text() | ||
93 | if strings.Contains(line, keyword) { | ||
94 | return true | ||
95 | } | ||
96 | } | ||
97 | return false | ||
98 | } | ||
99 | |||
100 | func getTimeFromStr(timeStr string) (time.Time, error) { | ||
101 | timestampFloat, err := strconv.ParseFloat(timeStr, 64) | ||
102 | if err != nil { | ||
103 | return time.Unix(0, 0), err | ||
104 | } | ||
105 | secs := int64(timestampFloat) | ||
106 | nsecs := int64((timestampFloat - float64(secs)) * 1e9) | ||
107 | |||
108 | // 只精确到毫秒就够了 | ||
109 | t := time.Unix(secs, nsecs).Truncate(time.Millisecond) | ||
110 | return t, nil | ||
111 | } | ||
112 | |||
113 | func hexToAscii(hexString string) string { | ||
114 | bytes := []byte{} | ||
115 | for i := 0; i < len(hexString); i += 2 { | ||
116 | hexPair := hexString[i : i+2] | ||
117 | // 将十六进制数转换为十进制数 | ||
118 | decimal, err := strconv.ParseInt(hexPair, 16, 8) | ||
119 | if err != nil { | ||
120 | return "Invalid hex string" | ||
121 | } | ||
122 | char := byte(decimal) | ||
123 | bytes = append(bytes, char) | ||
124 | } | ||
125 | |||
126 | asciiString := strings.ReplaceAll(string(bytes), "\000", " ") | ||
127 | |||
128 | return asciiString | ||
129 | } | ||
diff --git a/src/deal.go b/src/deal.go deleted file mode 100644 index e553174..0000000 --- a/src/deal.go +++ /dev/null | |||
@@ -1,265 +0,0 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "os" | ||
6 | "syscall" | ||
7 | |||
8 | "go.mongodb.org/mongo-driver/bson" | ||
9 | ) | ||
10 | |||
11 | const ( | ||
12 | dbName string = "test" | ||
13 | pidColName string = "pids" | ||
14 | fdColName string = "fds" | ||
15 | fileColName string = "files" | ||
16 | ) | ||
17 | |||
18 | // var mongoMutex sync.Mutex | ||
19 | var pidCol, fdCol, fileCol mongoClient | ||
20 | |||
21 | var docRes []bson.M | ||
22 | var err error | ||
23 | |||
24 | func deal() { | ||
25 | defer wg.Done() | ||
26 | var cooked Event | ||
27 | var ok bool | ||
28 | |||
29 | if err = pidCol.init(dbName, pidColName); err != nil { | ||
30 | fmt.Fprintf(os.Stderr, "Error while initing the mongodb: %v\n", err) | ||
31 | return | ||
32 | } | ||
33 | err = pidCol.InsertOne(bson.M{ | ||
34 | "ppid": 1, | ||
35 | "pid": containerdPid, | ||
36 | "cwd": "/", | ||
37 | "children": []bson.M{}, | ||
38 | "daemon": true, | ||
39 | }) | ||
40 | if err != nil { | ||
41 | fmt.Fprintf(os.Stderr, "Error while initing the mongodb: %v\n", err) | ||
42 | return | ||
43 | } | ||
44 | |||
45 | if err = fdCol.init(dbName, fdColName); err != nil { | ||
46 | fmt.Fprintf(os.Stderr, "Error while initing the mongodb: %v\n", err) | ||
47 | return | ||
48 | } | ||
49 | if err = fileCol.init(dbName, fileColName); err != nil { | ||
50 | fmt.Fprintf(os.Stderr, "Error while initing the mongodb: %v\n", err) | ||
51 | } | ||
52 | |||
53 | fmt.Printf("Containerd: %d\n", containerdPid) | ||
54 | defer pidCol.Disconnect() | ||
55 | defer fdCol.Disconnect() | ||
56 | defer fileCol.Disconnect() | ||
57 | |||
58 | for { | ||
59 | cooked, ok = <-cookedChan | ||
60 | if !ok { | ||
61 | break | ||
62 | } | ||
63 | |||
64 | switch cooked.tag { | ||
65 | case NEWPID: | ||
66 | go dealNewPid(cooked) | ||
67 | case EXECVE: | ||
68 | go dealExecve(cooked) | ||
69 | case PIDEXIT: | ||
70 | go deletePid(cooked) | ||
71 | case FILEOPEN: | ||
72 | go fileOpen(cooked) | ||
73 | case FILEWRITE: | ||
74 | go fileWrite(cooked) | ||
75 | case FILECLOSE: | ||
76 | go fileClose(cooked) | ||
77 | case PIVOTROOT: | ||
78 | go pivotRoot(cooked) | ||
79 | } | ||
80 | } | ||
81 | } | ||
82 | |||
83 | func deletePid(cooked Event) { | ||
84 | // 先从老爹那里销户 | ||
85 | pidCol.UpdateOne(bson.M{"pid": cooked.ppid}, bson.M{ | ||
86 | "$pull": bson.M{ | ||
87 | "children": cooked.pid, | ||
88 | }, | ||
89 | }) | ||
90 | |||
91 | // 在这套逻辑里,孩子是不需要收容的,因为我们根本就不看ppid来工作 | ||
92 | |||
93 | // 可以去死了 | ||
94 | pidCol.UpdateOne(bson.M{"pid": cooked.pid}, bson.M{ | ||
95 | "$set": bson.M{ | ||
96 | "exit_timestamp": cooked.timestamp, | ||
97 | "exit_code": cooked.exit_code, | ||
98 | "exit_signal": cooked.exit_signal, | ||
99 | }, | ||
100 | }) | ||
101 | |||
102 | // 理论上这里需要关闭所有文件描述符,但为了处理效率,留给后续流程 | ||
103 | } | ||
104 | |||
105 | func dealNewPid(cooked Event) { | ||
106 | // 自身是否已经记录 | ||
107 | docRes, err = pidCol.Finddoc(bson.M{"pid": cooked.pid}) | ||
108 | if err != nil { | ||
109 | fmt.Fprintf(os.Stderr, "Err finding: %v\n", err) | ||
110 | return | ||
111 | } | ||
112 | |||
113 | if len(docRes) != 0 { | ||
114 | // 进程原本就存在,换言之别的消息先到了 | ||
115 | // 所有先行抵达的消息必须保留execve/children字段 | ||
116 | // 此处不再更新 | ||
117 | // 以防把原有信息更没了 | ||
118 | pidCol.UpdateOne(bson.M{"pid": cooked.pid}, bson.M{ | ||
119 | "start_timestamp": cooked.timestamp, | ||
120 | "ppid": cooked.ppid, | ||
121 | "parentTgid": cooked.parentTgid, | ||
122 | "pid": cooked.pid, | ||
123 | "tgid": cooked.tgid, | ||
124 | "cwd": cooked.cwd, | ||
125 | // "execve": []bson.M{}, | ||
126 | "args": cooked.argv, | ||
127 | // "children": []bson.M{}, | ||
128 | }) | ||
129 | } else { | ||
130 | // 这进程本是新修的 | ||
131 | pidCol.InsertOne(bson.M{ | ||
132 | "start_timestamp": cooked.timestamp, | ||
133 | "ppid": cooked.ppid, | ||
134 | "parentTgid": cooked.parentTgid, | ||
135 | "pid": cooked.pid, | ||
136 | "tgid": cooked.tgid, | ||
137 | "cwd": cooked.cwd, | ||
138 | "execve": []bson.M{}, | ||
139 | "args": cooked.argv, | ||
140 | "children": []bson.M{}, | ||
141 | }) | ||
142 | } | ||
143 | |||
144 | pidCol.UpdateOne(bson.M{"pid": cooked.ppid}, bson.M{ | ||
145 | "$push": bson.M{ | ||
146 | "children": cooked.pid, | ||
147 | }, | ||
148 | }) | ||
149 | } | ||
150 | |||
151 | func dealExecve(cooked Event) { | ||
152 | // 父进程在不在?不在扔 | ||
153 | docRes, err = pidCol.Finddoc(bson.M{"pid": cooked.ppid}) | ||
154 | if err != nil || len(docRes) != 1 { | ||
155 | return | ||
156 | } | ||
157 | |||
158 | // 首先检查进程是否存在,如不存在则为之创建 | ||
159 | docRes, err = pidCol.Finddoc(bson.M{"pid": cooked.pid}) | ||
160 | if err != nil { | ||
161 | return | ||
162 | } | ||
163 | |||
164 | if len(docRes) == 1 { | ||
165 | // 自身已在,直接记录 | ||
166 | pidCol.UpdateOne(bson.M{"pid": cooked.pid}, bson.M{ | ||
167 | "$push": bson.M{ | ||
168 | "execve": bson.M{ | ||
169 | "timestamp": cooked.timestamp, | ||
170 | "execArgs": cooked.argv, | ||
171 | }, | ||
172 | }, | ||
173 | }) | ||
174 | } else { | ||
175 | // 先fork抵达,插入 | ||
176 | pidCol.InsertOne(bson.M{ | ||
177 | "ppid": cooked.ppid, | ||
178 | "pid": cooked.pid, | ||
179 | "children": []bson.M{}, | ||
180 | "execve": []bson.M{ | ||
181 | { | ||
182 | "timestamp": cooked.timestamp, | ||
183 | "execArgs": cooked.argv, | ||
184 | }, | ||
185 | }, | ||
186 | }) | ||
187 | } | ||
188 | } | ||
189 | |||
190 | func fileOpen(cooked Event) { | ||
191 | // 权限检查过了,不必再查 | ||
192 | fdCol.InsertOne(bson.M{ | ||
193 | "timestamp": cooked.timestamp, | ||
194 | "fileName": cooked.srcPath, | ||
195 | "pid": cooked.pid, | ||
196 | "fd": cooked.exit_code, | ||
197 | "flags": cooked.syscallParam, | ||
198 | "written": []bson.M{}, | ||
199 | }) | ||
200 | |||
201 | if cooked.syscallParam[1]&syscall.O_TRUNC != 0 { | ||
202 | fdCol.UpdateOne(bson.M{"pid": cooked.pid, "fd": cooked.exit_code}, bson.M{ | ||
203 | "$push": bson.M{ | ||
204 | "written": cooked.timestamp, | ||
205 | }, | ||
206 | }) | ||
207 | } | ||
208 | } | ||
209 | |||
210 | func fileClose(cooked Event) { | ||
211 | res, err := fdCol.FindOneAndDelete(bson.M{"pid": cooked.pid, "fd": cooked.syscallParam[0]}) | ||
212 | if err != nil { | ||
213 | return | ||
214 | } | ||
215 | res["close_timestamp"] = cooked.timestamp | ||
216 | if err := fileCol.InsertOne(res); err != nil { | ||
217 | fmt.Fprintf(os.Stderr, "Err inserting files: %v\n", err) | ||
218 | } | ||
219 | } | ||
220 | |||
221 | func fileWrite(cooked Event) { | ||
222 | res, err := fdCol.Finddoc(bson.M{ | ||
223 | "pid": cooked.pid, | ||
224 | "fd": cooked.syscallParam[0], | ||
225 | "close_timestamp": bson.M{"$exists": false}, | ||
226 | }) | ||
227 | if err != nil { | ||
228 | fmt.Fprintf(os.Stderr, "Err closing fd %d of pid %d: %v\n", cooked.syscallParam[0], cooked.pid, err) | ||
229 | } | ||
230 | if len(res) == 0 { | ||
231 | return | ||
232 | } | ||
233 | fdCol.UpdateOne(bson.M{ | ||
234 | "pid": cooked.pid, | ||
235 | "fd": cooked.syscallParam[0], | ||
236 | "close_timestamp": bson.M{"$exists": false}, | ||
237 | }, bson.M{"$push": bson.M{"written": cooked.timestamp}}) | ||
238 | } | ||
239 | |||
240 | func pivotRoot(cooked Event) { | ||
241 | // docker的根目录信息,记录 | ||
242 | docRes, err := pidCol.Finddoc(bson.M{"pid": cooked.pid}) | ||
243 | if err != nil { | ||
244 | fmt.Fprintf(os.Stderr, "Err finding: %v\n", err) | ||
245 | return | ||
246 | } | ||
247 | |||
248 | if len(docRes) == 0 { | ||
249 | // fork还没到,等一下 | ||
250 | pidCol.InsertOne(bson.M{ | ||
251 | "start_timestamp": cooked.timestamp, | ||
252 | "ppid": cooked.ppid, | ||
253 | "pid": cooked.pid, | ||
254 | "rootfs": "cwd", | ||
255 | }) | ||
256 | } else { | ||
257 | // 读取已有的工作目录 | ||
258 | cwd := docRes[0]["cwd"] | ||
259 | pidCol.UpdateOne(bson.M{"pid": cooked.pid}, bson.M{ | ||
260 | "$set": bson.M{ | ||
261 | "rootfs": cwd, | ||
262 | }, | ||
263 | }) | ||
264 | } | ||
265 | } | ||
diff --git a/src/global.go b/src/global.go deleted file mode 100644 index 349ba6c..0000000 --- a/src/global.go +++ /dev/null | |||
@@ -1,49 +0,0 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "sync" | ||
5 | "time" | ||
6 | ) | ||
7 | |||
8 | type eventType int | ||
9 | |||
10 | const ( | ||
11 | NEWPID eventType = iota | ||
12 | PIDEXIT | ||
13 | EXECVE | ||
14 | FILEOPEN | ||
15 | FILECLOSE | ||
16 | FILEWRITE | ||
17 | PIVOTROOT | ||
18 | TYPENUM | ||
19 | ) | ||
20 | |||
21 | func (et eventType) String() string { | ||
22 | names := []string{"NEWPID", "PIDEXIT", "EXECVE", "FILEOPEN", "FILECLOSE", "FILEWRITE", "PIVOTROOT", "TYPENUM"} | ||
23 | if et < NEWPID || et > TYPENUM { | ||
24 | return "Unknown" | ||
25 | } | ||
26 | return names[et] | ||
27 | } | ||
28 | |||
29 | type Event struct { | ||
30 | tag eventType | ||
31 | timestamp time.Time | ||
32 | pid, tgid int | ||
33 | ppid, parentTgid int | ||
34 | syscall int | ||
35 | syscallParam [4]uint64 | ||
36 | argc int | ||
37 | argv []string | ||
38 | cwd string | ||
39 | exit_code uint64 | ||
40 | exit_signal int | ||
41 | srcPath string | ||
42 | destPath string | ||
43 | } | ||
44 | |||
45 | var wg sync.WaitGroup // 掌管协程 | ||
46 | var rawChan chan interface{} // 从接收到整理的管道 | ||
47 | var cookedChan chan Event // 整理好的信息的管道 | ||
48 | var syscallTable [500]string //记录一下系统调用 | ||
49 | var containerdPid int | ||
diff --git a/src/go.mod b/src/go.mod deleted file mode 100644 index ed40331..0000000 --- a/src/go.mod +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | module godo | ||
2 | |||
3 | go 1.21.5 | ||
4 | |||
5 | require ( | ||
6 | github.com/elastic/go-libaudit/v2 v2.5.0 | ||
7 | github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 | ||
8 | go.mongodb.org/mongo-driver v1.16.0 | ||
9 | ) | ||
10 | |||
11 | require ( | ||
12 | github.com/golang/snappy v0.0.4 // indirect | ||
13 | github.com/klauspost/compress v1.13.6 // indirect | ||
14 | github.com/montanaflynn/stats v0.7.1 // indirect | ||
15 | github.com/xdg-go/pbkdf2 v1.0.0 // indirect | ||
16 | github.com/xdg-go/scram v1.1.2 // indirect | ||
17 | github.com/xdg-go/stringprep v1.0.4 // indirect | ||
18 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect | ||
19 | go.uber.org/atomic v1.7.0 // indirect | ||
20 | go.uber.org/multierr v1.7.0 // indirect | ||
21 | golang.org/x/crypto v0.22.0 // indirect | ||
22 | golang.org/x/sync v0.7.0 // indirect | ||
23 | golang.org/x/sys v0.19.0 // indirect | ||
24 | golang.org/x/text v0.14.0 // indirect | ||
25 | gopkg.in/yaml.v3 v3.0.1 // indirect | ||
26 | ) | ||
diff --git a/src/go.sum b/src/go.sum deleted file mode 100644 index 9164cd3..0000000 --- a/src/go.sum +++ /dev/null | |||
@@ -1,96 +0,0 @@ | |||
1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
4 | github.com/elastic/go-libaudit/v2 v2.5.0 h1:5OK919QRnGtcjVBz3n/cs5F42im1mPlVTA9TyIn2K54= | ||
5 | github.com/elastic/go-libaudit/v2 v2.5.0/go.mod h1:AjlnhinP+kKQuUJoXLVrqxBM8uyhQmkzoV6jjsCFP4Q= | ||
6 | github.com/elastic/go-licenser v0.4.1 h1:1xDURsc8pL5zYT9R29425J3vkHdt4RT5TNEMeRN48x4= | ||
7 | github.com/elastic/go-licenser v0.4.1/go.mod h1:V56wHMpmdURfibNBggaSBfqgPxyT1Tldns1i87iTEvU= | ||
8 | github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= | ||
9 | github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= | ||
10 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= | ||
11 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= | ||
12 | github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= | ||
13 | github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= | ||
14 | github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= | ||
15 | github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= | ||
16 | github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= | ||
17 | github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= | ||
18 | github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= | ||
19 | github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= | ||
20 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
21 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
22 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
23 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | ||
24 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||
25 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||
26 | github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= | ||
27 | github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= | ||
28 | github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= | ||
29 | github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= | ||
30 | github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= | ||
31 | github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= | ||
32 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA= | ||
33 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= | ||
34 | github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= | ||
35 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= | ||
36 | go.mongodb.org/mongo-driver v1.16.0 h1:tpRsfBJMROVHKpdGyc1BBEzzjDUWjItxbVSZ8Ls4BQ4= | ||
37 | go.mongodb.org/mongo-driver v1.16.0/go.mod h1:oB6AhJQvFQL4LEHyXi6aJzQJtBiTQHiAd83l0GdFaiw= | ||
38 | go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= | ||
39 | go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= | ||
40 | go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= | ||
41 | go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= | ||
42 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||
43 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||
44 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | ||
45 | golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= | ||
46 | golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= | ||
47 | golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= | ||
48 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= | ||
49 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||
50 | golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= | ||
51 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= | ||
52 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||
53 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||
54 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | ||
55 | golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||
56 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= | ||
57 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
58 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
59 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
60 | golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= | ||
61 | golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= | ||
62 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
63 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
64 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
65 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
66 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
67 | golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
68 | golang.org/x/sys v0.0.0-20211102192858-4dd72447c267/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
69 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
70 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
71 | golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||
72 | golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= | ||
73 | golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||
74 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||
75 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= | ||
76 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||
77 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
78 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
79 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= | ||
80 | golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= | ||
81 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= | ||
82 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= | ||
83 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||
84 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||
85 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= | ||
86 | golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= | ||
87 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= | ||
88 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
89 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
90 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
91 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
92 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= | ||
93 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||
94 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||
95 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
96 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||
diff --git a/src/go.work b/src/go.work deleted file mode 100644 index 5b6c957..0000000 --- a/src/go.work +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | go 1.21.5 | ||
2 | |||
3 | use ( | ||
4 | ./netlink | ||
5 | ./ | ||
6 | ) \ No newline at end of file | ||
diff --git a/src/go.work.sum b/src/go.work.sum deleted file mode 100644 index 8201e39..0000000 --- a/src/go.work.sum +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= | ||
2 | golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= | ||
3 | golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= | ||
4 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= | ||
diff --git a/src/godo.go b/src/godo.go deleted file mode 100644 index a30aa88..0000000 --- a/src/godo.go +++ /dev/null | |||
@@ -1,164 +0,0 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "bufio" | ||
5 | "flag" | ||
6 | "fmt" | ||
7 | "log" | ||
8 | "netlink" | ||
9 | "os" | ||
10 | "os/exec" | ||
11 | "strings" | ||
12 | "syscall" | ||
13 | "time" | ||
14 | |||
15 | "github.com/elastic/go-libaudit/v2" | ||
16 | ) | ||
17 | |||
18 | var ( | ||
19 | fs = flag.NewFlagSet("audit", flag.ExitOnError) | ||
20 | diag = fs.String("diag", "", "dump raw information from kernel to file") | ||
21 | rate = fs.Uint("rate", 0, "rate limit in kernel (default 0, no rate limit)") | ||
22 | backlog = fs.Uint("backlog", 8192, "backlog limit") | ||
23 | immutable = fs.Bool("immutable", false, "make kernel audit settings immutable (requires reboot to undo)") | ||
24 | receiveOnly = fs.Bool("ro", false, "receive only using multicast, requires kernel 3.16+") | ||
25 | ) | ||
26 | |||
27 | func main() { | ||
28 | // 检查用户身份,并添加auditd规则,监听所有syscall | ||
29 | if os.Geteuid() != 0 { | ||
30 | fmt.Fprintf(os.Stderr, "Err: Please run me as root, %d!\n", os.Getegid()) | ||
31 | return | ||
32 | } | ||
33 | |||
34 | // 所有的系统调用号与名称的关系 | ||
35 | err := figureOutSyscalls() | ||
36 | if err != nil { | ||
37 | fmt.Fprintf(os.Stderr, "Error figuring out syscall numbers: %v\n", err) | ||
38 | } | ||
39 | |||
40 | exec.Command("auditctl", "-D").Run() | ||
41 | exec.Command("auditctl", "-b", "1000000000").Run() | ||
42 | exec.Command("auditctl", "--reset-lost").Run() | ||
43 | |||
44 | var auditCmd *exec.Cmd | ||
45 | |||
46 | pidSyscall := []string{"execve", "pivot_root"} | ||
47 | // // 设置监听规则 | ||
48 | for i := 0; i < len(pidSyscall); i++ { | ||
49 | auditCmd = exec.Command("auditctl", "-a", "exit,always", "-F", "arch=b64", "-S", pidSyscall[i]) | ||
50 | auditCmd.Run() | ||
51 | } | ||
52 | |||
53 | // 监听文件的消息 | ||
54 | fileSyscall := []string{"open", "close", "write"} | ||
55 | // fileSyscall := []string{"open", "write", "creat", "unlink", "opendir", "mkdir", "rmdir", "chmod", "fchmod", "chown", "fchown", "lchown", "flock"} | ||
56 | for i := 0; i < len(fileSyscall); i++ { | ||
57 | auditCmd = exec.Command("auditctl", "-a", "exit,always", "-F", "arch=b64", "-S", fileSyscall[i]) | ||
58 | auditCmd.Run() | ||
59 | } | ||
60 | |||
61 | // 查找pid | ||
62 | containerdPid, err = getPid() | ||
63 | if err != nil { | ||
64 | fmt.Fprintf(os.Stderr, "Error finding containerd: %v\n", err) | ||
65 | return | ||
66 | } | ||
67 | |||
68 | // 开始运行,解析命令行参数后监听 | ||
69 | if err := fs.Parse(os.Args[1:]); err != nil { | ||
70 | log.Fatal(err) | ||
71 | } | ||
72 | |||
73 | if err := read(); err != nil { | ||
74 | log.Fatalf("error: %v", err) | ||
75 | } | ||
76 | } | ||
77 | |||
78 | func coroutine(client *libaudit.AuditClient) { | ||
79 | // 各协程至此开始 | ||
80 | rawChan = make(chan interface{}, 65536) | ||
81 | cookedChan = make(chan Event, 65536) | ||
82 | |||
83 | wg.Add(1) | ||
84 | go procWatch() | ||
85 | |||
86 | wg.Add(1) | ||
87 | go receive(client) | ||
88 | wg.Add(1) | ||
89 | go orgnaze() | ||
90 | wg.Add(1) | ||
91 | go deal() | ||
92 | |||
93 | wg.Wait() | ||
94 | time.Sleep(2 * time.Second) | ||
95 | } | ||
96 | |||
97 | func procWatch() error { | ||
98 | ns, err := netlink.NewNetlinkSocket(syscall.NETLINK_CONNECTOR, 12345) | ||
99 | if err != nil { | ||
100 | fmt.Fprintf(os.Stderr, "Error creating socket: %v\n", err) | ||
101 | return err | ||
102 | } | ||
103 | defer ns.Close() | ||
104 | for { | ||
105 | res, err := ns.Receive(20) | ||
106 | if err != nil { | ||
107 | fmt.Fprintf(os.Stderr, "Error recv: %v\n", err) | ||
108 | continue | ||
109 | } | ||
110 | for i := 0; i < len(res); i++ { | ||
111 | procEvent := netlink.ParseProcEvent(res[i].Data) | ||
112 | switch procEvent.What { | ||
113 | case netlink.PROC_EVENT_FORK: | ||
114 | data := procEvent.Data.(netlink.ProcEventFork) | ||
115 | cooked := Event{ | ||
116 | tag: NEWPID, | ||
117 | timestamp: time.Now(), | ||
118 | pid: int(data.ChildPid), | ||
119 | tgid: int(data.ChildTgid), | ||
120 | ppid: int(data.ParentPid), | ||
121 | parentTgid: int(data.ParentTgid), | ||
122 | } | ||
123 | checkProc(&cooked) | ||
124 | cookedChan <- cooked | ||
125 | case netlink.PROC_EVENT_EXIT: | ||
126 | data := procEvent.Data.(netlink.ProcEventExit) | ||
127 | cooked := Event{ | ||
128 | tag: PIDEXIT, | ||
129 | timestamp: time.Now(), | ||
130 | pid: int(data.ProcessPid), | ||
131 | exit_code: uint64(data.ExitCode), | ||
132 | exit_signal: int(data.ExitSignal), | ||
133 | } | ||
134 | cookedChan <- cooked | ||
135 | default: | ||
136 | } | ||
137 | } | ||
138 | } | ||
139 | } | ||
140 | |||
141 | func checkProc(pCooked *Event) { | ||
142 | fileName := fmt.Sprintf("/proc/%d/task/%d/cmdline", pCooked.tgid, pCooked.pid) | ||
143 | fd, err := os.Open(fileName) | ||
144 | if err != nil { | ||
145 | fmt.Fprintf(os.Stderr, "Err: %v\n", err) | ||
146 | return | ||
147 | } | ||
148 | |||
149 | scanner := bufio.NewScanner(fd) | ||
150 | scanner.Split(bufio.ScanLines) | ||
151 | for scanner.Scan() { | ||
152 | line := scanner.Text() | ||
153 | pCooked.argv = append(pCooked.argv, strings.Split(line, "\x00")...) | ||
154 | } | ||
155 | pCooked.argc = len(pCooked.argv) | ||
156 | fd.Close() | ||
157 | |||
158 | fileName = fmt.Sprintf("/proc/%d/task/%d/cwd", pCooked.tgid, pCooked.pid) | ||
159 | pCooked.cwd, err = os.Readlink(fileName) | ||
160 | if err != nil { | ||
161 | fmt.Fprintf(os.Stderr, "Err: %v\n", err) | ||
162 | pCooked.cwd = "" | ||
163 | } | ||
164 | } | ||
diff --git a/src/mongo.go b/src/mongo.go deleted file mode 100644 index 1d9f74f..0000000 --- a/src/mongo.go +++ /dev/null | |||
@@ -1,98 +0,0 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "context" | ||
5 | "time" | ||
6 | |||
7 | "go.mongodb.org/mongo-driver/bson" | ||
8 | "go.mongodb.org/mongo-driver/mongo" | ||
9 | "go.mongodb.org/mongo-driver/mongo/options" | ||
10 | ) | ||
11 | |||
12 | type mongoClient struct { | ||
13 | dbName, colName string | ||
14 | client *mongo.Client | ||
15 | col *mongo.Collection | ||
16 | } | ||
17 | |||
18 | func (mc *mongoClient) init(dbName, colName string) error { | ||
19 | var err error | ||
20 | if err = mc.Connect(dbName, colName); err != nil { | ||
21 | return err | ||
22 | } | ||
23 | if err = mc.Drop(); err != nil { | ||
24 | return err | ||
25 | } | ||
26 | |||
27 | return nil | ||
28 | } | ||
29 | |||
30 | func (mc *mongoClient) Connect(dbName, colName string) error { | ||
31 | var err error | ||
32 | mc.client, err = mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:27017")) | ||
33 | |||
34 | if err != nil { | ||
35 | return err | ||
36 | } | ||
37 | |||
38 | ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) | ||
39 | err = mc.client.Connect(ctx) | ||
40 | if err != nil { | ||
41 | return err | ||
42 | } | ||
43 | |||
44 | mc.col = mc.client.Database(dbName).Collection(colName) | ||
45 | mc.dbName = dbName | ||
46 | mc.colName = colName | ||
47 | return nil | ||
48 | } | ||
49 | |||
50 | func (mc *mongoClient) InsertOne(document interface{}) error { | ||
51 | _, err := mc.col.InsertOne(context.Background(), document) | ||
52 | return err | ||
53 | } | ||
54 | |||
55 | func (mc *mongoClient) UpdateOne(filter, update interface{}) error { | ||
56 | _, err := mc.col.UpdateOne(context.Background(), filter, update) | ||
57 | return err | ||
58 | } | ||
59 | |||
60 | func (mc *mongoClient) UpdateMany(filter, update interface{}) error { | ||
61 | _, err := mc.col.UpdateMany(context.Background(), filter, update) | ||
62 | return err | ||
63 | } | ||
64 | |||
65 | func (mc *mongoClient) Finddoc(filter bson.M) ([]bson.M, error) { | ||
66 | cur, err := mc.col.Find(context.Background(), filter) | ||
67 | if err != nil { | ||
68 | return nil, err | ||
69 | } | ||
70 | |||
71 | var results []bson.M | ||
72 | err = cur.All(context.Background(), &results) | ||
73 | |||
74 | return results, err | ||
75 | } | ||
76 | |||
77 | func (mc *mongoClient) FindOneAndDelete(filter bson.M) (bson.M, error) { | ||
78 | res := mc.col.FindOneAndDelete(context.Background(), filter) | ||
79 | var result bson.M | ||
80 | err := res.Decode(&result) | ||
81 | return result, err | ||
82 | } | ||
83 | |||
84 | func (mc *mongoClient) Drop() error { | ||
85 | return mc.col.Drop(context.Background()) | ||
86 | } | ||
87 | |||
88 | func (mc *mongoClient) Disconnect() error { | ||
89 | err := mc.client.Disconnect(context.Background()) | ||
90 | if err != nil { | ||
91 | return err | ||
92 | } | ||
93 | mc.col = nil | ||
94 | mc.client = nil | ||
95 | mc.dbName = "" | ||
96 | mc.colName = "" | ||
97 | return nil | ||
98 | } | ||
diff --git a/src/netlink b/src/netlink deleted file mode 160000 | |||
Subproject e53c2724725c5991cdd9ea088c26832c5c9fcf0 | |||
diff --git a/src/organize.go b/src/organize.go deleted file mode 100644 index 293371b..0000000 --- a/src/organize.go +++ /dev/null | |||
@@ -1,291 +0,0 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "os" | ||
6 | "regexp" | ||
7 | "strconv" | ||
8 | "strings" | ||
9 | "sync" | ||
10 | "syscall" | ||
11 | |||
12 | "github.com/elastic/go-libaudit/v2" | ||
13 | "github.com/elastic/go-libaudit/v2/auparse" | ||
14 | ) | ||
15 | |||
16 | // 为每个事务id存储其信息,事务id在操作系统运行期间是唯一的 | ||
17 | var eventTable sync.Map | ||
18 | |||
19 | // 事件信息 | ||
20 | var tmp any | ||
21 | var ok bool | ||
22 | var event Event | ||
23 | var pEvent *Event | ||
24 | var eventId, argc int | ||
25 | |||
26 | // var errs [6]error | ||
27 | |||
28 | // 要用的正则匹配列表 | ||
29 | var ( | ||
30 | syscallRegex = regexp.MustCompile(`audit\((\d+\.\d+):(\d+)\).*?syscall=(\d+)(?:.*?exit=([-+]?\d+))?.*?ppid=(\d+) pid=(\d+).*?subj=(.*?):(.*?):(.*?):(.*?) .*?$`) | ||
31 | execveRegex = regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): argc=(\d+)`) | ||
32 | argsRegex = regexp.MustCompile(`a\d+=("(.*?)"|([0-9a-fA-F]+))`) | ||
33 | pathRegex = regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): item=(\d+) name="(.*?)"`) | ||
34 | cwdRegex = regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): cwd="(.*?)"`) | ||
35 | proctitleRegex = regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): proctitle=("(.*?)"|([0-9a-fA-F]+))$`) | ||
36 | eoeRegex = regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\)`) | ||
37 | ) | ||
38 | |||
39 | func orgnaze() { | ||
40 | defer wg.Done() | ||
41 | defer close(cookedChan) | ||
42 | // 接收信息 | ||
43 | var raw interface{} | ||
44 | var rawEvent libaudit.RawAuditMessage | ||
45 | |||
46 | for { | ||
47 | raw, ok = <-rawChan | ||
48 | if !ok { | ||
49 | break | ||
50 | } | ||
51 | rawEvent = raw.(libaudit.RawAuditMessage) | ||
52 | // fmt.Printf("type=%v msg=%s\n", rawEvent.Type, rawEvent.Data) | ||
53 | |||
54 | switch rawEvent.Type { | ||
55 | case auparse.AUDIT_SYSCALL: | ||
56 | syscallRaw(rawEvent) | ||
57 | case auparse.AUDIT_EXECVE: | ||
58 | execve(rawEvent) | ||
59 | case auparse.AUDIT_CWD: | ||
60 | cwd(rawEvent) | ||
61 | case auparse.AUDIT_PATH: | ||
62 | path(rawEvent) | ||
63 | case auparse.AUDIT_PROCTITLE: | ||
64 | proctitle(rawEvent) | ||
65 | case auparse.AUDIT_EOE: | ||
66 | eoe(rawEvent) | ||
67 | default: | ||
68 | } | ||
69 | } | ||
70 | } | ||
71 | |||
72 | func syscallRaw(rawEvent libaudit.RawAuditMessage) { | ||
73 | if !syscallRegex.Match(rawEvent.Data) { | ||
74 | return | ||
75 | } | ||
76 | |||
77 | var exit int | ||
78 | var a [4]uint64 | ||
79 | var subj [4]string | ||
80 | // 捕获基础信息 | ||
81 | match := syscallRegex.FindSubmatch(rawEvent.Data) | ||
82 | event.timestamp, _ = getTimeFromStr(string(match[1])) | ||
83 | eventId, _ = strconv.Atoi(string(match[2])) | ||
84 | event.syscall, _ = strconv.Atoi(string(match[3])) | ||
85 | if string(match[4]) == "" { | ||
86 | // exit没捕获到 | ||
87 | exit = 0 | ||
88 | } else { | ||
89 | exit, _ = strconv.Atoi(string(match[4])) | ||
90 | } | ||
91 | event.ppid, _ = strconv.Atoi(string(match[5])) | ||
92 | event.pid, _ = strconv.Atoi(string(match[6])) | ||
93 | |||
94 | // 几个subj,说不定会有用 | ||
95 | for i := 0; i < 4; i++ { | ||
96 | subj[i] = string(match[7+i]) | ||
97 | } | ||
98 | |||
99 | // 捕获参数 | ||
100 | if !argsRegex.Match(rawEvent.Data) { | ||
101 | fmt.Fprintf(os.Stderr, "Error: don't get args in syscall event!\n") | ||
102 | return | ||
103 | } | ||
104 | argsMatch := argsRegex.FindAllSubmatch(rawEvent.Data, -1) | ||
105 | for i := 0; i < 4; i++ { | ||
106 | a[i], _ = strconv.ParseUint(string(argsMatch[i][3]), 16, 64) | ||
107 | } | ||
108 | |||
109 | switch syscallTable[event.syscall] { | ||
110 | case "execve": | ||
111 | eventTable.Store(eventId, &Event{ | ||
112 | tag: EXECVE, | ||
113 | timestamp: event.timestamp, | ||
114 | syscall: event.syscall, | ||
115 | exit_code: a[0], | ||
116 | ppid: event.ppid, | ||
117 | pid: event.pid, | ||
118 | argc: 0, | ||
119 | argv: make([]string, 0), | ||
120 | cwd: "", | ||
121 | }) | ||
122 | case "open": | ||
123 | // 检查打开的权限 | ||
124 | if a[1]&(syscall.O_APPEND|syscall.O_WRONLY|syscall.O_RDWR|syscall.O_TRUNC) == 0 { | ||
125 | break | ||
126 | } | ||
127 | // TRUNC应该被直接标记为改变,而不是打开 | ||
128 | eventTable.Store(eventId, &Event{ | ||
129 | tag: FILEOPEN, | ||
130 | timestamp: event.timestamp, | ||
131 | syscall: event.syscall, | ||
132 | exit_code: uint64(exit), | ||
133 | ppid: event.ppid, | ||
134 | pid: event.pid, | ||
135 | argc: 0, | ||
136 | argv: make([]string, 0), | ||
137 | cwd: "", | ||
138 | syscallParam: a, | ||
139 | srcPath: "", | ||
140 | }) | ||
141 | case "write": | ||
142 | eventTable.Store(eventId, &Event{ | ||
143 | tag: FILEWRITE, | ||
144 | timestamp: event.timestamp, | ||
145 | syscall: event.syscall, | ||
146 | exit_code: uint64(exit), | ||
147 | ppid: event.ppid, | ||
148 | pid: event.pid, | ||
149 | argc: 0, | ||
150 | argv: make([]string, 0), | ||
151 | cwd: "", | ||
152 | syscallParam: a, | ||
153 | }) | ||
154 | case "close": | ||
155 | // 文件关闭 | ||
156 | eventTable.Store(eventId, &Event{ | ||
157 | tag: FILECLOSE, | ||
158 | timestamp: event.timestamp, | ||
159 | syscall: event.syscall, | ||
160 | exit_code: uint64(exit), | ||
161 | ppid: event.ppid, | ||
162 | pid: event.pid, | ||
163 | argc: 0, | ||
164 | argv: make([]string, 0), | ||
165 | cwd: "", | ||
166 | syscallParam: a, | ||
167 | }) | ||
168 | case "pivot_root": | ||
169 | if subj[2] == "container_runtime_t" { | ||
170 | eventTable.Store(eventId, &Event{ | ||
171 | tag: PIVOTROOT, | ||
172 | timestamp: event.timestamp, | ||
173 | syscall: event.syscall, | ||
174 | ppid: event.ppid, | ||
175 | pid: event.pid, | ||
176 | syscallParam: a, | ||
177 | }) | ||
178 | } | ||
179 | } | ||
180 | } | ||
181 | |||
182 | func execve(rawEvent libaudit.RawAuditMessage) { | ||
183 | if !execveRegex.Match(rawEvent.Data) { | ||
184 | return | ||
185 | } | ||
186 | |||
187 | match := execveRegex.FindSubmatch(rawEvent.Data) | ||
188 | eventId, _ = strconv.Atoi(string(match[1])) | ||
189 | argc, _ = strconv.Atoi(string(match[2])) | ||
190 | tmp, ok = eventTable.Load(eventId) | ||
191 | if !ok { | ||
192 | return | ||
193 | } | ||
194 | pEvent = tmp.(*Event) | ||
195 | if argsRegex.Match(rawEvent.Data) { | ||
196 | match := argsRegex.FindAllSubmatch(rawEvent.Data, -1) | ||
197 | for i := 0; i < argc; i++ { | ||
198 | if len(match[i][2]) == 0 { | ||
199 | // 代表着匹配到的是十六进制数 | ||
200 | str := hexToAscii(string(match[i][3])) | ||
201 | pEvent.argv = append(pEvent.argv, str) | ||
202 | } else { | ||
203 | pEvent.argv = append(pEvent.argv, string(match[i][2])) | ||
204 | } | ||
205 | } | ||
206 | pEvent.argc = argc | ||
207 | } | ||
208 | } | ||
209 | |||
210 | func cwd(rawEvent libaudit.RawAuditMessage) { | ||
211 | if !cwdRegex.Match(rawEvent.Data) { | ||
212 | return | ||
213 | } | ||
214 | |||
215 | match := cwdRegex.FindSubmatch(rawEvent.Data) | ||
216 | eventId, _ = strconv.Atoi(string(match[1])) | ||
217 | tmp, ok = eventTable.Load(eventId) | ||
218 | if !ok { | ||
219 | return | ||
220 | } | ||
221 | tmp.(*Event).cwd = string(match[2]) | ||
222 | } | ||
223 | |||
224 | func proctitle(rawEvent libaudit.RawAuditMessage) { | ||
225 | if !proctitleRegex.Match(rawEvent.Data) { | ||
226 | return | ||
227 | } | ||
228 | |||
229 | var cmdline string | ||
230 | match := proctitleRegex.FindSubmatch(rawEvent.Data) | ||
231 | eventId, _ = strconv.Atoi(string(match[1])) | ||
232 | tmp, ok = eventTable.Load(eventId) | ||
233 | if !ok { | ||
234 | return | ||
235 | } | ||
236 | pEvent = tmp.(*Event) | ||
237 | if pEvent.argc == 0 { | ||
238 | // 只有等于0,才证明没经过EXECVE提取参数,才允许使用PROCTITLE提取参数 | ||
239 | if match[3] == nil { | ||
240 | // PROCTITLE写的是十六进制,转换为字符串 | ||
241 | cmdline = hexToAscii(string(match[4])) | ||
242 | } else { | ||
243 | cmdline = string(match[3]) | ||
244 | } | ||
245 | pEvent.argv = strings.Split(cmdline, " ") | ||
246 | pEvent.argc = len(pEvent.argv) | ||
247 | } | ||
248 | } | ||
249 | |||
250 | func eoe(rawEvent libaudit.RawAuditMessage) { | ||
251 | if !eoeRegex.Match(rawEvent.Data) { | ||
252 | return | ||
253 | } | ||
254 | |||
255 | match := eoeRegex.FindSubmatch(rawEvent.Data) | ||
256 | eventId, _ = strconv.Atoi(string(match[1])) | ||
257 | tmp, ok = eventTable.Load(eventId) | ||
258 | if !ok { | ||
259 | return | ||
260 | } | ||
261 | cooked := *(tmp.(*Event)) | ||
262 | cookedChan <- cooked | ||
263 | eventTable.Delete(eventId) // 死人别占地 | ||
264 | } | ||
265 | |||
266 | func path(rawEvent libaudit.RawAuditMessage) { | ||
267 | if !pathRegex.Match(rawEvent.Data) { | ||
268 | return | ||
269 | } | ||
270 | match := pathRegex.FindSubmatch(rawEvent.Data) | ||
271 | eventId, _ = strconv.Atoi(string(match[1])) | ||
272 | // item, _ := strconv.Atoi(string(match[2])) | ||
273 | name := string(match[3]) | ||
274 | |||
275 | tmp, ok = eventTable.Load(eventId) | ||
276 | if !ok { | ||
277 | return | ||
278 | } | ||
279 | pEvent = tmp.(*Event) | ||
280 | |||
281 | // 先看看是不是文件操作 | ||
282 | if pEvent.tag != FILEOPEN { | ||
283 | return | ||
284 | } | ||
285 | |||
286 | if name[0] == '/' { | ||
287 | pEvent.srcPath = name | ||
288 | } else { | ||
289 | pEvent.srcPath += "/" + name | ||
290 | } | ||
291 | } | ||
diff --git a/src/receive.go b/src/receive.go deleted file mode 100644 index c0dea00..0000000 --- a/src/receive.go +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | |||
6 | "github.com/elastic/go-libaudit/v2" | ||
7 | "github.com/elastic/go-libaudit/v2/auparse" | ||
8 | "github.com/mohae/deepcopy" | ||
9 | ) | ||
10 | |||
11 | func receive(r *libaudit.AuditClient) error { | ||
12 | defer wg.Done() | ||
13 | defer close(rawChan) | ||
14 | for { | ||
15 | rawEvent, err := r.Receive(false) | ||
16 | if err != nil { | ||
17 | return fmt.Errorf("receive failed: %w", err) | ||
18 | } | ||
19 | |||
20 | // Messages from 1300-2999 are valid audit messages. | ||
21 | if rawEvent.Type < auparse.AUDIT_USER_AUTH || | ||
22 | rawEvent.Type > auparse.AUDIT_LAST_USER_MSG2 { | ||
23 | continue | ||
24 | } | ||
25 | |||
26 | rawEventMessage := deepcopy.Copy(*rawEvent) | ||
27 | rawChan <- rawEventMessage | ||
28 | } | ||
29 | } | ||