diff options
author | 2024-08-01 10:15:09 +0800 | |
---|---|---|
committer | 2024-08-01 10:15:09 +0800 | |
commit | 88f080953a205c325ec80a19438236f3bb9e6d2b (patch) | |
tree | 1ede6e404f65b9383c0678fe2c5e7e17a4850064 | |
parent | ca2d881a749d3fc9f737c391ebf8b84f7d551c0d (diff) | |
download | godo-88f080953a205c325ec80a19438236f3bb9e6d2b.tar.gz godo-88f080953a205c325ec80a19438236f3bb9e6d2b.zip |
Fuck\!
-rw-r--r-- | src/connector.go | 176 | ||||
-rw-r--r-- | src/deal.go | 12 | ||||
-rw-r--r-- | src/global.go | 3 | ||||
-rw-r--r-- | src/godo.go | 29 | ||||
-rw-r--r-- | src/organize.go | 63 | ||||
-rw-r--r-- | src/procWatch.go | 86 | ||||
-rw-r--r-- | src/request.go | 57 | ||||
-rw-r--r-- | src/socket.go | 79 |
8 files changed, 457 insertions, 48 deletions
diff --git a/src/connector.go b/src/connector.go new file mode 100644 index 0000000..278dfe9 --- /dev/null +++ b/src/connector.go | |||
@@ -0,0 +1,176 @@ | |||
1 | package main | ||
2 | |||
3 | import "unsafe" | ||
4 | |||
5 | const ( | ||
6 | SizeofCnMsg = 0x14 | ||
7 | SizeofProcCnMcastOp = 0x04 | ||
8 | SizeofProcEventHeader = 0x10 | ||
9 | SizeofProcEventData = 0x18 | ||
10 | ) | ||
11 | |||
12 | const ( | ||
13 | CN_IDX_PROC = 0x1 | ||
14 | CN_VAL_PROC = 0x1 | ||
15 | ) | ||
16 | |||
17 | // linux/connector.h | ||
18 | type CbId struct { | ||
19 | idx uint32 | ||
20 | val uint32 | ||
21 | } | ||
22 | |||
23 | type CnMsg struct { | ||
24 | id CbId | ||
25 | seq uint32 | ||
26 | ack uint32 | ||
27 | len uint16 | ||
28 | flags uint16 | ||
29 | //data []uint8 | ||
30 | } | ||
31 | |||
32 | func (cm *CnMsg) Serialize() []byte { | ||
33 | return (*(*[SizeofCnMsg]byte)(unsafe.Pointer(cm)))[:] | ||
34 | } | ||
35 | |||
36 | func (cm *CnMsg) Len() int { | ||
37 | return SizeofCnMsg | ||
38 | } | ||
39 | |||
40 | func NewCnMsg() *CnMsg { | ||
41 | return &CnMsg{ | ||
42 | id: CbId{idx: CN_IDX_PROC, val: CN_VAL_PROC}, | ||
43 | seq: 0, | ||
44 | ack: 0, | ||
45 | len: SizeofProcCnMcastOp, | ||
46 | } | ||
47 | } | ||
48 | |||
49 | type ProcCnMcastOp int | ||
50 | |||
51 | const ( | ||
52 | _ ProcCnMcastOp = iota | ||
53 | PROC_CN_MCAST_LISTEN | ||
54 | PROC_CN_MCAST_IGNORE | ||
55 | ) | ||
56 | |||
57 | func (op *ProcCnMcastOp) Serialize() []byte { | ||
58 | return (*(*[SizeofProcCnMcastOp]byte)(unsafe.Pointer(op)))[:] | ||
59 | } | ||
60 | |||
61 | func (op *ProcCnMcastOp) Len() int { | ||
62 | return SizeofProcCnMcastOp | ||
63 | } | ||
64 | |||
65 | type ProcEventType uint32 | ||
66 | |||
67 | const ( | ||
68 | PROC_EVENT_NONE = 0x00000000 | ||
69 | PROC_EVENT_FORK = 0x00000001 | ||
70 | PROC_EVENT_EXEC = 0x00000002 | ||
71 | PROC_EVENT_UID = 0x00000004 | ||
72 | PROC_EVENT_GID = 0x00000040 | ||
73 | PROC_EVENT_SID = 0x00000080 | ||
74 | PROC_EVENT_PTRACE = 0x00000100 | ||
75 | PROC_EVENT_COMM = 0x00000200 | ||
76 | PROC_EVENT_COREDUMP = 0x40000000 | ||
77 | PROC_EVENT_EXIT = 0x80000000 | ||
78 | ) | ||
79 | |||
80 | type ProcEventData interface { | ||
81 | } | ||
82 | |||
83 | // linux/cn_proc.h | ||
84 | type ProcEvent struct { | ||
85 | What ProcEventType | ||
86 | Cpu uint32 | ||
87 | Timestamp uint64 | ||
88 | Data ProcEventData | ||
89 | } | ||
90 | |||
91 | type ProcEventNone struct{} | ||
92 | |||
93 | type ProcEventFork struct { | ||
94 | ParentPid int32 | ||
95 | ParentTgid int32 | ||
96 | ChildPid int32 | ||
97 | ChildTgid int32 | ||
98 | } | ||
99 | |||
100 | type ProcEventExec struct { | ||
101 | ProcessPid int32 | ||
102 | ProcessTgid int32 | ||
103 | } | ||
104 | |||
105 | type ProcEventUid struct { | ||
106 | ProcessPid int32 | ||
107 | ProcessTgid int32 | ||
108 | RUid uint32 | ||
109 | EUid uint32 | ||
110 | } | ||
111 | |||
112 | type ProcEventGid struct { | ||
113 | ProcessPid int32 | ||
114 | ProcessTgid int32 | ||
115 | RGid uint32 | ||
116 | EGid uint32 | ||
117 | } | ||
118 | |||
119 | type ProcEventExit struct { | ||
120 | ProcessPid int32 | ||
121 | ProcessTgid int32 | ||
122 | ExitCode uint32 | ||
123 | ExitSignal uint32 | ||
124 | } | ||
125 | |||
126 | type ProcEventCoreDump struct { | ||
127 | ProcessPid int32 | ||
128 | ProcessTgid int32 | ||
129 | } | ||
130 | |||
131 | type ProcEventComm struct { | ||
132 | ProcessPid int32 | ||
133 | ProcessTgid int32 | ||
134 | Comm [16]byte | ||
135 | } | ||
136 | |||
137 | type ProcEventPtrace struct { | ||
138 | ProcessPid int32 | ||
139 | ProcessTgid int32 | ||
140 | TracerPid int32 | ||
141 | TracerTgid int32 | ||
142 | } | ||
143 | |||
144 | type ProcEventSid struct { | ||
145 | ProcessPid int32 | ||
146 | ProcessTgid int32 | ||
147 | } | ||
148 | |||
149 | func ParseProcEvent(data []byte) *ProcEvent { | ||
150 | pe := (*ProcEvent)(unsafe.Pointer(&data[SizeofCnMsg])) | ||
151 | switch pe.What { | ||
152 | case PROC_EVENT_NONE: | ||
153 | pe.Data = nil | ||
154 | case PROC_EVENT_FORK: | ||
155 | pe.Data = *(*ProcEventFork)(unsafe.Pointer(&data[SizeofCnMsg+SizeofProcEventHeader])) | ||
156 | case PROC_EVENT_EXEC: | ||
157 | pe.Data = *(*ProcEventExec)(unsafe.Pointer(&data[SizeofCnMsg+SizeofProcEventHeader])) | ||
158 | case PROC_EVENT_UID: | ||
159 | pe.Data = *(*ProcEventUid)(unsafe.Pointer(&data[SizeofCnMsg+SizeofProcEventHeader])) | ||
160 | case PROC_EVENT_GID: | ||
161 | pe.Data = *(*ProcEventGid)(unsafe.Pointer(&data[SizeofCnMsg+SizeofProcEventHeader])) | ||
162 | case PROC_EVENT_SID: | ||
163 | pe.Data = *(*ProcEventSid)(unsafe.Pointer(&data[SizeofCnMsg+SizeofProcEventHeader])) | ||
164 | case PROC_EVENT_PTRACE: | ||
165 | pe.Data = *(*ProcEventPtrace)(unsafe.Pointer(&data[SizeofCnMsg+SizeofProcEventHeader])) | ||
166 | case PROC_EVENT_COMM: | ||
167 | pe.Data = *(*ProcEventComm)(unsafe.Pointer(&data[SizeofCnMsg+SizeofProcEventHeader])) | ||
168 | case PROC_EVENT_COREDUMP: | ||
169 | pe.Data = *(*ProcEventCoreDump)(unsafe.Pointer(&data[SizeofCnMsg+SizeofProcEventHeader])) | ||
170 | case PROC_EVENT_EXIT: | ||
171 | pe.Data = *(*ProcEventExit)(unsafe.Pointer(&data[SizeofCnMsg+SizeofProcEventHeader])) | ||
172 | default: | ||
173 | pe.Data = nil | ||
174 | } | ||
175 | return pe | ||
176 | } | ||
diff --git a/src/deal.go b/src/deal.go index 717344c..c50174a 100644 --- a/src/deal.go +++ b/src/deal.go | |||
@@ -2,7 +2,6 @@ package main | |||
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "fmt" | 4 | "fmt" |
5 | "sync" | ||
6 | "syscall" | 5 | "syscall" |
7 | 6 | ||
8 | "go.mongodb.org/mongo-driver/bson" | 7 | "go.mongodb.org/mongo-driver/bson" |
@@ -14,9 +13,6 @@ const ( | |||
14 | fdColName string = "fds" | 13 | fdColName string = "fds" |
15 | ) | 14 | ) |
16 | 15 | ||
17 | var mongoMutex sync.Mutex | ||
18 | var pidCol, fdCol mongoClient | ||
19 | |||
20 | var docRes []bson.M | 16 | var docRes []bson.M |
21 | var err error | 17 | var err error |
22 | 18 | ||
@@ -55,15 +51,17 @@ func deal() { | |||
55 | break | 51 | break |
56 | } | 52 | } |
57 | 53 | ||
58 | // fmt.Printf("%v\n", cooked) | 54 | fmt.Printf("recv: %v\n", cooked.tag) |
59 | 55 | ||
60 | switch cooked.tag { | 56 | switch cooked.tag { |
61 | case NEWPID: | 57 | case NEWPID: |
58 | fmt.Printf("Fork: ppid=%6d, pid=%6d\n", cooked.ppid, cooked.pid) | ||
62 | dealNewPid(cooked) | 59 | dealNewPid(cooked) |
63 | case EXECVE: | 60 | case EXECVE: |
64 | check(cooked) | 61 | check(cooked) |
65 | dealExecve(cooked) | 62 | dealExecve(cooked) |
66 | case PIDEXIT: | 63 | case PIDEXIT: |
64 | fmt.Printf("Exit: pid=%6d\n", cooked.pid) | ||
67 | check(cooked) | 65 | check(cooked) |
68 | deletePid(cooked) | 66 | deletePid(cooked) |
69 | case FILEOPEN: | 67 | case FILEOPEN: |
@@ -104,11 +102,13 @@ func deletePid(cooked Event) { | |||
104 | } | 102 | } |
105 | 103 | ||
106 | func dealNewPid(cooked Event) { | 104 | func dealNewPid(cooked Event) { |
105 | fmt.Printf("tag0 fork: %d %d\n", cooked.ppid, cooked.pid) | ||
107 | // 有无父进程在观察中 | 106 | // 有无父进程在观察中 |
108 | docRes, err = pidCol.Finddoc(bson.M{"pid": cooked.ppid}) | 107 | docRes, err = pidCol.Finddoc(bson.M{"pid": cooked.ppid}) |
109 | if err != nil || len(docRes) != 1 { | 108 | if err != nil || len(docRes) != 1 { |
110 | return | 109 | return |
111 | } | 110 | } |
111 | fmt.Printf("tag1 fork: %d %d\n", cooked.ppid, cooked.pid) | ||
112 | 112 | ||
113 | // 自身是否已经记录 | 113 | // 自身是否已经记录 |
114 | docRes, err = pidCol.Finddoc(bson.M{"pid": cooked.pid}) | 114 | docRes, err = pidCol.Finddoc(bson.M{"pid": cooked.pid}) |
@@ -117,6 +117,7 @@ func dealNewPid(cooked Event) { | |||
117 | return | 117 | return |
118 | } | 118 | } |
119 | mongoMutex.Lock() | 119 | mongoMutex.Lock() |
120 | fmt.Printf("tag2 fork: %d %d\n", cooked.ppid, cooked.pid) | ||
120 | if len(docRes) != 0 { | 121 | if len(docRes) != 0 { |
121 | // 进程原本就存在,换言之别的消息先到了 | 122 | // 进程原本就存在,换言之别的消息先到了 |
122 | // 所有先行抵达的消息必须保留execve/children字段 | 123 | // 所有先行抵达的消息必须保留execve/children字段 |
@@ -193,6 +194,7 @@ func dealExecve(cooked Event) { | |||
193 | } | 194 | } |
194 | 195 | ||
195 | func fileOpen(cooked Event) { | 196 | func fileOpen(cooked Event) { |
197 | fmt.Printf("FILEOPEN: %d %d %s\n", cooked.ppid, cooked.pid, cooked.pathName) | ||
196 | // 查看是否记录了该进程 | 198 | // 查看是否记录了该进程 |
197 | res, err := pidCol.Finddoc(bson.M{"pid": cooked.pid}) | 199 | res, err := pidCol.Finddoc(bson.M{"pid": cooked.pid}) |
198 | if err != nil { | 200 | if err != nil { |
diff --git a/src/global.go b/src/global.go index f0f909c..d9bf4d0 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 | ||
37 | argc int | 36 | argc int |
38 | argv []string | 37 | argv []string |
39 | cwd string | 38 | cwd string |
40 | syscallParam [4]uint64 | 39 | syscallParam [4]uint64 |
41 | pathName string | 40 | pathName string |
41 | exit_code uint64 | ||
42 | exit_signal int | ||
42 | } | 43 | } |
43 | 44 | ||
44 | func (event Event) String() string { | 45 | func (event Event) String() string { |
diff --git a/src/godo.go b/src/godo.go index 0edcc9f..c4d92c1 100644 --- a/src/godo.go +++ b/src/godo.go | |||
@@ -6,11 +6,14 @@ import ( | |||
6 | "log" | 6 | "log" |
7 | "os" | 7 | "os" |
8 | "os/exec" | 8 | "os/exec" |
9 | "time" | 9 | "sync" |
10 | 10 | ||
11 | "github.com/elastic/go-libaudit/v2" | 11 | "github.com/elastic/go-libaudit/v2" |
12 | ) | 12 | ) |
13 | 13 | ||
14 | var mongoMutex sync.Mutex | ||
15 | var pidCol, fdCol mongoClient | ||
16 | |||
14 | var ( | 17 | var ( |
15 | fs = flag.NewFlagSet("audit", flag.ExitOnError) | 18 | fs = flag.NewFlagSet("audit", flag.ExitOnError) |
16 | diag = fs.String("diag", "", "dump raw information from kernel to file") | 19 | diag = fs.String("diag", "", "dump raw information from kernel to file") |
@@ -37,7 +40,8 @@ func main() { | |||
37 | auditCmd = exec.Command("auditctl", "-D") // 清空所有规则 | 40 | auditCmd = exec.Command("auditctl", "-D") // 清空所有规则 |
38 | auditCmd.Run() | 41 | auditCmd.Run() |
39 | 42 | ||
40 | pidSyscall := []string{"fork", "vfork", "clone", "execve", "exit", "exit_group"} | 43 | pidSyscall := []string{"execve"} |
44 | // pidSyscall := []string{"fork", "vfork", "clone", "execve", "exit", "exit_group"} | ||
41 | // 设置监听规则 | 45 | // 设置监听规则 |
42 | for i := 0; i < len(pidSyscall); i++ { | 46 | for i := 0; i < len(pidSyscall); i++ { |
43 | auditCmd = exec.Command("auditctl", "-a", "exit,always", "-F", "arch=b64", "-S", pidSyscall[i]) | 47 | auditCmd = exec.Command("auditctl", "-a", "exit,always", "-F", "arch=b64", "-S", pidSyscall[i]) |
@@ -76,14 +80,17 @@ func main() { | |||
76 | func coroutine(client *libaudit.AuditClient) { | 80 | func coroutine(client *libaudit.AuditClient) { |
77 | // 各协程至此开始 | 81 | // 各协程至此开始 |
78 | rawChan = make(chan interface{}) | 82 | rawChan = make(chan interface{}) |
79 | cookedChan = make(chan Event) | 83 | cookedChan = make(chan Event, 1024) |
80 | wg.Add(1) | 84 | ProcWatch() |
81 | go receive(client) | 85 | // wg.Add(1) |
82 | wg.Add(1) | 86 | // go ProcWatch() |
83 | go orgnaze() | 87 | // wg.Add(1) |
84 | wg.Add(1) | 88 | // go receive(client) |
85 | go deal() | 89 | // wg.Add(1) |
90 | // go orgnaze() | ||
91 | // wg.Add(1) | ||
92 | // go deal() | ||
86 | 93 | ||
87 | wg.Wait() | 94 | // wg.Wait() |
88 | time.Sleep(2 * time.Second) | 95 | // time.Sleep(2 * time.Second) |
89 | } | 96 | } |
diff --git a/src/organize.go b/src/organize.go index d7a1df1..49796cc 100644 --- a/src/organize.go +++ b/src/organize.go | |||
@@ -47,7 +47,7 @@ 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) | 50 | // fmt.Printf("type=%v msg=%s\n", rawEvent.Type, rawEvent.Data) |
51 | 51 | ||
52 | switch rawEvent.Type { | 52 | switch rawEvent.Type { |
53 | case auparse.AUDIT_SYSCALL: | 53 | case auparse.AUDIT_SYSCALL: |
@@ -100,24 +100,24 @@ func syscallRaw(rawEvent libaudit.RawAuditMessage) { | |||
100 | } | 100 | } |
101 | 101 | ||
102 | switch syscallTable[event.syscall] { | 102 | switch syscallTable[event.syscall] { |
103 | case "clone": | 103 | // case "clone": |
104 | if exit == 0 || event.pid > exit { | 104 | // if exit == 0 || event.pid > exit { |
105 | // exit=0是给新进程的返回,没用 | 105 | // // exit=0是给新进程的返回,没用 |
106 | // pid>exit,证明有问题,抛弃 | 106 | // // pid>exit,证明有问题,抛弃 |
107 | break | 107 | // break |
108 | } else { | 108 | // } else { |
109 | eventTable.Store(eventId, &Event{ | 109 | // eventTable.Store(eventId, &Event{ |
110 | tag: NEWPID, | 110 | // tag: NEWPID, |
111 | timestamp: event.timestamp, | 111 | // timestamp: event.timestamp, |
112 | syscall: event.syscall, | 112 | // syscall: event.syscall, |
113 | exit_code: 0, | 113 | // exit_code: 0, |
114 | ppid: event.pid, | 114 | // ppid: event.pid, |
115 | pid: exit, | 115 | // pid: exit, |
116 | argc: 0, | 116 | // argc: 0, |
117 | argv: make([]string, 0), | 117 | // argv: make([]string, 0), |
118 | cwd: "", | 118 | // cwd: "", |
119 | }) | 119 | // }) |
120 | } | 120 | // } |
121 | case "execve": | 121 | case "execve": |
122 | eventTable.Store(eventId, &Event{ | 122 | eventTable.Store(eventId, &Event{ |
123 | tag: EXECVE, | 123 | tag: EXECVE, |
@@ -130,18 +130,18 @@ func syscallRaw(rawEvent libaudit.RawAuditMessage) { | |||
130 | argv: make([]string, 0), | 130 | argv: make([]string, 0), |
131 | cwd: "", | 131 | cwd: "", |
132 | }) | 132 | }) |
133 | case "exit", "exit_group": | 133 | // case "exit", "exit_group": |
134 | eventTable.Store(eventId, &Event{ | 134 | // eventTable.Store(eventId, &Event{ |
135 | tag: PIDEXIT, | 135 | // tag: PIDEXIT, |
136 | timestamp: event.timestamp, | 136 | // timestamp: event.timestamp, |
137 | syscall: event.syscall, | 137 | // syscall: event.syscall, |
138 | exit_code: a[0], | 138 | // exit_code: a[0], |
139 | ppid: event.ppid, | 139 | // ppid: event.ppid, |
140 | pid: event.pid, | 140 | // pid: event.pid, |
141 | argc: 0, | 141 | // argc: 0, |
142 | argv: make([]string, 0), | 142 | // argv: make([]string, 0), |
143 | cwd: "", | 143 | // cwd: "", |
144 | }) | 144 | // }) |
145 | case "open": | 145 | case "open": |
146 | // 检查打开的权限 | 146 | // 检查打开的权限 |
147 | if a[1]&(syscall.O_APPEND|syscall.O_WRONLY|syscall.O_RDWR|syscall.O_TRUNC) == 0 { | 147 | if a[1]&(syscall.O_APPEND|syscall.O_WRONLY|syscall.O_RDWR|syscall.O_TRUNC) == 0 { |
@@ -190,6 +190,7 @@ func syscallRaw(rawEvent libaudit.RawAuditMessage) { | |||
190 | syscallParam: a, | 190 | syscallParam: a, |
191 | // pathName: "", | 191 | // pathName: "", |
192 | }) | 192 | }) |
193 | default: | ||
193 | } | 194 | } |
194 | } | 195 | } |
195 | 196 | ||
diff --git a/src/procWatch.go b/src/procWatch.go new file mode 100644 index 0000000..34721cf --- /dev/null +++ b/src/procWatch.go | |||
@@ -0,0 +1,86 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "bufio" | ||
5 | "fmt" | ||
6 | "os" | ||
7 | "strings" | ||
8 | "syscall" | ||
9 | "time" | ||
10 | ) | ||
11 | |||
12 | func ProcWatch() error { | ||
13 | ns, err := NewNetlinkSocket(syscall.NETLINK_CONNECTOR, 12345) | ||
14 | if err != nil { | ||
15 | return err | ||
16 | } | ||
17 | defer ns.Close() | ||
18 | fmt.Printf("Proc Watch!\n") | ||
19 | for { | ||
20 | res, err := ns.Receive() | ||
21 | if err != nil { | ||
22 | continue | ||
23 | } | ||
24 | for i := 0; i < len(res); i++ { | ||
25 | procEvent := ParseProcEvent(res[i].Data) | ||
26 | switch procEvent.What { | ||
27 | case PROC_EVENT_FORK: | ||
28 | data := procEvent.Data.(ProcEventFork) | ||
29 | // if data.ChildPid != data.ChildTgid { | ||
30 | // break | ||
31 | // } | ||
32 | fmt.Printf("fork\t%6d\t%6d\t%6d\t%6d\n", data.ParentPid, data.ParentTgid, data.ChildPid, data.ChildTgid) | ||
33 | cooked := Event{ | ||
34 | tag: NEWPID, | ||
35 | timestamp: time.Now(), | ||
36 | ppid: int(data.ParentTgid), | ||
37 | pid: int(data.ChildTgid), | ||
38 | syscall: 57, | ||
39 | syscallParam: [4]uint64{}, | ||
40 | } | ||
41 | checkProc(&cooked) | ||
42 | cookedChan <- cooked | ||
43 | fmt.Printf("send fork: %d-->%d\n", cooked.ppid, cooked.pid) | ||
44 | case PROC_EVENT_EXIT: | ||
45 | data := procEvent.Data.(ProcEventExit) | ||
46 | // TODO: Event是否增加退出信号字段, 酌定 | ||
47 | if data.ProcessPid != data.ProcessTgid { | ||
48 | break | ||
49 | } | ||
50 | cooked := Event{ | ||
51 | tag: PIDEXIT, | ||
52 | timestamp: time.Now(), | ||
53 | pid: int(data.ProcessTgid), | ||
54 | exit_code: uint64(data.ExitCode), | ||
55 | exit_signal: int(data.ExitSignal), | ||
56 | } | ||
57 | cookedChan <- cooked | ||
58 | default: | ||
59 | } | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | |||
64 | // 补充args与cwd | ||
65 | func checkProc(pCooked *Event) { | ||
66 | fileName := fmt.Sprintf("/proc/%d/cmdline", pCooked.pid) | ||
67 | fd, err := os.Open(fileName) | ||
68 | if err != nil { | ||
69 | return | ||
70 | } | ||
71 | // defer fd.Close() | ||
72 | |||
73 | scanner := bufio.NewScanner(fd) | ||
74 | for scanner.Scan() { | ||
75 | line := scanner.Text() | ||
76 | pCooked.argv = append(pCooked.argv, strings.Split(line, "\x00")...) | ||
77 | } | ||
78 | pCooked.argc = len(pCooked.argv) | ||
79 | fd.Close() | ||
80 | |||
81 | fileName = fmt.Sprintf("/proc/%d/cwd", pCooked.pid) | ||
82 | pCooked.cwd, err = os.Readlink(fileName) | ||
83 | if err != nil { | ||
84 | pCooked.cwd = "" | ||
85 | } | ||
86 | } | ||
diff --git a/src/request.go b/src/request.go new file mode 100644 index 0000000..40df8df --- /dev/null +++ b/src/request.go | |||
@@ -0,0 +1,57 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "os" | ||
5 | "syscall" | ||
6 | "unsafe" | ||
7 | ) | ||
8 | |||
9 | type NetlinkRequestData interface { | ||
10 | Len() int | ||
11 | Serialize() []byte | ||
12 | } | ||
13 | |||
14 | // linux/netlink.h | ||
15 | type NetlinkRequest struct { | ||
16 | syscall.NlMsghdr | ||
17 | Data []NetlinkRequestData | ||
18 | } | ||
19 | |||
20 | func (req *NetlinkRequest) Serialize() []byte { | ||
21 | length := syscall.SizeofNlMsghdr | ||
22 | dataBytes := make([][]byte, len(req.Data)) | ||
23 | for i, data := range req.Data { | ||
24 | dataBytes[i] = data.Serialize() | ||
25 | length = length + len(dataBytes[i]) | ||
26 | } | ||
27 | req.Len = uint32(length) | ||
28 | b := make([]byte, length) | ||
29 | hdr := (*(*[syscall.SizeofNlMsghdr]byte)(unsafe.Pointer(req)))[:] | ||
30 | next := syscall.SizeofNlMsghdr | ||
31 | copy(b[0:next], hdr) | ||
32 | for _, data := range dataBytes { | ||
33 | for _, dataByte := range data { | ||
34 | b[next] = dataByte | ||
35 | next = next + 1 | ||
36 | } | ||
37 | } | ||
38 | return b | ||
39 | } | ||
40 | |||
41 | func (req *NetlinkRequest) AddData(data NetlinkRequestData) { | ||
42 | if data != nil { | ||
43 | req.Data = append(req.Data, data) | ||
44 | } | ||
45 | } | ||
46 | |||
47 | func NewNetlinkRequest() *NetlinkRequest { | ||
48 | return &NetlinkRequest{ | ||
49 | NlMsghdr: syscall.NlMsghdr{ | ||
50 | Len: uint32(0), | ||
51 | Type: uint16(syscall.NLMSG_DONE), | ||
52 | Flags: uint16(0), | ||
53 | Seq: uint32(0), | ||
54 | Pid: uint32(os.Getpid()), | ||
55 | }, | ||
56 | } | ||
57 | } | ||
diff --git a/src/socket.go b/src/socket.go new file mode 100644 index 0000000..83c7333 --- /dev/null +++ b/src/socket.go | |||
@@ -0,0 +1,79 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "os" | ||
6 | "syscall" | ||
7 | ) | ||
8 | |||
9 | type NetlinkProtocol int | ||
10 | |||
11 | const ( | ||
12 | CONNECTOR NetlinkProtocol = syscall.NETLINK_CONNECTOR | ||
13 | INET_DIAG NetlinkProtocol = syscall.NETLINK_INET_DIAG | ||
14 | ) | ||
15 | |||
16 | type NetlinkSocket struct { | ||
17 | fd int | ||
18 | protocol NetlinkProtocol | ||
19 | groups uint32 | ||
20 | } | ||
21 | |||
22 | func NewNetlinkSocket(protocol NetlinkProtocol, groups uint32) (*NetlinkSocket, error) { | ||
23 | fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, int(protocol)) | ||
24 | if err != nil { | ||
25 | return nil, err | ||
26 | } | ||
27 | ns := &NetlinkSocket{ | ||
28 | fd: fd, | ||
29 | protocol: protocol, | ||
30 | groups: groups, | ||
31 | } | ||
32 | if ns.protocol == CONNECTOR { | ||
33 | sockaddr := &syscall.SockaddrNetlink{ | ||
34 | Family: syscall.AF_NETLINK, | ||
35 | Pid: uint32(os.Getpid()), | ||
36 | Groups: groups, | ||
37 | } | ||
38 | if err = syscall.Bind(fd, sockaddr); err != nil { | ||
39 | syscall.Close(fd) | ||
40 | return nil, err | ||
41 | } | ||
42 | } | ||
43 | return ns, nil | ||
44 | } | ||
45 | |||
46 | func (ns *NetlinkSocket) Close() { | ||
47 | syscall.Close(ns.fd) | ||
48 | } | ||
49 | |||
50 | func (ns *NetlinkSocket) Send(request *NetlinkRequest) error { | ||
51 | if ns.protocol == CONNECTOR { | ||
52 | if _, err := syscall.Write(ns.fd, request.Serialize()); err != nil { | ||
53 | return err | ||
54 | } | ||
55 | } else { | ||
56 | sockaddr := &syscall.SockaddrNetlink{ | ||
57 | Family: syscall.AF_NETLINK, | ||
58 | Pid: 0, | ||
59 | Groups: ns.groups, | ||
60 | } | ||
61 | if err := syscall.Sendto(ns.fd, request.Serialize(), 0, sockaddr); err != nil { | ||
62 | return err | ||
63 | } | ||
64 | } | ||
65 | return nil | ||
66 | } | ||
67 | |||
68 | func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, error) { | ||
69 | rb := make([]byte, syscall.Getpagesize()) | ||
70 | nr, _, err := syscall.Recvfrom(s.fd, rb, 0) | ||
71 | if err != nil { | ||
72 | return nil, err | ||
73 | } | ||
74 | if nr < syscall.NLMSG_HDRLEN { | ||
75 | return nil, fmt.Errorf("Got short response from netlink") | ||
76 | } | ||
77 | rb = rb[:nr] | ||
78 | return syscall.ParseNetlinkMessage(rb) | ||
79 | } | ||