package main import ( "regexp" "strconv" "strings" "github.com/elastic/go-libaudit/v2" "github.com/elastic/go-libaudit/v2/auparse" ) func orgnaze() { defer wg.Done() defer close(cookedChan) // 接收信息 var raw interface{} var ok bool var rawEvent libaudit.RawAuditMessage // 事件信息 var eventId, argc int var err [6]error var event, cooked Event // 为每个事务id存储其信息,事务id在操作系统运行期间是唯一的 eventTable := make(map[int]*Event) // 要用的正则匹配列表 syscallRegex := regexp.MustCompile(`audit\((\d+\.\d+):(\d+)\).*?syscall=(\d+).*?ppid=(\d+) pid=(\d+).*?$`) execveRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): argc=(\d+)`) argsRegex := regexp.MustCompile(`a\d+=("(.*?)"|([0-9a-fA-F]+))`) cwdRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): cwd="(.*?)"`) proctitleRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\): proctitle=("(.*?)"|([0-9a-fA-F]+))$`) eoeRegex := regexp.MustCompile(`audit\(\d+\.\d+:(\d+)\)`) for { raw, ok = <-rawChan if !ok { break } rawEvent = raw.(libaudit.RawAuditMessage) // type Event struct { // timestamp time.Time // pid, ppid int // syscall int // argc int // args []string // cwd string // } switch rawEvent.Type { case auparse.AUDIT_SYSCALL: if syscallRegex.Match(rawEvent.Data) { match := syscallRegex.FindSubmatch(rawEvent.Data) event.timestamp, err[0] = getTimeFromStr(string(match[1])) eventId, err[1] = strconv.Atoi(string(match[2])) event.syscall, err[2] = strconv.Atoi(string(match[3])) event.ppid, err[3] = strconv.Atoi(string(match[4])) event.pid, err[4] = strconv.Atoi(string(match[5])) eventTable[eventId] = &Event{ timestamp: event.timestamp, syscall: event.syscall, ppid: event.ppid, pid: event.pid, argc: 0, argv: make([]string, 0), cwd: "", } } case auparse.AUDIT_EXECVE: if execveRegex.Match(rawEvent.Data) { match := execveRegex.FindSubmatch(rawEvent.Data) eventId, err[0] = strconv.Atoi(string(match[1])) argc, err[1] = strconv.Atoi(string(match[2])) if err[0] == nil && err[1] == nil && argsRegex.Match(rawEvent.Data) { match := argsRegex.FindAllSubmatch(rawEvent.Data, -1) for i := 0; i < argc; i++ { if len(match[i][2]) == 0 { // 代表着匹配到的是十六进制数 str := hexToAscii(string(match[i][3])) eventTable[eventId].argv = append(eventTable[eventId].argv, str) } else { eventTable[eventId].argv = append(eventTable[eventId].argv, string(match[i][2])) } } eventTable[eventId].argc = argc } } // case auparse.AUDIT_PATH: case auparse.AUDIT_CWD: if cwdRegex.Match(rawEvent.Data) { match := cwdRegex.FindSubmatch(rawEvent.Data) eventId, err[0] = strconv.Atoi(string(match[1])) eventTable[eventId].cwd = string(match[2]) } case auparse.AUDIT_PROCTITLE: if proctitleRegex.Match(rawEvent.Data) { var cmdline string var pEvent *Event match := proctitleRegex.FindSubmatch(rawEvent.Data) eventId, err[0] = strconv.Atoi(string(match[1])) pEvent = eventTable[eventId] if pEvent.argc == 0 { // 只有等于0,才证明没经过EXECVE提取参数,才允许使用PROCTITLE提取参数 if match[3] == nil { // PROCTITLE写的是十六进制,转换为字符串 cmdline = hexToAscii(string(match[4])) } else { cmdline = string(match[3]) } pEvent.argv = strings.Split(cmdline, " ") pEvent.argc = len(eventTable[eventId].argv) } } case auparse.AUDIT_EOE: if eoeRegex.Match(rawEvent.Data) { match := eoeRegex.FindSubmatch(rawEvent.Data) eventId, err[0] = strconv.Atoi(string(match[1])) // ATTENTION: 事件整理完毕,即刻发出,是否合理呢? cooked = *eventTable[eventId] // 应当采用深拷贝吗?有待实验 cookedChan <- cooked delete(eventTable, eventId) //发出之后就从信息表扔掉,死人别占地 } default: // ATTENTION: 这里也需要做防护 } } }