diff options
-rw-r--r-- | src/basefunc.go | 40 | ||||
-rw-r--r-- | src/deal.go | 173 | ||||
-rw-r--r-- | src/global.go | 2 | ||||
-rw-r--r-- | src/godo.go | 18 | ||||
-rw-r--r-- | src/mongo.go | 79 | ||||
-rw-r--r-- | src/organize.go | 79 |
6 files changed, 266 insertions, 125 deletions
diff --git a/src/basefunc.go b/src/basefunc.go index 5fff3e8..2f39507 100644 --- a/src/basefunc.go +++ b/src/basefunc.go | |||
@@ -4,32 +4,46 @@ import ( | |||
4 | "bufio" | 4 | "bufio" |
5 | "fmt" | 5 | "fmt" |
6 | "os" | 6 | "os" |
7 | "os/exec" | ||
7 | "path/filepath" | 8 | "path/filepath" |
8 | "regexp" | ||
9 | "strconv" | 9 | "strconv" |
10 | "strings" | 10 | "strings" |
11 | "time" | 11 | "time" |
12 | ) | 12 | ) |
13 | 13 | ||
14 | func figureOutSyscalls() error { | 14 | func figureOutSyscalls() error { |
15 | NRRegex := regexp.MustCompile(`#define __NR_(.*?) (\d+)$`) | 15 | cmd := exec.Command("ausyscall", "--dump") |
16 | file, err := os.Open("/usr/include/asm/unistd_64.h") | 16 | stdout, err := cmd.StdoutPipe() |
17 | if err != nil { | 17 | if err != nil { |
18 | return err | 18 | return err |
19 | } | 19 | } |
20 | defer file.Close() | ||
21 | 20 | ||
22 | scanner := bufio.NewScanner(file) | 21 | if err := cmd.Start(); err != nil { |
23 | for scanner.Scan() { | 22 | return err |
23 | } | ||
24 | |||
25 | scanner := bufio.NewScanner(stdout) | ||
26 | for i := 0; scanner.Scan(); i++ { | ||
27 | if i == 0 { | ||
28 | continue | ||
29 | } | ||
24 | line := scanner.Text() | 30 | line := scanner.Text() |
25 | if NRRegex.MatchString(line) { | 31 | parts := strings.Split(line, "\t") |
26 | match := NRRegex.FindStringSubmatch(line) | 32 | if len(parts) != 2 { |
27 | num, err := strconv.Atoi(match[2]) | 33 | return fmt.Errorf("invalid ausyscall format") |
28 | if err != nil { | ||
29 | return err | ||
30 | } | ||
31 | syscallTable[num] = match[1] | ||
32 | } | 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 | ||
33 | } | 47 | } |
34 | return nil | 48 | return nil |
35 | } | 49 | } |
diff --git a/src/deal.go b/src/deal.go index 118d914..783dab8 100644 --- a/src/deal.go +++ b/src/deal.go | |||
@@ -1,51 +1,48 @@ | |||
1 | package main | 1 | package main |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "context" | ||
5 | "fmt" | 4 | "fmt" |
5 | "sync" | ||
6 | "time" | 6 | "time" |
7 | 7 | ||
8 | "go.mongodb.org/mongo-driver/bson" | 8 | "go.mongodb.org/mongo-driver/bson" |
9 | "go.mongodb.org/mongo-driver/mongo" | ||
10 | "go.mongodb.org/mongo-driver/mongo/options" | ||
11 | ) | 9 | ) |
12 | 10 | ||
13 | const ( | 11 | const ( |
14 | dbName string = "test" | 12 | dbName string = "test" |
15 | colName string = "pids" | 13 | pidColName string = "pids" |
16 | ) | 14 | ) |
17 | 15 | ||
16 | var mongoMutex sync.Mutex | ||
17 | var pidCol mongoClient | ||
18 | |||
18 | func deal() { | 19 | func deal() { |
19 | defer wg.Done() | 20 | defer wg.Done() |
20 | var cooked Event | 21 | var cooked Event |
21 | var ok bool | 22 | var ok bool |
22 | 23 | ||
23 | var err error | 24 | var err error |
24 | var mongo *mongo.Client | ||
25 | var res []bson.M | 25 | var res []bson.M |
26 | 26 | ||
27 | mongo, err = connect() | 27 | if err = pidCol.Connect(dbName, pidColName); err != nil { |
28 | if err != nil { | 28 | fmt.Printf("Error connecting the mongodb: %v\n", err) |
29 | fmt.Printf("Err connecting the mongodb: %v\n", err) | ||
30 | } | 29 | } |
31 | pidCol := mongo.Database(dbName).Collection(colName) | 30 | if err = pidCol.Drop(); err != nil { |
32 | 31 | fmt.Printf("Error drop the mongodb: %v\n", err) | |
33 | err = pidCol.Drop(context.Background()) | ||
34 | if err != nil { | ||
35 | fmt.Printf("Err drop: %v\n", err) | ||
36 | } | 32 | } |
37 | 33 | ||
38 | _, err = pidCol.InsertOne(context.Background(), bson.M{ | 34 | err = pidCol.InsertOne(bson.M{ |
39 | "ppid": 1, | 35 | "ppid": 1, |
40 | "pid": containerdPid, | 36 | "pid": containerdPid, |
41 | "cwd": "/", | 37 | "cwd": "/", |
38 | "children": bson.M{}, | ||
42 | }) | 39 | }) |
43 | if err != nil { | 40 | if err != nil { |
44 | fmt.Printf("Err containerd: %v", err) | 41 | fmt.Printf("Err containerd: %v", err) |
45 | return | 42 | return |
46 | } | 43 | } |
47 | |||
48 | fmt.Printf("Containerd: %d\n", containerdPid) | 44 | fmt.Printf("Containerd: %d\n", containerdPid) |
45 | defer pidCol.Disconnect() | ||
49 | 46 | ||
50 | for { | 47 | for { |
51 | cooked, ok = <-cookedChan | 48 | cooked, ok = <-cookedChan |
@@ -54,81 +51,115 @@ func deal() { | |||
54 | } | 51 | } |
55 | 52 | ||
56 | switch syscallTable[cooked.syscall] { | 53 | switch syscallTable[cooked.syscall] { |
57 | case "fork", "vfork", "clone": | 54 | case "clone": |
58 | // 有无父进程在观察中 | 55 | // 有无父进程在观察中 |
59 | res, err = findDocuments(mongo, "test", "pids", bson.M{"pid": cooked.ppid}) | 56 | res, err = pidCol.Finddoc(bson.M{"pid": cooked.ppid}) |
60 | if err != nil || len(res) != 1 { | 57 | if err != nil || len(res) != 1 { |
61 | break | 58 | break |
62 | } | 59 | } |
63 | 60 | ||
64 | // 自身是否已经记录 | 61 | // 自身是否已经记录 |
65 | res, err = findDocuments(mongo, "test", "pids", bson.M{"pid": cooked.pid}) | 62 | res, err = pidCol.Finddoc(bson.M{"pid": cooked.pid}) |
66 | if err != nil { | 63 | if err != nil { |
67 | fmt.Printf("Err finding: %v\n", err) | 64 | fmt.Printf("Err finding: %v\n", err) |
68 | break | 65 | break |
69 | } else if len(res) != 0 { | ||
70 | fmt.Printf("Err inserting pid %v: already in db: %v\n", cooked.pid, res) | ||
71 | break | ||
72 | } | ||
73 | |||
74 | doc := []bson.A{} | ||
75 | for _, str := range cooked.argv { | ||
76 | doc = append(doc, bson.A{str}) | ||
77 | } | 66 | } |
78 | _, err := pidCol.InsertOne(context.Background(), bson.M{ | 67 | mongoMutex.Lock() |
79 | "timestamp": cooked.timestamp, | 68 | if len(res) != 0 { |
80 | "ppid": cooked.ppid, | 69 | // 进程原本就存在,换言之别的消息先到了 |
81 | "pid": cooked.pid, | 70 | // 所有先行抵达的消息必须保留execve/children字段 |
82 | "cwd": cooked.cwd, | 71 | // 此处不再更新 |
83 | "args": doc, | 72 | // 以防把原有信息更没了 |
84 | "children": []bson.M{}, | 73 | pidCol.UpdateOne(bson.M{"pid": cooked.pid}, bson.M{ |
85 | }) | 74 | "start_timestamp": cooked.timestamp, |
86 | if err != nil { | 75 | "ppid": cooked.ppid, |
87 | fmt.Printf("Err insert: %v\n", err) | 76 | "pid": cooked.pid, |
77 | "cwd": cooked.cwd, | ||
78 | // "execve": []bson.M{}, | ||
79 | "args": cooked.argv, | ||
80 | // "children": []bson.M{}, | ||
81 | }) | ||
82 | } else { | ||
83 | // 这进程本是新修的 | ||
84 | pidCol.InsertOne(bson.M{ | ||
85 | "start_timestamp": cooked.timestamp, | ||
86 | "ppid": cooked.ppid, | ||
87 | "pid": cooked.pid, | ||
88 | "cwd": cooked.cwd, | ||
89 | "execve": []bson.M{}, | ||
90 | "args": cooked.argv, | ||
91 | "children": []bson.M{}, | ||
92 | }) | ||
88 | } | 93 | } |
89 | 94 | ||
90 | _, err = pidCol.UpdateOne(context.Background(), bson.M{"pid": cooked.pid}, bson.M{ | 95 | pidCol.UpdateOne(bson.M{"pid": cooked.ppid}, bson.M{ |
91 | "$push": bson.M{ | 96 | "$push": bson.M{ |
92 | "children": cooked.pid, | 97 | "children": cooked.pid, |
93 | }, | 98 | }, |
94 | }) | 99 | }) |
100 | mongoMutex.Unlock() | ||
101 | case "execve": | ||
102 | // 父进程在不在?不在扔 | ||
103 | res, err = pidCol.Finddoc(bson.M{"pid": cooked.ppid}) | ||
104 | if err != nil || len(res) != 1 { | ||
105 | break | ||
106 | } | ||
107 | |||
108 | // 首先检查进程是否存在,如不存在则为之创建 | ||
109 | res, err = pidCol.Finddoc(bson.M{"pid": cooked.pid}) | ||
95 | if err != nil { | 110 | if err != nil { |
96 | fmt.Printf("Err insert: %v\n", err) | 111 | break |
112 | } | ||
113 | mongoMutex.Lock() | ||
114 | if len(res) == 1 { | ||
115 | // 自身已在,直接记录 | ||
116 | pidCol.UpdateOne(bson.M{"pid": cooked.pid}, bson.M{ | ||
117 | "$push": bson.M{ | ||
118 | "execve": bson.M{ | ||
119 | "timestamp": cooked.timestamp, | ||
120 | "args": cooked.argv, | ||
121 | }, | ||
122 | }, | ||
123 | }) | ||
124 | } else { | ||
125 | // 先fork抵达,插入 | ||
126 | pidCol.InsertOne(bson.M{ | ||
127 | "children": []bson.M{}, | ||
128 | "execve": []bson.M{ | ||
129 | { | ||
130 | "timestamp": cooked.timestamp, | ||
131 | "execve": cooked.argv, | ||
132 | }, | ||
133 | }, | ||
134 | }) | ||
97 | } | 135 | } |
136 | mongoMutex.Unlock() | ||
98 | case "exit", "exit_group": | 137 | case "exit", "exit_group": |
99 | // TODO: 记得补全退出逻辑 | 138 | go deletePid(cooked) |
100 | // 上哪找exit code呢? | ||
101 | } | 139 | } |
102 | } | 140 | } |
103 | } | 141 | } |
104 | 142 | ||
105 | func connect() (*mongo.Client, error) { | 143 | func deletePid(cooked Event) { |
106 | client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:27017")) | 144 | time.Sleep(1 * time.Second) |
107 | 145 | mongoMutex.Lock() | |
108 | if err != nil { | 146 | // 先从老爹那里销户 |
109 | return nil, err | 147 | pidCol.UpdateOne(bson.M{"pid": cooked.ppid}, bson.M{ |
110 | } | 148 | "$pull": bson.M{ |
111 | 149 | "children": cooked.pid, | |
112 | ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) | 150 | }, |
113 | err = client.Connect(ctx) | 151 | }) |
114 | |||
115 | if err != nil { | ||
116 | return nil, err | ||
117 | } | ||
118 | |||
119 | return client, nil | ||
120 | } | ||
121 | |||
122 | func findDocuments(client *mongo.Client, dbName, colName string, filter bson.M) ([]bson.M, error) { | ||
123 | collection := client.Database(dbName).Collection(colName) | ||
124 | |||
125 | cur, err := collection.Find(context.Background(), filter) | ||
126 | if err != nil { | ||
127 | return nil, err | ||
128 | } | ||
129 | 152 | ||
130 | var results []bson.M | 153 | // 孩子们需要收容 |
131 | err = cur.All(context.Background(), &results) | 154 | // 不必到children里一个个找,直接看ppid即可 |
155 | pidCol.UpdateMany(bson.M{"ppid": cooked.pid}, bson.M{"ppid": 1}) | ||
132 | 156 | ||
133 | return results, err | 157 | // 可以去死了 |
158 | pidCol.UpdateOne(bson.M{"pid": cooked.pid}, bson.M{ | ||
159 | "$set": bson.M{ | ||
160 | "exit_timestamp": cooked.timestamp, | ||
161 | "exit_code": cooked.exit_code, | ||
162 | }, | ||
163 | }) | ||
164 | mongoMutex.Unlock() | ||
134 | } | 165 | } |
diff --git a/src/global.go b/src/global.go index 0439df6..c3001ab 100644 --- a/src/global.go +++ b/src/global.go | |||
@@ -9,6 +9,7 @@ type Event struct { | |||
9 | timestamp time.Time | 9 | timestamp time.Time |
10 | pid, ppid int | 10 | pid, ppid int |
11 | syscall int | 11 | syscall int |
12 | exit_code uint64 | ||
12 | argc int | 13 | argc int |
13 | argv []string | 14 | argv []string |
14 | cwd string | 15 | cwd string |
@@ -23,7 +24,6 @@ type process struct { | |||
23 | children []int | 24 | children []int |
24 | } | 25 | } |
25 | 26 | ||
26 | var pids sync.Map // 古希腊掌管进程的神,int->*process | ||
27 | var wg sync.WaitGroup // 掌管协程 | 27 | var wg sync.WaitGroup // 掌管协程 |
28 | var rawChan chan interface{} // 从接收到整理的管道 | 28 | var rawChan chan interface{} // 从接收到整理的管道 |
29 | var cookedChan chan Event // 整理好的信息的管道 | 29 | var cookedChan chan Event // 整理好的信息的管道 |
diff --git a/src/godo.go b/src/godo.go index 72f68c0..cc29a01 100644 --- a/src/godo.go +++ b/src/godo.go | |||
@@ -51,26 +51,8 @@ func main() { | |||
51 | } | 51 | } |
52 | 52 | ||
53 | // 创世之神,1号进程 | 53 | // 创世之神,1号进程 |
54 | // pids[1] = &process{rootfs: "/", children: make([]int, 0)} | ||
55 | // pids[1].children = append(pids[1].children, containerdPid) | ||
56 | // 1号进程还是不要在进程树上直接出现了,不然它的小儿子们都会出现 | 54 | // 1号进程还是不要在进程树上直接出现了,不然它的小儿子们都会出现 |
57 | |||
58 | // /usr/bin/containerd,也就是我们最关注的进程 | 55 | // /usr/bin/containerd,也就是我们最关注的进程 |
59 | // pids[containerdPid] = &process{rootfs: "/", children: make([]int, 0)} | ||
60 | pids.Store(containerdPid, &process{ | ||
61 | ppid: 1, | ||
62 | pid: containerdPid, | ||
63 | argv: make([]string, 0), | ||
64 | cwd: "/", | ||
65 | rootfs: "/", | ||
66 | children: make([]int, 0), | ||
67 | }) | ||
68 | p, ok := pids.Load(containerdPid) | ||
69 | if !ok { | ||
70 | fmt.Printf("???\n") | ||
71 | return | ||
72 | } | ||
73 | p.(*process).argv = append(p.(*process).argv, "/usr/bin/containerd") | ||
74 | 56 | ||
75 | // 开始运行,解析命令行参数后监听 | 57 | // 开始运行,解析命令行参数后监听 |
76 | if err := fs.Parse(os.Args[1:]); err != nil { | 58 | if err := fs.Parse(os.Args[1:]); err != nil { |
diff --git a/src/mongo.go b/src/mongo.go new file mode 100644 index 0000000..d00abd2 --- /dev/null +++ b/src/mongo.go | |||
@@ -0,0 +1,79 @@ | |||
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) Connect(dbName, colName string) error { | ||
19 | var err error | ||
20 | mc.client, err = mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:27017")) | ||
21 | |||
22 | if err != nil { | ||
23 | return err | ||
24 | } | ||
25 | |||
26 | ctx, _ := context.WithTimeout(context.Background(), 10*time.Second) | ||
27 | err = mc.client.Connect(ctx) | ||
28 | if err != nil { | ||
29 | return err | ||
30 | } | ||
31 | |||
32 | mc.col = mc.client.Database(dbName).Collection(colName) | ||
33 | mc.dbName = dbName | ||
34 | mc.colName = colName | ||
35 | return nil | ||
36 | } | ||
37 | |||
38 | func (mc *mongoClient) InsertOne(document interface{}) error { | ||
39 | _, err := mc.col.InsertOne(context.Background(), document) | ||
40 | return err | ||
41 | } | ||
42 | |||
43 | func (mc *mongoClient) UpdateOne(filter, update interface{}) error { | ||
44 | _, err := mc.col.UpdateOne(context.Background(), filter, update) | ||
45 | return err | ||
46 | } | ||
47 | |||
48 | func (mc *mongoClient) UpdateMany(filter, update interface{}) error { | ||
49 | _, err := mc.col.UpdateMany(context.Background(), filter, update) | ||
50 | return err | ||
51 | } | ||
52 | |||
53 | func (mc *mongoClient) Finddoc(filter bson.M) ([]bson.M, error) { | ||
54 | cur, err := mc.col.Find(context.Background(), filter) | ||
55 | if err != nil { | ||
56 | return nil, err | ||
57 | } | ||
58 | |||
59 | var results []bson.M | ||
60 | err = cur.All(context.Background(), &results) | ||
61 | |||
62 | return results, err | ||
63 | } | ||
64 | |||
65 | func (mc *mongoClient) Drop() error { | ||
66 | return mc.col.Drop(context.Background()) | ||
67 | } | ||
68 | |||
69 | func (mc *mongoClient) Disconnect() error { | ||
70 | err := mc.client.Disconnect(context.Background()) | ||
71 | if err != nil { | ||
72 | return err | ||
73 | } | ||
74 | mc.col = nil | ||
75 | mc.client = nil | ||
76 | mc.dbName = "" | ||
77 | mc.colName = "" | ||
78 | return nil | ||
79 | } | ||
diff --git a/src/organize.go b/src/organize.go index bb6736a..d963288 100644 --- a/src/organize.go +++ b/src/organize.go | |||
@@ -1,9 +1,11 @@ | |||
1 | package main | 1 | package main |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "fmt" | ||
4 | "regexp" | 5 | "regexp" |
5 | "strconv" | 6 | "strconv" |
6 | "strings" | 7 | "strings" |
8 | "sync" | ||
7 | 9 | ||
8 | "github.com/elastic/go-libaudit/v2" | 10 | "github.com/elastic/go-libaudit/v2" |
9 | "github.com/elastic/go-libaudit/v2/auparse" | 11 | "github.com/elastic/go-libaudit/v2/auparse" |
@@ -19,16 +21,20 @@ func orgnaze() { | |||
19 | // 事件信息 | 21 | // 事件信息 |
20 | var eventId, argc int | 22 | var eventId, argc int |
21 | var err [6]error | 23 | var err [6]error |
22 | var event, cooked Event | 24 | var event Event |
25 | var pEvent *Event | ||
26 | var tmp any | ||
23 | // 为每个事务id存储其信息,事务id在操作系统运行期间是唯一的 | 27 | // 为每个事务id存储其信息,事务id在操作系统运行期间是唯一的 |
24 | eventTable := make(map[int]*Event) | 28 | var eventTable sync.Map |
29 | |||
25 | // 要用的正则匹配列表 | 30 | // 要用的正则匹配列表 |
26 | syscallRegex := regexp.MustCompile(`audit\((\d+\.\d+):(\d+)\).*?syscall=(\d+).*?(exit=([-+]?\d+).*?)?ppid=(\d+) pid=(\d+).*?$`) | 31 | syscallRegex := regexp.MustCompile(`audit\((\d+\.\d+):(\d+)\).*?syscall=(\d+).*?(exit=([-+]?\d+))? a0=([0-9a-fA-F]+).*?ppid=(\d+) pid=(\d+).*?$`) |
27 | execveRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): argc=(\d+)`) | 32 | execveRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): argc=(\d+)`) |
28 | argsRegex := regexp.MustCompile(`a\d+=("(.*?)"|([0-9a-fA-F]+))`) | 33 | argsRegex := regexp.MustCompile(`a\d+=("(.*?)"|([0-9a-fA-F]+))`) |
29 | cwdRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): cwd="(.*?)"`) | 34 | cwdRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): cwd="(.*?)"`) |
30 | proctitleRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): proctitle=("(.*?)"|([0-9a-fA-F]+))$`) | 35 | proctitleRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): proctitle=("(.*?)"|([0-9a-fA-F]+))$`) |
31 | eoeRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\)`) | 36 | eoeRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\)`) |
37 | |||
32 | for { | 38 | for { |
33 | raw, ok = <-rawChan | 39 | raw, ok = <-rawChan |
34 | if !ok { | 40 | if !ok { |
@@ -44,39 +50,53 @@ func orgnaze() { | |||
44 | eventId, err[1] = strconv.Atoi(string(match[2])) | 50 | eventId, err[1] = strconv.Atoi(string(match[2])) |
45 | event.syscall, err[2] = strconv.Atoi(string(match[3])) | 51 | event.syscall, err[2] = strconv.Atoi(string(match[3])) |
46 | var exit int | 52 | var exit int |
47 | // exit, err[3] = strconv.Atoi(string(match[4])) | 53 | var a0 uint64 |
48 | if string(match[5]) == "" { | 54 | if string(match[5]) == "" { |
49 | // exit没捕获到 | 55 | // exit没捕获到 |
50 | exit = 0 | 56 | exit = 0 |
51 | } else { | 57 | } else { |
52 | exit, err[3] = strconv.Atoi(string(match[5])) | 58 | exit, err[3] = strconv.Atoi(string(match[5])) |
53 | } | 59 | } |
54 | event.ppid, err[4] = strconv.Atoi(string(match[5])) | 60 | if string(match[6]) == "" { |
55 | event.pid, err[5] = strconv.Atoi(string(match[6])) | 61 | a0 = 0 |
62 | } else { | ||
63 | // 系统调用的第一个参数 | ||
64 | // exit和exit_group都是syscall_define1,只有一个参数 | ||
65 | // fork没参数,clone几个参数不重要 | ||
66 | // execve三个参数咱也不关心 | ||
67 | // 所以看第一个就够了 | ||
68 | a0, err[4] = strconv.ParseUint(string(match[6]), 16, 64) | ||
69 | } | ||
70 | event.ppid, err[4] = strconv.Atoi(string(match[7])) | ||
71 | event.pid, err[5] = strconv.Atoi(string(match[8])) | ||
56 | if syscallTable[event.syscall] == "clone" { | 72 | if syscallTable[event.syscall] == "clone" { |
57 | if exit == 0 { | 73 | if exit == 0 || event.pid > exit { |
74 | // exit=0是给新进程的返回,没用 | ||
75 | // pid>exit,证明有问题,抛弃 | ||
58 | break | 76 | break |
59 | } else { | 77 | } else { |
60 | eventTable[eventId] = &Event{ | 78 | eventTable.Store(eventId, &Event{ |
61 | timestamp: event.timestamp, | 79 | timestamp: event.timestamp, |
62 | syscall: event.syscall, | 80 | syscall: event.syscall, |
81 | exit_code: 0, | ||
63 | ppid: event.pid, | 82 | ppid: event.pid, |
64 | pid: exit, | 83 | pid: exit, |
65 | argc: 0, | 84 | argc: 0, |
66 | argv: make([]string, 0), | 85 | argv: make([]string, 0), |
67 | cwd: "", | 86 | cwd: "", |
68 | } | 87 | }) |
69 | } | 88 | } |
70 | } else { | 89 | } else { |
71 | eventTable[eventId] = &Event{ | 90 | eventTable.Store(eventId, &Event{ |
72 | timestamp: event.timestamp, | 91 | timestamp: event.timestamp, |
73 | syscall: event.syscall, | 92 | syscall: event.syscall, |
93 | exit_code: a0, | ||
74 | ppid: event.ppid, | 94 | ppid: event.ppid, |
75 | pid: event.pid, | 95 | pid: event.pid, |
76 | argc: 0, | 96 | argc: 0, |
77 | argv: make([]string, 0), | 97 | argv: make([]string, 0), |
78 | cwd: "", | 98 | cwd: "", |
79 | } | 99 | }) |
80 | } | 100 | } |
81 | } | 101 | } |
82 | case auparse.AUDIT_EXECVE: | 102 | case auparse.AUDIT_EXECVE: |
@@ -84,34 +104,45 @@ func orgnaze() { | |||
84 | match := execveRegex.FindSubmatch(rawEvent.Data) | 104 | match := execveRegex.FindSubmatch(rawEvent.Data) |
85 | eventId, err[0] = strconv.Atoi(string(match[1])) | 105 | eventId, err[0] = strconv.Atoi(string(match[1])) |
86 | argc, err[1] = strconv.Atoi(string(match[2])) | 106 | argc, err[1] = strconv.Atoi(string(match[2])) |
107 | tmp, ok = eventTable.Load(eventId) | ||
108 | if !ok { | ||
109 | break | ||
110 | } | ||
111 | pEvent = tmp.(*Event) | ||
87 | if err[0] == nil && err[1] == nil && argsRegex.Match(rawEvent.Data) { | 112 | if err[0] == nil && err[1] == nil && argsRegex.Match(rawEvent.Data) { |
88 | match := argsRegex.FindAllSubmatch(rawEvent.Data, -1) | 113 | match := argsRegex.FindAllSubmatch(rawEvent.Data, -1) |
89 | for i := 0; i < argc; i++ { | 114 | for i := 0; i < argc; i++ { |
90 | if len(match[i][2]) == 0 { | 115 | if len(match[i][2]) == 0 { |
91 | // 代表着匹配到的是十六进制数 | 116 | // 代表着匹配到的是十六进制数 |
92 | str := hexToAscii(string(match[i][3])) | 117 | str := hexToAscii(string(match[i][3])) |
93 | eventTable[eventId].argv = append(eventTable[eventId].argv, str) | 118 | pEvent.argv = append(pEvent.argv, str) |
94 | } else { | 119 | } else { |
95 | eventTable[eventId].argv = append(eventTable[eventId].argv, string(match[i][2])) | 120 | pEvent.argv = append(pEvent.argv, string(match[i][2])) |
96 | } | 121 | } |
97 | } | 122 | } |
98 | eventTable[eventId].argc = argc | 123 | pEvent.argc = argc |
99 | } | 124 | } |
100 | } | 125 | } |
101 | // case auparse.AUDIT_PATH: | ||
102 | case auparse.AUDIT_CWD: | 126 | case auparse.AUDIT_CWD: |
103 | if cwdRegex.Match(rawEvent.Data) { | 127 | if cwdRegex.Match(rawEvent.Data) { |
104 | match := cwdRegex.FindSubmatch(rawEvent.Data) | 128 | match := cwdRegex.FindSubmatch(rawEvent.Data) |
105 | eventId, err[0] = strconv.Atoi(string(match[1])) | 129 | eventId, err[0] = strconv.Atoi(string(match[1])) |
106 | eventTable[eventId].cwd = string(match[2]) | 130 | tmp, ok = eventTable.Load(eventId) |
131 | if !ok { | ||
132 | break | ||
133 | } | ||
134 | tmp.(*Event).cwd = string(match[2]) | ||
107 | } | 135 | } |
108 | case auparse.AUDIT_PROCTITLE: | 136 | case auparse.AUDIT_PROCTITLE: |
109 | if proctitleRegex.Match(rawEvent.Data) { | 137 | if proctitleRegex.Match(rawEvent.Data) { |
110 | var cmdline string | 138 | var cmdline string |
111 | var pEvent *Event | ||
112 | match := proctitleRegex.FindSubmatch(rawEvent.Data) | 139 | match := proctitleRegex.FindSubmatch(rawEvent.Data) |
113 | eventId, err[0] = strconv.Atoi(string(match[1])) | 140 | eventId, err[0] = strconv.Atoi(string(match[1])) |
114 | pEvent = eventTable[eventId] | 141 | tmp, ok = eventTable.Load(eventId) |
142 | if !ok { | ||
143 | break | ||
144 | } | ||
145 | pEvent = tmp.(*Event) | ||
115 | if pEvent.argc == 0 { | 146 | if pEvent.argc == 0 { |
116 | // 只有等于0,才证明没经过EXECVE提取参数,才允许使用PROCTITLE提取参数 | 147 | // 只有等于0,才证明没经过EXECVE提取参数,才允许使用PROCTITLE提取参数 |
117 | if match[3] == nil { | 148 | if match[3] == nil { |
@@ -121,17 +152,21 @@ func orgnaze() { | |||
121 | cmdline = string(match[3]) | 152 | cmdline = string(match[3]) |
122 | } | 153 | } |
123 | pEvent.argv = strings.Split(cmdline, " ") | 154 | pEvent.argv = strings.Split(cmdline, " ") |
124 | pEvent.argc = len(eventTable[eventId].argv) | 155 | pEvent.argc = len(pEvent.argv) |
125 | } | 156 | } |
126 | } | 157 | } |
127 | case auparse.AUDIT_EOE: | 158 | case auparse.AUDIT_EOE: |
128 | if eoeRegex.Match(rawEvent.Data) { | 159 | if eoeRegex.Match(rawEvent.Data) { |
129 | match := eoeRegex.FindSubmatch(rawEvent.Data) | 160 | match := eoeRegex.FindSubmatch(rawEvent.Data) |
130 | eventId, err[0] = strconv.Atoi(string(match[1])) | 161 | eventId, err[0] = strconv.Atoi(string(match[1])) |
131 | // ATTENTION: 事件整理完毕,即刻发出,是否合理呢? | 162 | tmp, ok = eventTable.Load(eventId) |
132 | cooked = *eventTable[eventId] // 应当采用深拷贝吗?有待实验 | 163 | if !ok { |
164 | break | ||
165 | } | ||
166 | cooked := *(tmp.(*Event)) | ||
133 | cookedChan <- cooked | 167 | cookedChan <- cooked |
134 | delete(eventTable, eventId) //发出之后就从信息表扔掉,死人别占地 | 168 | eventTable.Delete(eventId) // 死人别占地 |
169 | fmt.Printf("%d: %3d %6d %6d\n", eventId, cooked.syscall, cooked.ppid, cooked.pid) | ||
135 | } | 170 | } |
136 | default: | 171 | default: |
137 | // ATTENTION: 这里也需要做防护 | 172 | // ATTENTION: 这里也需要做防护 |