summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWe-unite <3205135446@qq.com>2024-07-31 11:46:01 +0800
committerWe-unite <3205135446@qq.com>2024-08-01 15:10:36 +0800
commit3efeef969ebc344c993ce0fc46f557c7d8560525 (patch)
treef0f917080c64c8def6922c365465f1ee5371c464
parentd6c6e13796435f9e1e59fec891aa53680748a2d7 (diff)
downloadgodo-3efeef969ebc344c993ce0fc46f557c7d8560525.tar.gz
godo-3efeef969ebc344c993ce0fc46f557c7d8560525.zip
Use netlink connector to recv pid info, fix exec
For some reasons, kernel-connector can catch exec event, but it doesn't tell me about what the process exec and what're its args. So we should use audit to collect these infomations, and complete in the database. However, there's different delays between connector and audit, although they both use netlink socket, as a result of which, exec may comes before fork. we deal with it the same way. But, there's also exec event lost, may because of the check for ppid in exec event, but it's necessary, and if is deleted, too much irrelavent infomation would flood into database, i've tried. So make it there, just go forward. Besides, what's newly discovered is that pthread_create also use clone syscall, but if pid 1 has a thread 2, the exec info will say that pid 2 execs. So i shouldn't ignore connector msg that childPid ne childTgid. This is my first attempt to use git-submodule function in my own pro- ject, also golang local package. Congratulations! Now, fight to fix about file operations. Hope that there wouldn't be too many fucking bugs.
-rw-r--r--.gitignore3
-rw-r--r--.gitmodules3
-rw-r--r--src/deal.go30
-rw-r--r--src/global.go7
-rw-r--r--src/go.work6
-rw-r--r--src/go.work.sum4
-rw-r--r--src/godo.go82
m---------src/netlink0
-rw-r--r--src/organize.go31
9 files changed, 117 insertions, 49 deletions
diff --git a/.gitignore b/.gitignore
index bfe22fb..b9f0a38 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
1.vscode/* 1.vscode/*
2godo 2*/godo
3*/hello
3 4
4old/* 5old/*
5!old/*.* 6!old/*.*
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..6a63c7b
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
1[submodule "src/netlink"]
2 path = src/netlink
3 url = https://github.com/We-unite/netlink
diff --git a/src/deal.go b/src/deal.go
index 717344c..3119fff 100644
--- a/src/deal.go
+++ b/src/deal.go
@@ -98,12 +98,15 @@ func deletePid(cooked Event) {
98 "$set": bson.M{ 98 "$set": bson.M{
99 "exit_timestamp": cooked.timestamp, 99 "exit_timestamp": cooked.timestamp,
100 "exit_code": cooked.exit_code, 100 "exit_code": cooked.exit_code,
101 "exit_signal": cooked.exit_signal,
101 }, 102 },
102 }) 103 })
103 mongoMutex.Unlock() 104 mongoMutex.Unlock()
105 fmt.Printf("Exit: %v\t%6d\t%6d\n", cooked.timestamp, cooked.pid, cooked.exit_code)
104} 106}
105 107
106func dealNewPid(cooked Event) { 108func dealNewPid(cooked Event) {
109 fmt.Printf("Fork: %v\t%6d\t%6d\n", cooked.timestamp, cooked.ppid, cooked.pid)
107 // 有无父进程在观察中 110 // 有无父进程在观察中
108 docRes, err = pidCol.Finddoc(bson.M{"pid": cooked.ppid}) 111 docRes, err = pidCol.Finddoc(bson.M{"pid": cooked.ppid})
109 if err != nil || len(docRes) != 1 { 112 if err != nil || len(docRes) != 1 {
@@ -153,6 +156,7 @@ func dealNewPid(cooked Event) {
153} 156}
154 157
155func dealExecve(cooked Event) { 158func dealExecve(cooked Event) {
159 fmt.Printf("EXEC: %6d\t%6d\n", cooked.ppid, cooked.pid)
156 // 父进程在不在?不在扔 160 // 父进程在不在?不在扔
157 docRes, err = pidCol.Finddoc(bson.M{"pid": cooked.ppid}) 161 docRes, err = pidCol.Finddoc(bson.M{"pid": cooked.ppid})
158 if err != nil || len(docRes) != 1 { 162 if err != nil || len(docRes) != 1 {
@@ -175,19 +179,19 @@ func dealExecve(cooked Event) {
175 }, 179 },
176 }, 180 },
177 }) 181 })
178 // } else { 182 } else {
179 // // 先fork抵达,插入 183 // 先fork抵达,插入
180 // pidCol.InsertOne(bson.M{ 184 pidCol.InsertOne(bson.M{
181 // "ppid": cooked.ppid, 185 "ppid": cooked.ppid,
182 // "pid": cooked.pid, 186 "pid": cooked.pid,
183 // "children": []bson.M{}, 187 "children": []bson.M{},
184 // "execve": []bson.M{ 188 "execve": []bson.M{
185 // { 189 {
186 // "timestamp": cooked.timestamp, 190 "timestamp": cooked.timestamp,
187 // "execArgs": cooked.argv, 191 "execArgs": cooked.argv,
188 // }, 192 },
189 // }, 193 },
190 // }) 194 })
191 } 195 }
192 mongoMutex.Unlock() 196 mongoMutex.Unlock()
193} 197}
diff --git a/src/global.go b/src/global.go
index f0f909c..a266b1b 100644
--- a/src/global.go
+++ b/src/global.go
@@ -33,12 +33,13 @@ type Event struct {
33 timestamp time.Time 33 timestamp time.Time
34 pid, ppid int 34 pid, ppid int
35 syscall int 35 syscall int
36 exit_code uint64 36 syscallParam [4]uint64
37 pathName string
37 argc int 38 argc int
38 argv []string 39 argv []string
39 cwd string 40 cwd string
40 syscallParam [4]uint64 41 exit_code uint64
41 pathName string 42 exit_signal int
42} 43}
43 44
44func (event Event) String() string { 45func (event Event) String() string {
diff --git a/src/go.work b/src/go.work
new file mode 100644
index 0000000..5b6c957
--- /dev/null
+++ b/src/go.work
@@ -0,0 +1,6 @@
1go 1.21.5
2
3use (
4 ./netlink
5 ./
6) \ No newline at end of file
diff --git a/src/go.work.sum b/src/go.work.sum
new file mode 100644
index 0000000..8201e39
--- /dev/null
+++ b/src/go.work.sum
@@ -0,0 +1,4 @@
1golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
2golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
3golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
4golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
diff --git a/src/godo.go b/src/godo.go
index 0edcc9f..c332c86 100644
--- a/src/godo.go
+++ b/src/godo.go
@@ -1,11 +1,15 @@
1package main 1package main
2 2
3import ( 3import (
4 "bufio"
4 "flag" 5 "flag"
5 "fmt" 6 "fmt"
6 "log" 7 "log"
8 "netlink"
7 "os" 9 "os"
8 "os/exec" 10 "os/exec"
11 "strings"
12 "syscall"
9 "time" 13 "time"
10 14
11 "github.com/elastic/go-libaudit/v2" 15 "github.com/elastic/go-libaudit/v2"
@@ -37,7 +41,8 @@ func main() {
37 auditCmd = exec.Command("auditctl", "-D") // 清空所有规则 41 auditCmd = exec.Command("auditctl", "-D") // 清空所有规则
38 auditCmd.Run() 42 auditCmd.Run()
39 43
40 pidSyscall := []string{"fork", "vfork", "clone", "execve", "exit", "exit_group"} 44 pidSyscall := []string{"execve"}
45 // pidSyscall := []string{"fork", "vfork", "clone", "execve", "exit", "exit_group"}
41 // 设置监听规则 46 // 设置监听规则
42 for i := 0; i < len(pidSyscall); i++ { 47 for i := 0; i < len(pidSyscall); i++ {
43 auditCmd = exec.Command("auditctl", "-a", "exit,always", "-F", "arch=b64", "-S", pidSyscall[i]) 48 auditCmd = exec.Command("auditctl", "-a", "exit,always", "-F", "arch=b64", "-S", pidSyscall[i])
@@ -77,6 +82,10 @@ func coroutine(client *libaudit.AuditClient) {
77 // 各协程至此开始 82 // 各协程至此开始
78 rawChan = make(chan interface{}) 83 rawChan = make(chan interface{})
79 cookedChan = make(chan Event) 84 cookedChan = make(chan Event)
85
86 wg.Add(1)
87 go procWatch()
88
80 wg.Add(1) 89 wg.Add(1)
81 go receive(client) 90 go receive(client)
82 wg.Add(1) 91 wg.Add(1)
@@ -87,3 +96,74 @@ func coroutine(client *libaudit.AuditClient) {
87 wg.Wait() 96 wg.Wait()
88 time.Sleep(2 * time.Second) 97 time.Sleep(2 * time.Second)
89} 98}
99
100func procWatch() error {
101 ns, err := netlink.NewNetlinkSocket(syscall.NETLINK_CONNECTOR, 12345)
102 if err != nil {
103 fmt.Printf("Error creating socket: %v\n", err)
104 return err
105 }
106 defer ns.Close()
107 for {
108 res, err := ns.Receive()
109 if err != nil {
110 fmt.Printf("Error recv: %v\n", err)
111 continue
112 }
113 for i := 0; i < len(res); i++ {
114 procEvent := netlink.ParseProcEvent(res[i].Data)
115 switch procEvent.What {
116 case netlink.PROC_EVENT_FORK:
117 data := procEvent.Data.(netlink.ProcEventFork)
118 cooked := Event{
119 tag: NEWPID,
120 ppid: int(data.ParentTgid),
121 pid: int(data.ChildPid),
122 timestamp: time.Now(),
123 }
124 checkProc(&cooked)
125 if data.ChildPid != data.ChildTgid {
126 cooked.ppid = int(data.ChildTgid)
127 cooked.pid = int(data.ChildPid)
128 }
129 cookedChan <- cooked
130 case netlink.PROC_EVENT_EXIT:
131 data := procEvent.Data.(netlink.ProcEventExit)
132 cooked := Event{
133 tag: PIDEXIT,
134 timestamp: time.Now(),
135 pid: int(data.ProcessPid),
136 exit_code: uint64(data.ExitCode),
137 exit_signal: int(data.ExitSignal),
138 }
139 cookedChan <- cooked
140 default:
141 }
142 }
143 }
144}
145
146func checkProc(pCooked *Event) {
147 fileName := fmt.Sprintf("/proc/%d/cmdline", pCooked.pid)
148 fd, err := os.Open(fileName)
149 if err != nil {
150 fmt.Printf("Err opening file %s: %v\n", fileName, err)
151 return
152 }
153
154 scanner := bufio.NewScanner(fd)
155 scanner.Split(bufio.ScanLines)
156 for scanner.Scan() {
157 line := scanner.Text()
158 pCooked.argv = append(pCooked.argv, strings.Split(line, "\x00")...)
159 }
160 pCooked.argc = len(pCooked.argv)
161 fd.Close()
162
163 fileName = fmt.Sprintf("/proc/%d/cwd", pCooked.pid)
164 pCooked.cwd, err = os.Readlink(fileName)
165 if err != nil {
166 fmt.Printf("Err readlink %s: %v\n", fileName, err)
167 pCooked.cwd = ""
168 }
169}
diff --git a/src/netlink b/src/netlink
new file mode 160000
Subproject 10d3ea361f0bcafb9b92054440984d32421aeb7
diff --git a/src/organize.go b/src/organize.go
index d7a1df1..238509f 100644
--- a/src/organize.go
+++ b/src/organize.go
@@ -47,7 +47,6 @@ func orgnaze() {
47 break 47 break
48 } 48 }
49 rawEvent = raw.(libaudit.RawAuditMessage) 49 rawEvent = raw.(libaudit.RawAuditMessage)
50 fmt.Printf("type=%v msg=%s\n", rawEvent.Type, rawEvent.Data)
51 50
52 switch rawEvent.Type { 51 switch rawEvent.Type {
53 case auparse.AUDIT_SYSCALL: 52 case auparse.AUDIT_SYSCALL:
@@ -100,24 +99,6 @@ func syscallRaw(rawEvent libaudit.RawAuditMessage) {
100 } 99 }
101 100
102 switch syscallTable[event.syscall] { 101 switch syscallTable[event.syscall] {
103 case "clone":
104 if exit == 0 || event.pid > exit {
105 // exit=0是给新进程的返回,没用
106 // pid>exit,证明有问题,抛弃
107 break
108 } else {
109 eventTable.Store(eventId, &Event{
110 tag: NEWPID,
111 timestamp: event.timestamp,
112 syscall: event.syscall,
113 exit_code: 0,
114 ppid: event.pid,
115 pid: exit,
116 argc: 0,
117 argv: make([]string, 0),
118 cwd: "",
119 })
120 }
121 case "execve": 102 case "execve":
122 eventTable.Store(eventId, &Event{ 103 eventTable.Store(eventId, &Event{
123 tag: EXECVE, 104 tag: EXECVE,
@@ -130,18 +111,6 @@ func syscallRaw(rawEvent libaudit.RawAuditMessage) {
130 argv: make([]string, 0), 111 argv: make([]string, 0),
131 cwd: "", 112 cwd: "",
132 }) 113 })
133 case "exit", "exit_group":
134 eventTable.Store(eventId, &Event{
135 tag: PIDEXIT,
136 timestamp: event.timestamp,
137 syscall: event.syscall,
138 exit_code: a[0],
139 ppid: event.ppid,
140 pid: event.pid,
141 argc: 0,
142 argv: make([]string, 0),
143 cwd: "",
144 })
145 case "open": 114 case "open":
146 // 检查打开的权限 115 // 检查打开的权限
147 if a[1]&(syscall.O_APPEND|syscall.O_WRONLY|syscall.O_RDWR|syscall.O_TRUNC) == 0 { 116 if a[1]&(syscall.O_APPEND|syscall.O_WRONLY|syscall.O_RDWR|syscall.O_TRUNC) == 0 {