Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cmd/extract_windows.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build windows
// +build windows

package main
Expand Down Expand Up @@ -160,7 +161,7 @@ func doExtract() {
}
defer fd.Close()

fmt.Printf("Openning message table file %v\n", message_table)
fmt.Printf("Opening message table file %v\n", message_table)

reader, err := reader.NewPagedReader(fd, 4096, 100)
if err != nil {
Expand Down
7 changes: 7 additions & 0 deletions cmd/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ var (
parse_file_message_file = parse.Flag("messagedb", "Path to messages database.").
String()

parse_file_disable_message = parse.Flag("disable_messages", "Disable message resolver.").
Bool()

start_record_id = parse.Flag("start", "First EventID to dump").Int()
number_of_records = parse.Flag("number", "How many records to print").
Default("99999999").Int()
Expand Down Expand Up @@ -78,6 +81,10 @@ func (self *parsingContext) Parse() {
}

func NewParsingContext() *parsingContext {
if *parse_file_disable_message {
return &parsingContext{evtx.NullResolver{}}
}

if *parse_file_message_file != "" {
resolver, err := evtx.NewDBResolver(*parse_file_message_file)
kingpin.FatalIfError(err, " %v", err)
Expand Down
2 changes: 2 additions & 0 deletions debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ func debug(format string, args ...interface{}) {
fmt.Printf(format, args...)
}
}

func DlvBreak() {}
24 changes: 19 additions & 5 deletions evtx.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ type EVTXHeader struct {
MinorVersion uint16
MajorVersion uint16
HeaderBlockSize uint16
ChunkCount uint16
_ [76]byte
FileFlags uint32
CheckSum uint32
Expand Down Expand Up @@ -619,6 +620,7 @@ func ReadPrefixedUnicodeString(ctx *ParseContext, is_null_terminated bool) strin
buffer := ctx.ConsumeBytes(count * 2)
result := UTF16LEToUTF8(buffer)
debug("ReadPrefixedUnicodeString exit: %x %s\n", ctx.Offset(), string(result))

return string(result)
}

Expand Down Expand Up @@ -648,15 +650,16 @@ func ParseOpenStartElement(ctx *ParseContext,
debug("ParseOpenStartElement Enter: %x\n", ctx.Offset())
/*
dependencyID := ctx.ConsumeUint16()
elementLength := ctx.ConsumeUint32()
*/
// ctx.SkipBytes(2 + 4)

if template_instance {
ctx.SkipBytes(2)
}

ctx.SkipBytes(4)
elementLength := ctx.ConsumeUint32()
debug("ParseOpenStartElement elementLength: %x\n", elementLength)

nameBuffer := ReadName(ctx)

attributeListLength := uint32(0)
Expand Down Expand Up @@ -732,7 +735,8 @@ func ParseTemplateInstance(ctx *ParseContext) bool {
/*
tempResLen := ctx.ConsumeUint32()
*/
ctx.SkipBytes(4)
template_definition_data := int(ctx.ConsumeUint32())
debug("ParseTemplateInstance template_definition_data %x\n", template_definition_data)

// Template arguments should not be unreasonable here. Just cap
// them at a reasonable size.
Expand All @@ -745,7 +749,7 @@ func ParseTemplateInstance(ctx *ParseContext) bool {

template, pres := ctx.GetTemplateByID(short_id)
if !pres {
// longID := ctx.ConsumeBytes(16)
// longGUID := ctx.ConsumeBytes(16)
ctx.SkipBytes(16)
templateBodyLen := int(ctx.ConsumeUint32())

Expand Down Expand Up @@ -847,9 +851,18 @@ func ParseTemplateInstance(ctx *ParseContext) bool {
str += fmt.Sprintf("-%d", ctx.ConsumeUint32())
}
arg_values[idx] = str

case 0x21: // BinXml
new_ctx := ctx.Copy()
ParseBinXML(new_ctx, TemplateContext)

// Substitution args are not encoded in template context.
/*
https://github.com/libyal/libevtx/blob/main/documentation/Windows%20XML%20Event%20Log%20(EVTX).asciidoc#token_types
> According to [MS-EVEN6] the dependency identifier is not present
> when the element start is used in a substitution token with value
> type: Binary XML (0x21).
*/
ParseBinXML(new_ctx, !TemplateContext)
ctx.SkipBytes(arg.argLen)

arg_values[idx] = new_ctx.CurrentTemplate().Expand(nil)
Expand Down Expand Up @@ -943,6 +956,7 @@ func ParseBinXML(ctx *ParseContext, template_context bool) {
case 0x0B /* PIDataToken */ :
case 0x0C /* TemplateInstanceToken */ :
keep_going = ParseTemplateInstance(ctx)

case 0x0D /* NormalSubstitutionToken */, 0x0E: /* OptionalSubstitutionToken */
keep_going = ParseOptionalSubstitution(ctx)

Expand Down
56 changes: 56 additions & 0 deletions fixtures/CAPI2_Operational.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"System": {
"Provider": {
"Name": "Microsoft-Windows-CAPI2",
"Guid": "{5bbca4a8-b209-48dc-a8c7-b23d3e5216fb}"
},
"EventID": {
"Value": 70
},
"Version": 0,
"Level": 4,
"Task": 70,
"Opcode": 0,
"Keywords": 4611686018427388032,
"TimeCreated": {
"SystemTime": 1751191789.1541903
},
"EventRecordID": 707,
"Correlation": {
"ActivityID": "0E2A62B5-0688-42DE-9AE1-A2AD54A8CE40"
},
"Execution": {
"ProcessID": 23708,
"ThreadID": 17980
},
"Channel": "Microsoft-Windows-CAPI2/Operational",
"Computer": "ILDHBZJST3",
"Security": {
"UserID": "S-1-5-21-1332095402-2705258134-1427695613-1001"
}
},
"UserData": {
"CryptAcquireCertificatePrivateKey": {
"Certificate": {
"fileRef": "3AA55F503B946700761B3990B569E6F248C3D31D.cer",
"subjectName": "5ae3f7e8-6eef-4e9e-8fc9-94f5d0c0862b"
},
"Flags": {
"value": "10040",
"CRYPT_ACQUIRE_SILENT_FLAG": "true",
"CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG": "true"
},
"EventAuxInfo": {
"ProcessName": "RuntimeBroker.exe"
},
"CorrelationAuxInfo": {
"TaskId": "{59A34F27-7A62-4C7D-9DE1-9E1F0E2382D5}",
"SeqNumber": "2"
},
"Result": {
"value": "0"
}
}
},
"Message": ""
}
16 changes: 16 additions & 0 deletions parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,22 @@ func (self *EVTXTestSuite) TestCollector() {
goldie.Assert(self.T(), fixture_name, out)
}

func (self *EVTXTestSuite) TestTemplates() {
cmdline := []string{
"parse", "testdata/Microsoft-Windows-CAPI2_Operational_EventID70.evtx",
"--disable_messages",
}
cmd := exec.Command(self.binary, cmdline...)
out, err := cmd.CombinedOutput()
assert.NoError(self.T(), err)

out = bytes.ReplaceAll(out, []byte{'\r', '\n'}, []byte{'\n'})
fixture_name := "CAPI2_Operational"
fmt.Printf("Testing fixture %v\n", fixture_name)

goldie.Assert(self.T(), fixture_name, out)
}

func TestEvtx(t *testing.T) {
suite.Run(t, &EVTXTestSuite{})
}
Binary file not shown.