From a345258c3082903702c81c6c830ff1fd35758861 Mon Sep 17 00:00:00 2001 From: We-unite <3205135446@qq.com> Date: Mon, 29 Jul 2024 11:46:02 +0800 Subject: Hear file Open and close, especially O_TRUNC this commit i successfully catch open/close syscall, and insert them as an independent collection in mongodb otherwise along with pids. and now I've record those open flag "O_TRUNC" as written. --- src/deal.go | 101 ++++++++++++++++++++++++++++++++++++++++++-------------- src/global.go | 1 + src/godo.go | 11 +++--- src/mongo.go | 12 +++++++ src/organize.go | 59 +++++++++++++++++++++------------ 5 files changed, 133 insertions(+), 51 deletions(-) diff --git a/src/deal.go b/src/deal.go index a9861a5..d3b5da0 100644 --- a/src/deal.go +++ b/src/deal.go @@ -3,6 +3,7 @@ package main import ( "fmt" "sync" + "syscall" "time" "go.mongodb.org/mongo-driver/bson" @@ -11,10 +12,11 @@ import ( const ( dbName string = "test" pidColName string = "pids" + fdColName string = "fds" ) var mongoMutex sync.Mutex -var pidCol mongoClient +var pidCol, fdCol mongoClient var docRes []bson.M var err error @@ -24,11 +26,29 @@ func deal() { var cooked Event var ok bool - if err = initMongo(); err != nil { + if err = pidCol.init(dbName, pidColName); err != nil { fmt.Printf("Error while initing the mongodb: %v\n", err) return } + err = pidCol.InsertOne(bson.M{ + "ppid": 1, + "pid": containerdPid, + "cwd": "/", + "children": []bson.M{}, + }) + if err != nil { + fmt.Printf("Error while initing the mongodb: %v\n", err) + return + } + + if err = fdCol.init(dbName, fdColName); err != nil { + fmt.Printf("Error while initing the mongodb: %v\n", err) + return + } + + fmt.Printf("Containerd: %d\n", containerdPid) defer pidCol.Disconnect() + defer fdCol.Disconnect() for { cooked, ok = <-cookedChan @@ -43,6 +63,10 @@ func deal() { dealExecve(cooked) case PIDEXIT: go deletePid(cooked) + case FILEOPEN: + fileOpen(cooked) + case FILECLOSE: + fileClose(cooked) } } } @@ -71,28 +95,6 @@ func deletePid(cooked Event) { mongoMutex.Unlock() } -func initMongo() error { - var err error - if err = pidCol.Connect(dbName, pidColName); err != nil { - return err - } - if err = pidCol.Drop(); err != nil { - return err - } - - err = pidCol.InsertOne(bson.M{ - "ppid": 1, - "pid": containerdPid, - "cwd": "/", - "children": bson.M{}, - }) - if err != nil { - return err - } - fmt.Printf("Containerd: %d\n", containerdPid) - return nil -} - func dealNewPid(cooked Event) { // 有无父进程在观察中 docRes, err = pidCol.Finddoc(bson.M{"pid": cooked.ppid}) @@ -181,3 +183,54 @@ func dealExecve(cooked Event) { } mongoMutex.Unlock() } + +func fileOpen(cooked Event) { + // 查看是否记录了该进程 + res, err := pidCol.Finddoc(bson.M{"pid": cooked.pid}) + if err != nil { + fmt.Printf("Error finding pid %d: %v\n", cooked.pid, err) + } + if len(res) == 0 { + // 没找着,滚 + return + } + + // 确有该进程 + // 权限检查过了,不必再查 + fdCol.InsertOne(bson.M{ + "timestamp": cooked.timestamp, + "fileName": cooked.pathName, + "pid": cooked.pid, + "fd": cooked.exit_code, + "flags": cooked.syscallParam, + "written": []bson.M{}, + }) + + if cooked.syscallParam[1]&syscall.O_TRUNC != 0 { + fdCol.UpdateOne(bson.M{"pid": cooked.pid, "fd": cooked.exit_code}, bson.M{ + "$push": bson.M{ + "written": cooked.timestamp, + }, + }) + } +} + +func fileClose(cooked Event) { + // 直接看文件表有无记录 + res, err := fdCol.Finddoc(bson.M{ + "pid": cooked.pid, + "fd": cooked.syscallParam[0], + "close_timestamp": bson.M{"$exists": false}, + }) + if err != nil { + fmt.Printf("Err closing fd %d of pid %d: %v\n", cooked.syscallParam[0], cooked.pid, err) + } + if len(res) == 0 { + return + } + fdCol.UpdateOne(bson.M{ + "pid": cooked.pid, + "fd": cooked.syscallParam[0], + "close_timestamp": bson.M{"$exists": false}, + }, bson.M{"$set": bson.M{"close_timestamp": cooked.timestamp}}) +} diff --git a/src/global.go b/src/global.go index 7401dc5..d1c5c0f 100644 --- a/src/global.go +++ b/src/global.go @@ -13,6 +13,7 @@ const ( EXECVE FILEOPEN FILEWRITE + FILECLOSE TYPENUM ) diff --git a/src/godo.go b/src/godo.go index 2a00dad..0edcc9f 100644 --- a/src/godo.go +++ b/src/godo.go @@ -44,12 +44,13 @@ func main() { auditCmd.Run() } - // // 监听文件的消息 + // 监听文件的消息 + fileSyscall := []string{"open", "write", "close"} // fileSyscall := []string{"open", "write", "creat", "unlink", "opendir", "mkdir", "rmdir", "chmod", "fchmod", "chown", "fchown", "lchown", "flock"} - // for i := 0; i < len(fileSyscall); i++ { - // auditCmd = exec.Command("auditctl", "-a", "exit,always", "-F", "arch=b64", "-S", pidSyscall[i]) - // auditCmd.Run() - // } + for i := 0; i < len(fileSyscall); i++ { + auditCmd = exec.Command("auditctl", "-a", "exit,always", "-F", "arch=b64", "-S", fileSyscall[i]) + auditCmd.Run() + } // 查找pid containerdPid, err = getPid() diff --git a/src/mongo.go b/src/mongo.go index d00abd2..54f9533 100644 --- a/src/mongo.go +++ b/src/mongo.go @@ -15,6 +15,18 @@ type mongoClient struct { col *mongo.Collection } +func (mc *mongoClient) init(dbName, colName string) error { + var err error + if err = mc.Connect(dbName, colName); err != nil { + return err + } + if err = mc.Drop(); err != nil { + return err + } + + return nil +} + func (mc *mongoClient) Connect(dbName, colName string) error { var err error mc.client, err = mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:27017")) diff --git a/src/organize.go b/src/organize.go index 2489961..1b064c1 100644 --- a/src/organize.go +++ b/src/organize.go @@ -95,7 +95,7 @@ func syscallRaw(rawEvent libaudit.RawAuditMessage) { } argsMatch := argsRegex.FindAllSubmatch(rawEvent.Data, -1) for i := 0; i < 4; i++ { - a[i], errs[0] = strconv.ParseUint(string(argsMatch[i][2]), 16, 64) + a[i], errs[0] = strconv.ParseUint(string(argsMatch[i][3]), 16, 64) } switch syscallTable[event.syscall] { @@ -117,25 +117,6 @@ func syscallRaw(rawEvent libaudit.RawAuditMessage) { cwd: "", }) } - case "open": - // 检查打开的权限 - if a[1]&(syscall.O_APPEND|syscall.O_WRONLY|syscall.O_RDWR|syscall.O_TRUNC) == 0 { - break - } - // TRUNC应该被直接标记为改变,而不是打开 - eventTable.Store(eventId, &Event{ - tag: FILEOPEN, - timestamp: event.timestamp, - syscall: event.syscall, - exit_code: uint64(exit), - ppid: event.ppid, - pid: event.pid, - argc: 0, - argv: make([]string, 0), - cwd: "", - syscallParam: a, - pathName: "", - }) case "execve": eventTable.Store(eventId, &Event{ tag: EXECVE, @@ -160,6 +141,40 @@ func syscallRaw(rawEvent libaudit.RawAuditMessage) { argv: make([]string, 0), cwd: "", }) + case "open": + // 检查打开的权限 + if a[1]&(syscall.O_APPEND|syscall.O_WRONLY|syscall.O_RDWR|syscall.O_TRUNC) == 0 { + break + } + // TRUNC应该被直接标记为改变,而不是打开 + eventTable.Store(eventId, &Event{ + tag: FILEOPEN, + timestamp: event.timestamp, + syscall: event.syscall, + exit_code: uint64(exit), + ppid: event.ppid, + pid: event.pid, + argc: 0, + argv: make([]string, 0), + cwd: "", + syscallParam: a, + pathName: "", + }) + case "close": + // 文件关闭 + eventTable.Store(eventId, &Event{ + tag: FILECLOSE, + timestamp: event.timestamp, + syscall: event.syscall, + exit_code: uint64(exit), + ppid: event.ppid, + pid: event.pid, + argc: 0, + argv: make([]string, 0), + cwd: "", + syscallParam: a, + // pathName: "", + }) } } @@ -244,7 +259,7 @@ func eoe(rawEvent libaudit.RawAuditMessage) { } cooked := *(tmp.(*Event)) cookedChan <- cooked - fmt.Printf("Send: %10d\t%v\t%7d\t%7d\n", eventId, cooked.tag, cooked.ppid, cooked.pid) + // fmt.Printf("Send: %10d\t%v\t%7d\t%7d\n", eventId, cooked.tag, cooked.ppid, cooked.pid) eventTable.Delete(eventId) // 死人别占地 } @@ -267,7 +282,7 @@ func path(rawEvent libaudit.RawAuditMessage) { return } - if pEvent.pathName == "" { + if name[0] == '/' { pEvent.pathName = name } else { pEvent.pathName += "/" + name -- cgit v1.2.3-70-g09d2