diff --git a/README.md b/README.md index 715c5a7..46e400f 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,7 @@ Done. Output in ./testruns/harness-results-2773792211 - `M` : Module Load/Unload - `N` : Netflow - `P` : Process Event +- `R` : Windows Registry Event - `S` : NetSniff Event - `T` : PTrace Event - `V` : Volume Activity Event diff --git a/cmd/harness/validate.go b/cmd/harness/validate.go index 32de0b7..f02773f 100644 --- a/cmd/harness/validate.go +++ b/cmd/harness/validate.go @@ -333,6 +333,48 @@ func CheckAMSIEvent(testRun *SingleTestRun, evt *types.SimpleEvent, nativeJsonSt } +func CheckRegEvent(testRun *SingleTestRun, evt *types.SimpleEvent, nativeJsonStr string) bool { + retval := false + + for _, exp := range testRun.criteria.ExpectedEvents { + if exp.EventType != "REG" { + continue + } + + numMatchingChecks := 0 + for _, fc := range exp.FieldChecks { + isMatch := false + switch fc.FieldName { + case "event_type": + isMatch = CheckMatch(evt.RegFields.EventType, fc.Op, fc.Value) + case "key_name": + isMatch = CheckMatch(evt.RegFields.KeyName, fc.Op, fc.Value) + case "value_name": + isMatch = CheckMatch(evt.RegFields.ValueName, fc.Op, fc.Value) + case "value_data": + isMatch = CheckMatch(evt.RegFields.ValueData, fc.Op, fc.Value) + default: + fmt.Println("ERROR: unknown FieldName", fc) + } + if isMatch { + if gDebug { + fmt.Printf("Field Match '%s' '%s'\n", fc.FieldName, fc.Value) + } + numMatchingChecks += 1 + } + } + if numMatchingChecks == len(exp.FieldChecks) { + AddMatchingEvent(testRun, exp, evt) + retval = true + } else if numMatchingChecks > 0 { + fmt.Printf("ONLY %d of %d FieldChecks satisfied\n%s\n", numMatchingChecks, len(exp.FieldChecks), nativeJsonStr) + } + } + + return retval + +} + func ValidateSimpleTelemetry(testRun *SingleTestRun, tool *TelemTool) { gValidateState = ExtractState{} gValidateState.StartTime = uint64(testRun.StartTime) @@ -394,6 +436,8 @@ func ValidateSimpleTelemetry(testRun *SingleTestRun, tool *TelemTool) { isMatch = CheckETWEvent(testRun, evt, rawEventStr) case types.SimpleSchemaAMSI: isMatch = CheckAMSIEvent(testRun, evt, rawEventStr) + case types.SimpleSchemaReg: + isMatch = CheckRegEvent(testRun, evt, rawEventStr) default: fmt.Println("missing handling of type", line) } @@ -508,6 +552,10 @@ func GetTelemChar(exp *types.ExpectedEvent) string { return "V" case "ETW": return "E" + case "AMSI": + return "I" + case "REG": + return "R" default: break } diff --git a/pkg/types/harness_simple_telemetry.go b/pkg/types/harness_simple_telemetry.go index 8c58130..2ebedcf 100644 --- a/pkg/types/harness_simple_telemetry.go +++ b/pkg/types/harness_simple_telemetry.go @@ -23,6 +23,7 @@ const ( SimpleSchemaDetection SimpleSchemaChar = "W" SimpleSchemaETW SimpleSchemaChar = "E" SimpleSchemaAMSI SimpleSchemaChar = "I" + SimpleSchemaReg SimpleSchemaChar = "R" ) type SimpleProcessFields struct { @@ -94,6 +95,14 @@ type SimpleAMSIFields struct { AppName string `json:"app_name,omitempty"` } +type SimpleRegFields struct { + EventType string `json:"event_type,omitempty"` // event_type: "SETVALUEKEY", "DELETEKEY", ... + Pid int64 `json:"pid,omitempty"` + KeyName string `json:"key_name,omitempty"` + ValueName string `json:"value_name,omitempty"` // if present, for SETVALUEKEY + ValueData string `json:"value_data,omitempty"` // if present, for SETVALUEKEY +} + type SimpleEvent struct { EventType SimpleSchemaChar `json:"evt_type"` Timestamp int64 `json:"ts,omitempty"` @@ -106,4 +115,5 @@ type SimpleEvent struct { NetflowFields *SimpleNetflowFields `json:"evt_netflow,omitempty"` ETWFields *SimpleETWFields `json:"evt_etw,omitempty"` AMSIFields *SimpleAMSIFields `json:"evt_amsi,omitempty"` + RegFields *SimpleRegFields `json:"evt_reg,omitempty"` }