summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorWe-unite <3205135446@qq.com>2024-07-19 17:02:11 +0800
committerWe-unite <3205135446@qq.com>2024-07-19 17:05:29 +0800
commit7cf8e470471d30fc821a8be350dcb97dc64e5add (patch)
treee747afbc698bba079047f17674eef260a4c6733d /src
parent2e37dcf708be08dff963ee08cb7a9557f32e690d (diff)
downloadgodo-7cf8e470471d30fc821a8be350dcb97dc64e5add.tar.gz
godo-7cf8e470471d30fc821a8be350dcb97dc64e5add.zip
Depart the whole program into several files.
Put all the src code in only one file is to ugly, so devide it! and mv them into src dir to keep the whole repo clear.
Diffstat (limited to 'src')
-rw-r--r--src/audit.go84
-rw-r--r--src/basefunc.go115
-rw-r--r--src/deal.go97
-rw-r--r--src/global.go10
-rw-r--r--src/go.mod16
-rw-r--r--src/go.sum59
-rw-r--r--src/godo.go116
-rw-r--r--src/organize.go124
-rw-r--r--src/receive.go29
9 files changed, 650 insertions, 0 deletions
diff --git a/src/audit.go b/src/audit.go
new file mode 100644
index 0000000..ed48691
--- /dev/null
+++ b/src/audit.go
@@ -0,0 +1,84 @@
1package main
2
3import (
4 "fmt"
5 "io"
6 "log"
7 "os"
8
9 "github.com/elastic/go-libaudit/v2"
10)
11
12func 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
new file mode 100644
index 0000000..5fff3e8
--- /dev/null
+++ b/src/basefunc.go
@@ -0,0 +1,115 @@
1package main
2
3import (
4 "bufio"
5 "fmt"
6 "os"
7 "path/filepath"
8 "regexp"
9 "strconv"
10 "strings"
11 "time"
12)
13
14func figureOutSyscalls() error {
15 NRRegex := regexp.MustCompile(`#define __NR_(.*?) (\d+)$`)
16 file, err := os.Open("/usr/include/asm/unistd_64.h")
17 if err != nil {
18 return err
19 }
20 defer file.Close()
21
22 scanner := bufio.NewScanner(file)
23 for scanner.Scan() {
24 line := scanner.Text()
25 if NRRegex.MatchString(line) {
26 match := NRRegex.FindStringSubmatch(line)
27 num, err := strconv.Atoi(match[2])
28 if err != nil {
29 return err
30 }
31 syscallTable[num] = match[1]
32 }
33 }
34 return nil
35}
36
37func getPid() (int, error) {
38 // 指定要搜索的关键词
39 keyword := "/usr/bin/containerd"
40
41 // 获取/proc目录下的所有子目录
42 procDir, err := filepath.Glob("/proc/*")
43 if err != nil {
44 return 0, err
45 }
46
47 // 遍历子目录,查找包含关键词的进程
48 for _, dir := range procDir {
49 pid, err := strconv.Atoi(filepath.Base(dir))
50 if err != nil {
51 continue // 跳过非PID的目录
52 }
53
54 // 检查进程是否包含关键词
55 if containsKeyword(pid, keyword) {
56 return pid, nil
57 }
58 }
59 err = fmt.Errorf("Error: no containerd process found.")
60 return 0, err
61}
62
63func containsKeyword(pid int, keyword string) bool {
64 // 构造完整的进程命令路径
65 cmdPath := fmt.Sprintf("/proc/%d/cmdline", pid)
66
67 // 打开文件
68 file, err := os.Open(cmdPath)
69 if err != nil {
70 return false
71 }
72 defer file.Close()
73
74 // 读取文件内容
75 scanner := bufio.NewScanner(file)
76 scanner.Split(bufio.ScanLines)
77 for scanner.Scan() {
78 line := scanner.Text()
79 if strings.Contains(line, keyword) {
80 return true
81 }
82 }
83 return false
84}
85
86func getTimeFromStr(timeStr string) (time.Time, error) {
87 timestampFloat, err := strconv.ParseFloat(timeStr, 64)
88 if err != nil {
89 return time.Unix(0, 0), err
90 }
91 secs := int64(timestampFloat)
92 nsecs := int64((timestampFloat - float64(secs)) * 1e9)
93
94 // 只精确到毫秒就够了
95 t := time.Unix(secs, nsecs).Truncate(time.Millisecond)
96 return t, nil
97}
98
99func hexToAscii(hexString string) string {
100 bytes := []byte{}
101 for i := 0; i < len(hexString); i += 2 {
102 hexPair := hexString[i : i+2]
103 // 将十六进制数转换为十进制数
104 decimal, err := strconv.ParseInt(hexPair, 16, 8)
105 if err != nil {
106 return "Invalid hex string"
107 }
108 char := byte(decimal)
109 bytes = append(bytes, char)
110 }
111
112 asciiString := strings.ReplaceAll(string(bytes), "\000", " ")
113
114 return asciiString
115}
diff --git a/src/deal.go b/src/deal.go
new file mode 100644
index 0000000..fd9f788
--- /dev/null
+++ b/src/deal.go
@@ -0,0 +1,97 @@
1package main
2
3import (
4 "fmt"
5 "time"
6)
7
8func deal() {
9 defer wg.Done()
10 var cooked Event
11 var ok bool
12 for {
13 cooked, ok = <-cookedChan
14 if !ok {
15 break
16 }
17 // type Event struct {
18 // timestamp time.Time
19 // pid, ppid int
20 // syscall int
21 // argc int
22 // args []string
23 // cwd string
24 // }
25 // type process struct {
26 // timestamp time.Time
27 // pid, ppid int
28 // argv []string
29 // cwd string
30 // rootfs string
31 // children []int
32 // }
33 switch syscallTable[cooked.syscall] {
34 case "fork", "vfork", "clone":
35 ppid := cooked.ppid
36 pid := cooked.pid
37 parent, ok := pids.Load(ppid)
38 if !ok {
39 break
40 }
41 parent.(*process).children = append(parent.(*process).children, pid)
42 pids.Store(pid, &process{
43 timestamp: cooked.timestamp,
44 pid: cooked.pid,
45 ppid: cooked.ppid,
46 argv: cooked.argv,
47 cwd: cooked.cwd,
48 children: make([]int, 0),
49 })
50 fmt.Printf("%v syscall=%d, ppid=%d, pid=%d, cwd=\"%s\", argc=%d, ", cooked.timestamp, cooked.syscall, cooked.ppid, cooked.pid, cooked.cwd, cooked.argc)
51 for i := 0; i < cooked.argc; i++ {
52 fmt.Printf("arg[%d]=\"%s\", ", i, cooked.argv[i])
53 }
54 fmt.Printf("\n")
55 case "exit", "exit_group":
56 _, ok := pids.Load(cooked.pid)
57 if !ok {
58 break
59 }
60 go deletePid(cooked)
61 }
62 }
63}
64
65func deletePid(cooked Event) {
66 time.Sleep(1 * time.Second)
67 Process, ok := pids.Load(cooked.pid)
68 if !ok {
69 return
70 }
71 pProcess := Process.(*process)
72
73 // 先从爹那里注销户籍
74 parent, ok := pids.Load(pProcess.ppid)
75 if ok {
76 pParent := parent.(*process)
77 for i, child := range pParent.children {
78 if child == pProcess.pid {
79 pParent.children = append(pParent.children[:i], pParent.children[i+1:]...)
80 break
81 }
82 }
83 }
84
85 // 子进程需要收容
86 for i := 0; i < len(pProcess.children); i++ {
87 child, ok := pids.Load(pProcess.children[i])
88 if ok {
89 child.(*process).ppid = 1
90 }
91 }
92
93 // 可以去死了
94 pids.Delete(cooked.pid)
95 _, ok = pids.Load(cooked.pid)
96 fmt.Printf("%v Goodbye, %d! ok = %v\n", time.Now(), cooked.pid, ok)
97}
diff --git a/src/global.go b/src/global.go
new file mode 100644
index 0000000..4e08866
--- /dev/null
+++ b/src/global.go
@@ -0,0 +1,10 @@
1package main
2
3import "sync"
4
5var pids sync.Map // 古希腊掌管进程的神,int->*process
6var wg sync.WaitGroup // 掌管协程
7var rawChan chan interface{} // 从接收到整理的管道
8var cookedChan chan Event // 整理好的信息的管道
9var syscallTable [500]string //记录一下系统调用
10var containerdPid int
diff --git a/src/go.mod b/src/go.mod
new file mode 100644
index 0000000..2969b32
--- /dev/null
+++ b/src/go.mod
@@ -0,0 +1,16 @@
1module godo
2
3go 1.21.5
4
5require (
6 github.com/elastic/go-libaudit/v2 v2.5.0
7 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
8 gopkg.in/yaml.v3 v3.0.1
9)
10
11require (
12 go.uber.org/atomic v1.7.0 // indirect
13 go.uber.org/multierr v1.7.0 // indirect
14 golang.org/x/sys v0.11.0 // indirect
15 gopkg.in/yaml.v2 v2.4.0 // indirect
16)
diff --git a/src/go.sum b/src/go.sum
new file mode 100644
index 0000000..7ce498a
--- /dev/null
+++ b/src/go.sum
@@ -0,0 +1,59 @@
1github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
3github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4github.com/elastic/go-libaudit/v2 v2.5.0 h1:5OK919QRnGtcjVBz3n/cs5F42im1mPlVTA9TyIn2K54=
5github.com/elastic/go-libaudit/v2 v2.5.0/go.mod h1:AjlnhinP+kKQuUJoXLVrqxBM8uyhQmkzoV6jjsCFP4Q=
6github.com/elastic/go-licenser v0.4.1 h1:1xDURsc8pL5zYT9R29425J3vkHdt4RT5TNEMeRN48x4=
7github.com/elastic/go-licenser v0.4.1/go.mod h1:V56wHMpmdURfibNBggaSBfqgPxyT1Tldns1i87iTEvU=
8github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
9github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
10github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
11github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
12github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
13github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
14github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
15github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
16github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
17github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
18github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
19go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
20go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
21go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec=
22go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
23golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
24golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
25golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
26golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
27golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
28golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
29golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
30golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
31golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
32golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
33golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
34golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
35golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
36golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
37golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
38golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
39golang.org/x/sys v0.0.0-20211102192858-4dd72447c267/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
40golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
41golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
42golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
43golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
44golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
45golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
46golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
47golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
48golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
49golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
50golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
51golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
52gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
53gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
54gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
55gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
56gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
57gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
58gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
59gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/src/godo.go b/src/godo.go
new file mode 100644
index 0000000..6f73893
--- /dev/null
+++ b/src/godo.go
@@ -0,0 +1,116 @@
1package main
2
3import (
4 "flag"
5 "fmt"
6 "log"
7 "os"
8 "os/exec"
9 "time"
10
11 "github.com/elastic/go-libaudit/v2"
12)
13
14var (
15 fs = flag.NewFlagSet("audit", flag.ExitOnError)
16 diag = fs.String("diag", "", "dump raw information from kernel to file")
17 rate = fs.Uint("rate", 0, "rate limit in kernel (default 0, no rate limit)")
18 backlog = fs.Uint("backlog", 8192, "backlog limit")
19 immutable = fs.Bool("immutable", false, "make kernel audit settings immutable (requires reboot to undo)")
20 receiveOnly = fs.Bool("ro", false, "receive only using multicast, requires kernel 3.16+")
21)
22
23type Event struct {
24 timestamp time.Time
25 pid, ppid int
26 syscall int
27 argc int
28 argv []string
29 cwd string
30}
31
32type process struct {
33 timestamp time.Time
34 pid, ppid int
35 argv []string
36 cwd string
37 rootfs string
38 children []int
39}
40
41func main() {
42 // 检查用户身份,并添加auditd规则,监听所有syscall
43 if os.Geteuid() != 0 {
44 fmt.Printf("Err: Please run me as root, %d!\n", os.Getegid())
45 return
46 }
47
48 // 所有的系统调用号与名称的关系
49 err := figureOutSyscalls()
50 if err != nil {
51 fmt.Printf("Error figuring out syscall numbers: %v\n", err)
52 }
53
54 syscall := [6]string{"fork", "vfork", "clone", "execve", "exit", "exit_group"}
55 var auditCmd *exec.Cmd
56 auditCmd = exec.Command("auditctl", "-D") // 清空所有规则
57 auditCmd.Run()
58 // 设置监听规则
59 for i := 0; i < len(syscall); i++ {
60 auditCmd = exec.Command("auditctl", "-a", "exit,always", "-F", "arch=b64", "-S", syscall[i])
61 auditCmd.Run()
62 }
63
64 // 查找pid
65 containerdPid, err = getPid()
66 if err != nil {
67 fmt.Printf("Error finding containerd: %v\n", err)
68 return
69 }
70
71 // 创世之神,1号进程
72 // pids[1] = &process{rootfs: "/", children: make([]int, 0)}
73 // pids[1].children = append(pids[1].children, containerdPid)
74 // 1号进程还是不要在进程树上直接出现了,不然它的小儿子们都会出现
75
76 // /usr/bin/containerd,也就是我们最关注的进程
77 // pids[containerdPid] = &process{rootfs: "/", children: make([]int, 0)}
78 pids.Store(containerdPid, &process{
79 ppid: 1,
80 pid: containerdPid,
81 argv: make([]string, 0),
82 cwd: "/",
83 rootfs: "/",
84 children: make([]int, 0),
85 })
86 p, ok := pids.Load(containerdPid)
87 if !ok {
88 fmt.Printf("???\n")
89 return
90 }
91 p.(*process).argv = append(p.(*process).argv, "/usr/bin/containerd")
92
93 // 开始运行,解析命令行参数后监听
94 if err := fs.Parse(os.Args[1:]); err != nil {
95 log.Fatal(err)
96 }
97
98 if err := read(); err != nil {
99 log.Fatalf("error: %v", err)
100 }
101}
102
103func coroutine(client *libaudit.AuditClient) {
104 // 各协程至此开始
105 rawChan = make(chan interface{})
106 cookedChan = make(chan Event)
107 wg.Add(1)
108 go receive(client)
109 wg.Add(1)
110 go orgnaze()
111 wg.Add(1)
112 go deal()
113
114 wg.Wait()
115 time.Sleep(2 * time.Second)
116}
diff --git a/src/organize.go b/src/organize.go
new file mode 100644
index 0000000..025d8c0
--- /dev/null
+++ b/src/organize.go
@@ -0,0 +1,124 @@
1package main
2
3import (
4 "regexp"
5 "strconv"
6 "strings"
7
8 "github.com/elastic/go-libaudit/v2"
9 "github.com/elastic/go-libaudit/v2/auparse"
10)
11
12func orgnaze() {
13 defer wg.Done()
14 defer close(cookedChan)
15 // 接收信息
16 var raw interface{}
17 var ok bool
18 var rawEvent libaudit.RawAuditMessage
19 // 事件信息
20 var eventId, argc int
21 var err [6]error
22 var event, cooked Event
23 // 为每个事务id存储其信息,事务id在操作系统运行期间是唯一的
24 eventTable := make(map[int]*Event)
25 // 要用的正则匹配列表
26 syscallRegex := regexp.MustCompile(`audit\((\d+\.\d+):(\d+)\).*?syscall=(\d+).*?ppid=(\d+) pid=(\d+).*?$`)
27 execveRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): argc=(\d+)`)
28 argsRegex := regexp.MustCompile(`a\d+=("(.*?)"|([0-9a-fA-F]+))`)
29 cwdRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): cwd="(.*?)"`)
30 proctitleRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): proctitle=("(.*?)"|([0-9a-fA-F]+))$`)
31 eoeRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\)`)
32 for {
33 raw, ok = <-rawChan
34 if !ok {
35 break
36 }
37 rawEvent = raw.(libaudit.RawAuditMessage)
38
39 // type Event struct {
40 // timestamp time.Time
41 // pid, ppid int
42 // syscall int
43 // argc int
44 // args []string
45 // cwd string
46 // }
47 switch rawEvent.Type {
48 case auparse.AUDIT_SYSCALL:
49 if syscallRegex.Match(rawEvent.Data) {
50 match := syscallRegex.FindSubmatch(rawEvent.Data)
51 event.timestamp, err[0] = getTimeFromStr(string(match[1]))
52 eventId, err[1] = strconv.Atoi(string(match[2]))
53 event.syscall, err[2] = strconv.Atoi(string(match[3]))
54 event.ppid, err[3] = strconv.Atoi(string(match[4]))
55 event.pid, err[4] = strconv.Atoi(string(match[5]))
56 eventTable[eventId] = &Event{
57 timestamp: event.timestamp,
58 syscall: event.syscall,
59 ppid: event.ppid,
60 pid: event.pid,
61 argc: 0,
62 argv: make([]string, 0),
63 cwd: "",
64 }
65 }
66 case auparse.AUDIT_EXECVE:
67 if execveRegex.Match(rawEvent.Data) {
68 match := execveRegex.FindSubmatch(rawEvent.Data)
69 eventId, err[0] = strconv.Atoi(string(match[1]))
70 argc, err[1] = strconv.Atoi(string(match[2]))
71 if err[0] == nil && err[1] == nil && argsRegex.Match(rawEvent.Data) {
72 match := argsRegex.FindAllSubmatch(rawEvent.Data, -1)
73 for i := 0; i < argc; i++ {
74 if len(match[i][2]) == 0 {
75 // 代表着匹配到的是十六进制数
76 str := hexToAscii(string(match[i][3]))
77 eventTable[eventId].argv = append(eventTable[eventId].argv, str)
78 } else {
79 eventTable[eventId].argv = append(eventTable[eventId].argv, string(match[i][2]))
80 }
81 }
82 eventTable[eventId].argc = argc
83 }
84 }
85 // case auparse.AUDIT_PATH:
86 case auparse.AUDIT_CWD:
87 if cwdRegex.Match(rawEvent.Data) {
88 match := cwdRegex.FindSubmatch(rawEvent.Data)
89 eventId, err[0] = strconv.Atoi(string(match[1]))
90 eventTable[eventId].cwd = string(match[2])
91 }
92 case auparse.AUDIT_PROCTITLE:
93 if proctitleRegex.Match(rawEvent.Data) {
94 var cmdline string
95 var pEvent *Event
96 match := proctitleRegex.FindSubmatch(rawEvent.Data)
97 eventId, err[0] = strconv.Atoi(string(match[1]))
98 pEvent = eventTable[eventId]
99 if pEvent.argc == 0 {
100 // 只有等于0,才证明没经过EXECVE提取参数,才允许使用PROCTITLE提取参数
101 if match[3] == nil {
102 // PROCTITLE写的是十六进制,转换为字符串
103 cmdline = hexToAscii(string(match[4]))
104 } else {
105 cmdline = string(match[3])
106 }
107 pEvent.argv = strings.Split(cmdline, " ")
108 pEvent.argc = len(eventTable[eventId].argv)
109 }
110 }
111 case auparse.AUDIT_EOE:
112 if eoeRegex.Match(rawEvent.Data) {
113 match := eoeRegex.FindSubmatch(rawEvent.Data)
114 eventId, err[0] = strconv.Atoi(string(match[1]))
115 // ATTENTION: 事件整理完毕,即刻发出,是否合理呢?
116 cooked = *eventTable[eventId] // 应当采用深拷贝吗?有待实验
117 cookedChan <- cooked
118 delete(eventTable, eventId) //发出之后就从信息表扔掉,死人别占地
119 }
120 default:
121 // ATTENTION: 这里也需要做防护
122 }
123 }
124}
diff --git a/src/receive.go b/src/receive.go
new file mode 100644
index 0000000..c0dea00
--- /dev/null
+++ b/src/receive.go
@@ -0,0 +1,29 @@
1package main
2
3import (
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
11func 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}