diff --git a/pkg/event/event_windows.go b/pkg/event/event_windows.go
index b4f1ee6a0..7c1d21bfc 100644
--- a/pkg/event/event_windows.go
+++ b/pkg/event/event_windows.go
@@ -48,13 +48,13 @@ var (
// New constructs a fresh event instance with basic fields and parameters
// from the raw ETW event record.
-func New(seq uint64, evt *etw.EventRecord) *Event {
+func New(seq uint64, r *etw.EventRecord) *Event {
var (
- pid = evt.Header.ProcessID
- tid = evt.Header.ThreadID
- cpu = *(*uint8)(unsafe.Pointer(&evt.BufferContext.ProcessorIndex[0]))
- ts = filetime.ToEpoch(evt.Header.Timestamp)
- typ = NewTypeFromEventRecord(evt)
+ pid = r.Header.ProcessID
+ tid = r.Header.ThreadID
+ cpu = *(*uint8)(unsafe.Pointer(&r.BufferContext.ProcessorIndex[0]))
+ ts = filetime.ToEpoch(r.Header.Timestamp)
+ typ = NewTypeFromEventRecord(r)
)
e := &Event{
@@ -70,7 +70,7 @@ func New(seq uint64, evt *etw.EventRecord) *Event {
Host: hostname.Get(),
}
- e.produceParams(evt)
+ e.decodeParams(r)
e.adjustPID()
return e
diff --git a/pkg/event/param.go b/pkg/event/param.go
index a7d21ce20..58f003865 100644
--- a/pkg/event/param.go
+++ b/pkg/event/param.go
@@ -406,6 +406,16 @@ func (pars Params) GetUint16(name string) (uint16, error) {
return v, nil
}
+// MustGetUint8 returns the underlying uint8 value parameter. It panics if
+// an error occurs while trying to get the parameter.
+func (pars Params) MustGetUint8(name string) uint8 {
+ v, err := pars.GetUint8(name)
+ if err != nil {
+ panic(err)
+ }
+ return v
+}
+
// MustGetUint16 returns the underlying uint16 value parameter. It panics if
// an error occurs while trying to get the parameter.
func (pars Params) MustGetUint16(name string) uint16 {
diff --git a/pkg/event/param_decoder_windows.go b/pkg/event/param_decoder_windows.go
new file mode 100644
index 000000000..ed5b09ddd
--- /dev/null
+++ b/pkg/event/param_decoder_windows.go
@@ -0,0 +1,623 @@
+/*
+ * Copyright 2020-present by Nedim Sabic Sabic
+ * https://www.fibratus.io
+ * All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package event
+
+import (
+ "encoding/binary"
+ "path/filepath"
+ "strings"
+
+ "github.com/rabbitstack/fibratus/pkg/event/params"
+ "github.com/rabbitstack/fibratus/pkg/fs"
+ "github.com/rabbitstack/fibratus/pkg/sys/etw"
+ "github.com/rabbitstack/fibratus/pkg/util/filetime"
+ "github.com/rabbitstack/fibratus/pkg/util/key"
+ "github.com/rabbitstack/fibratus/pkg/util/signature"
+ "github.com/rabbitstack/fibratus/pkg/util/utf16"
+ "github.com/rabbitstack/fibratus/pkg/util/va"
+ "golang.org/x/sys/windows"
+ "golang.org/x/sys/windows/registry"
+)
+
+// ParamDecoder parses parameters from the event buffer.
+type ParamDecoder struct{}
+
+// DecodeRegistry parses registry events such as key creation,
+// key/value access, or value mutation.
+func (d *ParamDecoder) DecodeRegistry(r *etw.EventRecord, e *Event) {
+ // typedef struct _WMI_REGISTRY {
+ // LONGLONG InitialTime;
+ // ULONG Status;
+ // union{
+ // ULONG Index;
+ // ULONG InfoClass;
+ // } DUMMYUNIONNAME;
+ // PVOID Kcb;
+ // WCHAR Name[1];
+ // } WMI_REGISTRY, *PWMI_REGISTRY;
+
+ // skip InitialTime (uint64)
+ e.AppendParam(params.NTStatus, params.Status, r.ReadUint32(8))
+ // skip Index/InfoClass (uint32)
+ e.AppendParam(params.RegKeyHandle, params.Address, r.ReadUint64(16))
+ e.AppendParam(params.RegPath, params.Key, r.ConsumeUTF16String(24))
+}
+
+// DecodeRegSetValueInternal decodes the payload for the registry set value
+// event used for enriching the core RegSetValue event emitted by the system
+// logger.
+//
+// The event describes a registry value modification operation and contains
+// both metadata about the target registry value and a captured snapshot of
+// the written data buffer.
+func (d *ParamDecoder) DecodeRegSetValueInternal(r *etw.EventRecord, e *Event) {
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ valueType := r.ReadUint32(12)
+ // skip DataSize (uint32)
+ keyName, koffset := r.ReadUTF16String(20)
+ valueName, voffset := r.ReadUTF16String(koffset)
+ capturedSize := r.ReadUint16(voffset)
+ capturedData := r.ReadBytes(2+voffset, capturedSize)
+
+ // copy the buffer to avoid dangling pointers
+ // after the callback function returns and the
+ // buffer lifetime evicts
+ b := make([]byte, capturedSize)
+ copy(b, capturedData)
+
+ e.AppendParam(params.RegKeyHandle, params.Address, r.ReadUint64(0))
+ e.AppendParam(params.NTStatus, params.Status, r.ReadUint32(8))
+ e.AppendParam(params.RegPath, params.Key, filepath.Join(keyName, valueName))
+ e.AppendEnum(params.RegValueType, valueType, key.RegistryValueTypes)
+
+ if len(b) == 0 {
+ return
+ }
+
+ // populate value data depending on its type
+ switch valueType {
+ case registry.SZ, registry.MULTI_SZ, registry.EXPAND_SZ:
+ e.AppendParam(params.RegData, params.UnicodeString, utf16.BytesToString(b, binary.LittleEndian))
+ case registry.BINARY:
+ e.AppendParam(params.RegData, params.Binary, b)
+ case registry.DWORD:
+ var v uint32
+ switch len(b) {
+ case 4:
+ v = binary.LittleEndian.Uint32(b)
+ case 2:
+ v = uint32(binary.LittleEndian.Uint16(b))
+ case 1:
+ v = uint32(b[0])
+ }
+ e.AppendParam(params.RegData, params.Uint32, v)
+ case registry.DWORD_BIG_ENDIAN:
+ var v uint32
+ switch len(b) {
+ case 4:
+ v = binary.BigEndian.Uint32(b)
+ case 2:
+ v = uint32(binary.BigEndian.Uint16(b))
+ case 1:
+ v = uint32(b[0])
+ }
+ e.AppendParam(params.RegData, params.Uint32, v)
+ case registry.QWORD:
+ var v uint64
+ switch len(b) {
+ case 8:
+ v = binary.LittleEndian.Uint64(b)
+ case 4:
+ v = uint64(binary.LittleEndian.Uint32(b))
+ case 2:
+ v = uint64(binary.LittleEndian.Uint16(b))
+ case 1:
+ v = uint64(b[0])
+ }
+ e.AppendParam(params.RegData, params.Uint64, v)
+ }
+}
+
+// DecodeFile decodes file I/O operations such as file creation, access,
+// or file metadata manipulation.
+func (d *ParamDecoder) DecodeFile(r *etw.EventRecord, e *Event) {
+ switch r.Header.EventDescriptor.Opcode {
+ case CreateFileID:
+ // typedef struct _PERFINFO_FILE_CREATE {
+ // LONG_PTR Irp;
+ // ULONG_PTR FileObject;
+ // ULONG IssuingThreadId;
+ // ULONG Options;
+ // ULONG Attributes;
+ // ULONG ShareAccess;
+ // WCHAR OpenPath[1];
+ // } PERFINFO_FILE_CREATE, *PPERFINFO_FILE_CREATE;
+ e.AppendParam(params.FileIrpPtr, params.Address, r.ReadUint64(0))
+ e.AppendParam(params.FileObject, params.Address, r.ReadUint64(8))
+ e.AppendParam(params.ThreadID, params.TID, r.ReadUint32(16))
+ e.AppendParam(params.FileCreateOptions, params.Flags, r.ReadUint32(20), WithFlags(FileCreateOptionsFlags))
+ e.AppendParam(params.FileAttributes, params.Flags, r.ReadUint32(24), WithFlags(FileAttributeFlags))
+ e.AppendParam(params.FileShareMask, params.Flags, r.ReadUint32(28), WithFlags(FileShareModeFlags))
+ e.AppendParam(params.FilePath, params.DOSPath, r.ConsumeUTF16String(32))
+ case FileOpEndID:
+ // typedef struct _PERFINFO_FILE_OPERATION_END {
+ // ULONG_PTR Irp;
+ // ULONG_PTR ExtraInformation;
+ // NTSTATUS Status;
+ // } PERFINFO_FILE_OPERATION_END, *PPERFINFO_FILE_OPERATION_END;
+ e.AppendParam(params.FileIrpPtr, params.Address, r.ReadUint64(0))
+ e.AppendParam(params.FileExtraInfo, params.Address, r.ReadUint64(8))
+ e.AppendParam(params.NTStatus, params.Status, r.ReadUint32(16))
+ case MapViewFileID, UnmapViewFileID, MapFileRundownID:
+ e.AppendParam(params.FileViewBase, params.Address, r.ReadUint64(0))
+ e.AppendParam(params.FileKey, params.Address, r.ReadUint64(8))
+ e.AppendParam(params.MemProtect, params.Flags, uint32(r.ReadUint64(16)>>32), WithFlags(ViewProtectionFlags))
+ e.AppendParam(params.FileViewSectionType, params.Enum, uint32(r.ReadUint64(16)>>52), WithEnum(ViewSectionTypes))
+ e.AppendParam(params.FileViewSize, params.Uint64, r.ReadUint64(24))
+ e.AppendParam(params.FileOffset, params.Uint64, r.ReadUint64(32))
+ e.AppendParam(params.ProcessID, params.PID, r.ReadUint32(40))
+ case SetFileInformationID, DeleteFileID, RenameFileID:
+ // DeleteFile, RenameFile, and SetFileInformation share the same layout
+ // typedef struct _PERFINFO_FILE_INFORMATION {
+ // ULONG_PTR Irp;
+ // ULONG_PTR FileObject;
+ // ULONG_PTR FileKey;
+ // ULONG_PTR ExtraInformation;
+ // ULONG IssuingThreadId;
+ // ULONG InfoClass;
+ // } PERFINFO_FILE_INFORMATION, *PPERFINFO_FILE_INFORMATION;
+ e.AppendParam(params.FileIrpPtr, params.Address, r.ReadUint64(0))
+ e.AppendParam(params.FileObject, params.Address, r.ReadUint64(8))
+ e.AppendParam(params.FileKey, params.Address, r.ReadUint64(16))
+ e.AppendParam(params.FileExtraInfo, params.Uint64, r.ReadUint64(24))
+ e.AppendParam(params.ThreadID, params.TID, r.ReadUint32(32))
+ e.AppendParam(params.FileInfoClass, params.Enum, r.ReadUint32(36), WithEnum(fs.FileInfoClasses))
+ case ReleaseFileID, CloseFileID:
+ // typedef struct _PERFINFO_FILE_SIMPLE_OPERATION {
+ // ULONG_PTR Irp;
+ // ULONG_PTR FileObject;
+ // ULONG_PTR FileKey;
+ // ULONG IssuingThreadId;
+ // } PERFINFO_FILE_SIMPLE_OPERATION, *PPERFINFO_FILE_SIMPLE_OPERATION;
+ e.AppendParam(params.FileIrpPtr, params.Address, r.ReadUint64(0))
+ e.AppendParam(params.FileObject, params.Address, r.ReadUint64(8))
+ e.AppendParam(params.FileKey, params.Address, r.ReadUint64(16))
+ e.AppendParam(params.ThreadID, params.TID, r.ReadUint32(24))
+ case ReadFileID, WriteFileID:
+ // typedef struct _PERFINFO_FILE_READ_WRITE {
+ // ULONGLONG Offset;
+ // ULONG_PTR Irp;
+ // ULONG_PTR FileObject;
+ // ULONG_PTR FileKey;
+ // ULONG IssuingThreadId;
+ // ULONG Size;
+ // ULONG Flags;
+ // ULONG ExtraFlags;
+ // } PERFINFO_FILE_READ_WRITE, *PPERFINFO_FILE_READ_WRITE;
+ e.AppendParam(params.FileOffset, params.Uint64, r.ReadUint64(0))
+ e.AppendParam(params.FileIrpPtr, params.Address, r.ReadUint64(8))
+ e.AppendParam(params.FileObject, params.Address, r.ReadUint64(16))
+ e.AppendParam(params.FileKey, params.Address, r.ReadUint64(24))
+ e.AppendParam(params.ThreadID, params.TID, r.ReadUint32(32))
+ e.AppendParam(params.FileIoSize, params.Uint32, r.ReadUint32(34))
+ case EnumDirectoryID:
+ // typedef struct _PERFINFO_FILE_DIRENUM {
+ // ULONG_PTR Irp;
+ // ULONG_PTR FileObject;
+ // ULONG_PTR FileKey;
+ // ULONG IssuingThreadId;
+ // ULONG Length;
+ // ULONG InfoClass;
+ // ULONG FileIndex;
+ // WCHAR FileName[1];
+ // } PERFINFO_FILE_DIRENUM, *PPERFINFO_FILE_DIRENUM;
+ e.AppendParam(params.FileIrpPtr, params.Address, r.ReadUint64(0))
+ e.AppendParam(params.FileObject, params.Address, r.ReadUint64(8))
+ e.AppendParam(params.FileKey, params.Address, r.ReadUint64(16))
+ e.AppendParam(params.ThreadID, params.TID, r.ReadUint32(24))
+ // skip Length (uint32)
+ e.AppendParam(params.FileInfoClass, params.Enum, r.ReadUint32(32), WithEnum(fs.FileInfoClasses))
+ // skip FileIndex (uint32)
+ e.AppendParam(params.FilePath, params.UnicodeString, r.ConsumeUTF16String(40))
+ case FileRundownID:
+ e.AppendParam(params.FileObject, params.Address, r.ReadUint64(0))
+ e.AppendParam(params.FilePath, params.DOSPath, r.ConsumeUTF16String(8))
+ }
+}
+
+// DecodeProcess decodes process creation/termination/rundown event payloads.
+func (d *ParamDecoder) DecodeProcess(r *etw.EventRecord, e *Event) {
+ // typedef struct _WMI_PROCESS_INFORMATION {
+ // ULONG_PTR UniqueProcessKey;
+ // ULONG ProcessId;
+ // ULONG ParentId;
+ // ULONG SessionId;
+ // NTSTATUS ExitStatus;
+ // ULONG_PTR DirectoryTableBase;
+ // ULONG Flags;
+ // ULONG Sid;
+ // // Variable length sid
+ // // FileName (ansi string)
+ // // CommandLine (unicode string)
+ // // PackageFullName (unicode string)
+ // // PRAID (unicode string)
+ // } WMI_PROCESS_INFORMATION, *PWMI_PROCESS_INFORMATION;
+ const offset = 32
+ sid, soffset := r.ReadSID(offset+4, true)
+ name, noffset := r.ReadAnsiString(soffset)
+ cmdline, _ := r.ReadUTF16String(noffset)
+
+ e.AppendParam(params.ProcessObject, params.Address, r.ReadUint64(0))
+ e.AppendParam(params.ProcessID, params.PID, r.ReadUint32(8))
+ e.AppendParam(params.ProcessParentID, params.PID, r.ReadUint32(12))
+ e.AppendParam(params.SessionID, params.Uint32, r.ReadUint32(16))
+ e.AppendParam(params.ExitStatus, params.Status, r.ReadUint32(20))
+ e.AppendParam(params.DTB, params.Address, r.ReadUint64(24))
+ e.AppendParam(params.ProcessFlags, params.Flags, r.ReadUint32(32), WithFlags(PsCreationFlags))
+ e.AppendParam(params.UserSID, params.WbemSID, sid)
+ e.AppendParam(params.ProcessName, params.AnsiString, name)
+ e.AppendParam(params.Cmdline, params.UnicodeString, cmdline)
+ e.AppendParam(params.ProcessRealParentID, params.PID, r.Header.ProcessID)
+}
+
+// DecodeProcessInternal decodes process creation/rundown event payloads
+// for internal events that are used to enrich the core NT Kernel logger
+// process events.
+func (d *ParamDecoder) DecodeProcessInternal(r *etw.EventRecord, e *Event) {
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ e.AppendParam(params.ProcessID, params.PID, r.ReadUint32(0))
+ e.AppendParam(params.ProcessObject, params.Address, r.ReadUint64(4))
+
+ createTime := windows.NsecToFiletime(int64(r.ReadUint64(12)))
+ e.AppendParam(params.StartTime, params.Time, filetime.ToEpoch(uint64(createTime.Nanoseconds())))
+
+ e.AppendParam(params.ProcessParentID, params.PID, r.ReadUint32(20))
+ // skip ParentProcessSequenceNumber (uint64)
+ e.AppendParam(params.SessionID, params.Uint32, r.ReadUint32(32))
+ e.AppendParam(params.ProcessFlags, params.Flags, r.ReadUint32(36), WithFlags(PsCreationFlags))
+ e.AppendParam(params.ProcessTokenElevationType, params.Enum, r.ReadUint32(40), WithEnum(PsTokenElevationTypes))
+ e.AppendParam(params.ProcessTokenIsElevated, params.Bool, r.ReadUint32(44) > 0)
+
+ tokenMandatoryLabel, _ := r.ReadSID(48, false) // integrity level SID size is 12 bytes
+ e.AppendParam(params.ProcessTokenIntegrityLevel, params.SID, tokenMandatoryLabel)
+
+ exe, _ := r.ReadNTUnicodeString(60)
+ e.AppendParam(params.Exe, params.DOSPath, exe)
+}
+
+// DecodeModule decodes module load/unload/rundown event payloads.
+func (d *ParamDecoder) DecodeModule(r *etw.EventRecord, e *Event) {
+ // typedef struct _WMI_IMAGELOAD_INFORMATION64 {
+ // ULONG64 ImageBase64;
+ // ULONG64 ImageSize64;
+ // ULONG ProcessId;
+ // ULONG ImageChecksum;
+ // ULONG TimeDateStamp;
+ // UCHAR SignatureLevel;
+ // UCHAR SignatureType;
+ // USHORT Reserved0;
+ // ULONG64 DefaultBase64;
+ // ULONG Reserved1;
+ // ULONG Reserved2;
+ // ULONG Reserved3;
+ // ULONG Reserved4;
+ // WCHAR FileName[1];
+ // } WMI_IMAGELOAD_INFORMATION64, *PWMI_IMAGELOAD_INFORMATION64;
+ e.AppendParam(params.ModuleBase, params.Address, r.ReadUint64(0))
+ e.AppendParam(params.ModuleSize, params.Uint64, r.ReadUint64(8))
+ e.AppendParam(params.ProcessID, params.PID, r.ReadUint32(16))
+ e.AppendParam(params.ModuleCheckSum, params.Uint32, r.ReadUint32(20))
+ // skip TimeDateStamp (uint32)
+ e.AppendParam(params.ModuleSignatureLevel, params.Enum, uint32(r.ReadByte(28)), WithEnum(signature.Levels))
+ e.AppendParam(params.ModuleSignatureType, params.Enum, uint32(r.ReadByte(29)), WithEnum(signature.Types))
+ // skip Reserved0 (uint8)
+ e.AppendParam(params.ModuleDefaultBase, params.Address, r.ReadUint64(32))
+ // skip Reserved1-Reserved4 (uint32 * 4)
+ const offset = 56
+ e.AppendParam(params.ModulePath, params.DOSPath, r.ConsumeUTF16String(offset))
+}
+
+// DecodeModuleInternal decodes module load event payload for internal events
+// that are used to make the process snapshotter more resistant in light of
+// module lookups that might not be registered when the event from the security
+// logger session is published.
+func (d *ParamDecoder) DecodeModuleInternal(r *etw.EventRecord, e *Event) {
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ e.AppendParam(params.ModuleBase, params.Address, r.ReadUint64(0))
+ e.AppendParam(params.ModuleSize, params.Uint64, r.ReadUint64(8))
+ e.AppendParam(params.ProcessID, params.PID, r.ReadUint32(16))
+ e.AppendParam(params.ModuleCheckSum, params.Uint32, r.ReadUint32(20))
+ // skip TimeDateStamp (uint32)
+ e.AppendParam(params.ModuleDefaultBase, params.Address, r.ReadUint64(28))
+ e.AppendParam(params.ModulePath, params.DOSPath, r.ConsumeUTF16String(36))
+}
+
+// DecodeOpenProcess parses the event payload for OpenProcess events.
+func (d *ParamDecoder) DecodeOpenProcess(r *etw.EventRecord, e *Event) {
+ e.AppendParam(params.ProcessID, params.PID, r.ReadUint32(0))
+ e.AppendParam(params.DesiredAccess, params.Flags, r.ReadUint32(4), WithFlags(PsAccessRightFlags))
+ e.AppendParam(params.NTStatus, params.Status, r.ReadUint32(8))
+ e.AppendParam(params.Callstack, params.Slice, r.Callstack())
+}
+
+// DecodeThread decodes the event payload for thread creation/termination
+// and thread rundown events.
+func (d *ParamDecoder) DecodeThread(r *etw.EventRecord, e *Event) {
+ // typedef struct _WMI_EXTENDED_THREAD_INFORMATION64 {
+ // ULONG ProcessId;
+ // ULONG ThreadId;
+ // ULONG64 StackBase64;
+ // ULONG64 StackLimit64;
+ // ULONG64 UserStackBase64;
+ // ULONG64 UserStackLimit64;
+ // union {
+ // ULONG64 StartAddr64;
+ // ULONG64 Affinity;
+ // } DUMMYUNIONNAME;
+ // ULONG64 Win32StartAddr64;
+ // ULONG64 TebBase64;
+ // ULONG SubProcessTag;
+ // SCHAR BasePriority;
+ // UCHAR PagePriority;
+ // UCHAR IoPriority;
+ // UCHAR Flags;
+ // } WMI_EXTENDED_THREAD_INFORMATION64, *PWMI_EXTENDED_THREAD_INFORMATION64;
+ e.AppendParam(params.ProcessID, params.PID, r.ReadUint32(0))
+ e.AppendParam(params.ThreadID, params.TID, r.ReadUint32(4))
+ e.AppendParam(params.KstackBase, params.Address, r.ReadUint64(8))
+ e.AppendParam(params.KstackLimit, params.Address, r.ReadUint64(16))
+ e.AppendParam(params.UstackBase, params.Address, r.ReadUint64(24))
+ e.AppendParam(params.UstackLimit, params.Address, r.ReadUint64(32))
+ // skip StartAddr64 (uint64)
+ e.AppendParam(params.StartAddress, params.Address, r.ReadUint64(48))
+ e.AppendParam(params.TEB, params.Address, r.ReadUint64(56))
+ // skip SubProcessTag (uint32)
+ e.AppendParam(params.BasePrio, params.Uint8, r.ReadByte(68))
+ e.AppendParam(params.PagePrio, params.Uint8, r.ReadByte(69))
+ e.AppendParam(params.IOPrio, params.Uint8, r.ReadByte(70))
+}
+
+// DecodeOpenThread decodes the payload for the OpenThread event.
+func (d *ParamDecoder) DecodeOpenThread(r *etw.EventRecord, e *Event) {
+ e.AppendParam(params.ProcessID, params.PID, r.ReadUint32(0))
+ e.AppendParam(params.ThreadID, params.TID, r.ReadUint32(4))
+ e.AppendParam(params.DesiredAccess, params.Flags, r.ReadUint32(8), WithFlags(ThreadAccessRightFlags))
+ e.AppendParam(params.NTStatus, params.Status, r.ReadUint32(12))
+ e.AppendParam(params.Callstack, params.Slice, r.Callstack())
+}
+
+// DecodeSetThreadContext decodes the payload for the SetThreadContext event.
+func (d *ParamDecoder) DecodeSetThreadContext(r *etw.EventRecord, e *Event) {
+ e.AppendParam(params.NTStatus, params.Status, r.ReadUint32(0))
+ e.AppendParam(params.Callstack, params.Slice, r.Callstack())
+}
+
+// DecodeThreadpool decodes payloads for thread pool events.
+func (d *ParamDecoder) DecodeThreadpool(r *etw.EventRecord, e *Event) {
+ switch r.Header.EventDescriptor.Opcode {
+ case SubmitThreadpoolWorkID, SubmitThreadpoolCallbackID:
+ // typedef struct _ETW_TP_EVENT_CALLBACK_ENQUEUE {
+ // PVOID PoolId; // Pool Identifier
+ // PVOID TaskId; // Task Identifier
+ // PVOID Callback; // Callback Function
+ // PVOID Context; // Callback Context
+ // PVOID SubProcessTag; // Sub-components in a process
+ // } ETW_TP_EVENT_CALLBACK_ENQUEUE, *PETW_TP_EVENT_CALLBACK_ENQUEUE
+ e.AppendParam(params.ThreadpoolPoolID, params.Address, r.ReadUint64(0))
+ e.AppendParam(params.ThreadpoolTaskID, params.Address, r.ReadUint64(8))
+ e.AppendParam(params.ThreadpoolCallback, params.Address, r.ReadUint64(16))
+ e.AppendParam(params.ThreadpoolContext, params.Address, r.ReadUint64(24))
+ e.AppendParam(params.ThreadpoolSubprocessTag, params.Address, r.ReadUint64(32))
+ case SetThreadpoolTimerID:
+ // typedef struct _ETW_TP_EVENT_TIMER_SET {
+ // LONG64 DueTime; // Due time
+ // PVOID SubQueue; // Sub Queue to be inserted
+ // PVOID Timer; // Timer to be set
+ // ULONG Period; // period of the timer
+ // ULONG WindowLength; // Tolerate period
+ // ULONG Absolute; // An absolute timer or relative timer
+ // } ETW_TP_EVENT_TIMER_SET, *PETW_TP_EVENT_TIMER_SET;
+ e.AppendParam(params.ThreadpoolTimerDuetime, params.Uint64, r.ReadUint64(0))
+ e.AppendParam(params.ThreadpoolTimerSubqueue, params.Address, r.ReadUint64(8))
+ e.AppendParam(params.ThreadpoolTimer, params.Address, r.ReadUint64(16))
+ e.AppendParam(params.ThreadpoolTimerPeriod, params.Uint32, r.ReadUint32(24))
+ e.AppendParam(params.ThreadpoolTimerWindow, params.Uint32, r.ReadUint32(28))
+ e.AppendParam(params.ThreadpoolTimerAbsolute, params.Bool, r.ReadUint32(32) > 0)
+ }
+}
+
+// DecodeHandle decodes events for handle creation/disposition events.
+func (d *ParamDecoder) DecodeHandle(r *etw.EventRecord, e *Event) {
+ switch r.Header.EventDescriptor.Opcode {
+ case CreateHandleID, CloseHandleID:
+ // typedef struct _ETW_CREATE_HANDLE_EVENT {
+ // PVOID Object;
+ // ULONG Handle;
+ // USHORT ObjectType;
+ // } ETW_CREATE_HANDLE_EVENT, *PETW_CREATE_HANDLE_EVENT;
+ e.AppendParam(params.HandleObject, params.Address, r.ReadUint64(0))
+ e.AppendParam(params.HandleID, params.Uint32, r.ReadUint32(8))
+ e.AppendParam(params.HandleObjectTypeID, params.HandleType, r.ReadUint16(12))
+ if r.BufferLen >= 16 {
+ e.AppendParam(params.HandleObjectName, params.UnicodeString, r.ConsumeUTF16String(14))
+ }
+ case DuplicateHandleID:
+ // typedef struct _ETW_DUPLICATE_HANDLE_EVENT {
+ // PVOID Object;
+ // ULONG SourceHandle;
+ // ULONG TargetHandle;
+ // ULONG TargetProcessId;
+ // USHORT ObjectType;
+ // ULONG SourceProcessId;
+ // } ETW_DUPLICATE_HANDLE_EVENT, *PETW_DUPLICATE_HANDLE_EVENT;
+ e.AppendParam(params.HandleObject, params.Address, r.ReadUint64(0))
+ e.AppendParam(params.HandleSourceID, params.Uint32, r.ReadUint32(8))
+ e.AppendParam(params.HandleID, params.Uint32, r.ReadUint32(12))
+ e.AppendParam(params.TargetProcessID, params.PID, r.ReadUint32(16))
+ e.AppendParam(params.HandleObjectTypeID, params.HandleType, r.ReadUint16(20))
+ e.AppendParam(params.ProcessID, params.PID, r.ReadUint32(22))
+ }
+}
+
+// DecodeCreateSymbolicLinkObject decodes the payload for the CreateSymbolicLinkObject event.
+func (d *ParamDecoder) DecodeCreateSymbolicLinkObject(r *etw.EventRecord, e *Event) {
+ source, offset := r.ReadUTF16String(0)
+ target, offset := r.ReadUTF16String(offset)
+ e.AppendParam(params.LinkSource, params.UnicodeString, source)
+ e.AppendParam(params.LinkTarget, params.UnicodeString, target)
+ e.AppendParam(params.DesiredAccess, params.Flags, r.ReadUint32(offset), WithFlags(AccessMaskFlags))
+ e.AppendParam(params.NTStatus, params.Status, r.ReadUint32(offset+4))
+ e.AppendParam(params.Callstack, params.Slice, r.Callstack())
+}
+
+// DecodeStackwalk decodes stackwalk event parameters including frame return addresses.
+func (d *ParamDecoder) DecodeStackwalk(r *etw.EventRecord, e *Event) {
+ // typedef struct _STACK_WALK_EVENT_DATA {
+ // ULONGLONG TimeStamp;
+ // ULONG ProcessId;
+ // ULONG ThreadId;
+ // PVOID Addresses[1]; // Address of captured Stack address
+ // } STACK_WALK_EVENT_DATA, *PSTACK_WALK_EVENT_DATA;
+
+ // Skip TimeStamp (uint64)
+ e.AppendParam(params.ProcessID, params.PID, r.ReadUint32(8))
+ e.AppendParam(params.ThreadID, params.TID, r.ReadUint32(12))
+
+ var n uint16
+ var offset uint16 = 16
+
+ frames := (r.BufferLen - offset) / 8
+ callstack := make([]va.Address, frames)
+ for n < frames {
+ callstack[n] = va.Address(r.ReadUint64(offset))
+ offset += 8
+ n++
+ }
+ e.AppendParam(params.Callstack, params.Slice, callstack)
+}
+
+// DecodeMemory decodes memory event payloads.
+func (d *ParamDecoder) DecodeMemory(r *etw.EventRecord, e *Event) {
+ // typedef struct _PERFINFO_VIRTUAL_ALLOC {
+ // PVOID CapturedBase;
+ // SIZE_T CapturedRegionSize;
+ // ULONG ProcessId;
+ // ULONG Flags;
+ // } PERFINFO_VIRTUAL_ALLOC, *PPERFINFO_VIRTUAL_ALLOC;
+ e.AppendParam(params.MemBaseAddress, params.Address, r.ReadUint64(0))
+ e.AppendParam(params.MemRegionSize, params.Uint64, r.ReadUint64(8))
+ e.AppendParam(params.ProcessID, params.PID, r.ReadUint32(16))
+ e.AppendParam(params.MemAllocType, params.Flags, r.ReadUint32(20), WithFlags(MemAllocationFlags))
+}
+
+// DecodeNetwork decodes TCP/UDP network events. All network event
+// share the same schema layout. For IPv6 events, the IP fields are
+// 128 bits long.
+func (d *ParamDecoder) DecodeNetwork(r *etw.EventRecord, e *Event) {
+ // typedef struct _WMI_TCPIP {
+ // ULONG Context;
+ // ULONG Size;
+ // ULONG DestAddr;
+ // ULONG SrcAddr;
+ // USHORT DestPort;
+ // USHORT SrcPort;
+ // } WMI_TCPIP, *PWMI_TCPIP;
+
+ // typedef struct _WMI_UDP {
+ // ULONG PID;
+ // USHORT Size;
+ // ULONG DestAddr;
+ // ULONG SrcAddr;
+ // USHORT DestPort;
+ // USHORT SrcPort;
+ // }WMI_UDP, *PWMI_UDP;
+ e.AppendParam(params.ProcessID, params.PID, r.ReadUint32(0))
+ e.AppendParam(params.NetSize, params.Uint32, r.ReadUint32(4))
+
+ switch r.Header.EventDescriptor.Opcode {
+ case AcceptTCPv6ID, ConnectTCPv6ID, ReconnectTCPv6ID, RetransmitTCPv6ID,
+ DisconnectTCPv6ID, SendV6ID, RecvV6ID:
+ e.AppendParam(params.NetDIP, params.IPv6, r.ReadBytes(8, 16))
+ e.AppendParam(params.NetSIP, params.IPv6, r.ReadBytes(24, 16))
+ e.AppendParam(params.NetDport, params.Port, r.ReadUint16(40))
+ e.AppendParam(params.NetSport, params.Port, r.ReadUint16(42))
+ default:
+ e.AppendParam(params.NetDIP, params.IPv4, r.ReadUint32(8))
+ e.AppendParam(params.NetSIP, params.IPv4, r.ReadUint32(12))
+ e.AppendParam(params.NetDport, params.Port, r.ReadUint16(16))
+ e.AppendParam(params.NetSport, params.Port, r.ReadUint16(18))
+ }
+}
+
+// DecodeDNS decodes DNS query/reply event payloads.
+func (d *ParamDecoder) DecodeDNS(r *etw.EventRecord, e *Event) {
+ name, offset := r.ReadUTF16String(0)
+ e.AppendParam(params.DNSName, params.UnicodeString, name)
+ e.AppendParam(params.DNSRR, params.Enum, r.ReadUint32(offset), WithEnum(DNSRecordTypes))
+ e.AppendParam(params.DNSOpts, params.Flags64, r.ReadUint64(offset+4), WithFlags(DNSOptsFlags))
+
+ if r.Header.EventDescriptor.ID == ReplyDNSID {
+ e.AppendParam(params.DNSRcode, params.Enum, r.ReadUint32(offset+12), WithEnum(DNSResponseCodes))
+ answers := strings.Split(sanitizeDNSAnswers(r.ConsumeUTF16String(offset+16)), ";")
+ e.AppendParam(params.DNSAnswers, params.Slice, answers)
+ }
+}
+
+// sanitizeDNSAnswers removes the "type" string from DNS answers.
+func sanitizeDNSAnswers(answers string) string {
+ return strings.ReplaceAll(answers, "type: 5 ", "")
+}
diff --git a/pkg/event/param_decoder_windows_test.go b/pkg/event/param_decoder_windows_test.go
new file mode 100644
index 000000000..b9ea143e2
--- /dev/null
+++ b/pkg/event/param_decoder_windows_test.go
@@ -0,0 +1,971 @@
+/*
+ * Copyright 2020-present by Nedim Sabic Sabic
+ * https://www.fibratus.io
+ * All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package event
+
+import (
+ "testing"
+ "unsafe"
+
+ "github.com/rabbitstack/fibratus/pkg/event/params"
+ "github.com/rabbitstack/fibratus/pkg/sys/etw"
+ "github.com/rabbitstack/fibratus/pkg/util/va"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestDecodeRegistry(t *testing.T) {
+ var tests = []struct {
+ name string
+ buf []byte
+ assertions func(t *testing.T, e *Event)
+ }{
+ {name: "RegSetValue",
+ assertions: func(t *testing.T, e *Event) {
+ assert.Len(t, e.Params, 3)
+ assert.Equal(t, "StartTime", e.Params.MustGetString(params.RegPath))
+ assert.Equal(t, uint32(0), e.Params.MustGetUint32(params.NTStatus))
+ assert.Equal(t, uint64(0xffffde0e05e45330), e.Params.MustGetUint64(params.RegKeyHandle))
+ },
+ buf: []byte{
+ 116, 104, 52, 53, 29, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 48, 83, 228, 5, 14, 222, 255, 255,
+ 83, 0, 116, 0, 97, 0, 114, 0, 116, 0, 84, 0, 105, 0,
+ 109, 0, 101, 0, 0, 0},
+ },
+ {
+ name: "RegCreateKey",
+ assertions: func(t *testing.T, e *Event) {
+ assert.Len(t, e.Params, 3)
+ assert.Equal(t, `Software\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\Capabilities`, e.Params.MustGetString(params.RegPath))
+ assert.Equal(t, uint32(0), e.Params.MustGetUint32(params.NTStatus))
+ assert.Equal(t, uint64(0xffffb58b742ff990), e.Params.MustGetUint64(params.RegKeyHandle))
+ },
+ buf: []byte{
+ 248, 104, 16, 11, 5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 144, 249, 47, 116, 139, 181, 255, 255,
+ 83, 0, 111, 0, 102, 0, 116, 0,
+ 119, 0, 97, 0, 114, 0, 101, 0,
+ 92, 0,
+ 77, 0, 105, 0, 99, 0, 114, 0, 111, 0, 115, 0,
+ 111, 0, 102, 0, 116, 0,
+ 92, 0,
+ 87, 0, 105, 0, 110, 0, 100, 0, 111, 0, 119, 0,
+ 115, 0,
+ 92, 0,
+ 67, 0, 117, 0, 114, 0, 114, 0, 101, 0, 110, 0,
+ 116, 0, 86, 0, 101, 0, 114, 0, 115, 0, 105, 0,
+ 111, 0, 110, 0,
+ 92, 0,
+ 67, 0, 97, 0, 112, 0, 97, 0, 98, 0, 105, 0,
+ 108, 0, 105, 0, 116, 0, 121, 0,
+ 65, 0, 99, 0, 99, 0, 101, 0, 115, 0, 115, 0,
+ 77, 0, 97, 0, 110, 0, 97, 0, 103, 0, 101, 0,
+ 114, 0,
+ 92, 0,
+ 67, 0, 97, 0, 112, 0, 97, 0, 98, 0, 105, 0,
+ 108, 0, 105, 0, 116, 0, 105, 0, 101, 0, 115, 0,
+ 0, 0,
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ r := initEventRecord(0, 0, tt.buf)
+ e := &Event{Params: make(Params)}
+ paramDecoder.DecodeRegistry(r, e)
+ tt.assertions(t, e)
+ })
+ }
+}
+
+func TestDecodeRegSetValueInternal(t *testing.T) {
+ buf := []byte{
+ 224, 238, 210, 196, 139, 181, 255, 255,
+ 0, 0, 0, 0,
+ 1, 0, 0, 0,
+ 108, 0, 0, 0,
+ 0, 0,
+ 85, 0, 82, 0, 73, 0, 0, 0,
+ 108, 0,
+ 92, 0,
+ 77, 0, 105, 0, 99, 0, 114, 0, 111, 0, 115, 0,
+ 111, 0, 102, 0, 116, 0,
+ 92, 0,
+ 87, 0, 105, 0, 110, 0, 100, 0, 111, 0, 119, 0,
+ 115, 0,
+ 92, 0,
+ 70, 0, 108, 0, 105, 0, 103, 0, 104, 0, 116, 0,
+ 105, 0, 110, 0, 103, 0,
+ 92, 0,
+ 79, 0, 110, 0, 101, 0,
+ 83, 0, 101, 0, 116, 0, 116, 0, 105, 0, 110, 0,
+ 103, 0, 115, 0,
+ 92, 0,
+ 82, 0, 101, 0, 102, 0, 114, 0, 101, 0, 115, 0,
+ 104, 0,
+ 67, 0, 97, 0, 99, 0, 104, 0, 101, 0,
+ 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }
+
+ r := initEventRecord(0, 0, buf)
+ e := &Event{Params: make(Params)}
+ paramDecoder.DecodeRegSetValueInternal(r, e)
+
+ assert.Len(t, e.Params, 5)
+ assert.Equal(t, "URI", e.Params.MustGetString(params.RegPath))
+ assert.Equal(t, uint32(0), e.Params.MustGetUint32(params.NTStatus))
+ assert.Equal(t, `\Microsoft\Windows\Flighting\OneSettings\RefreshCache`, e.Params.MustGetString(params.RegData))
+ assert.Equal(t, "REG_SZ", e.GetParamAsString(params.RegValueType))
+ assert.Equal(t, uint64(0xffffb58bc4d2eee0), e.Params.MustGetUint64(params.RegKeyHandle))
+}
+
+func TestDecodeFile(t *testing.T) {
+ var tests = []struct {
+ name string
+ opcode uint8
+ buf []byte
+ assertions func(t *testing.T, e *Event)
+ }{
+ {
+ name: "CreateFile", opcode: CreateFileID,
+ assertions: func(t *testing.T, e *Event) {
+ assert.Len(t, e.Params, 7)
+ assert.Equal(t, uint64(0xffffd78d965e07c8), e.Params.MustGetUint64(params.FileIrpPtr))
+ assert.Equal(t, uint64(0xffffd78d920b6650), e.Params.MustGetUint64(params.FileObject))
+ assert.Equal(t, `\Device\HarddiskVolume3\WINDOWS\AppCompat\Programs\Amcache.hve`, e.Params.MustGetString(params.FilePath))
+ assert.Equal(t, "NORMAL", e.GetParamAsString(params.FileAttributes))
+ assert.Equal(t, "SEQUENTIAL_ONLY|SYNCHRONOUS_IO_NONALERT|NO_COMPRESSION", e.GetParamAsString(params.FileCreateOptions))
+ assert.Equal(t, uint32(6536), e.Params.MustGetTid())
+ },
+ buf: []byte{
+ 200, 7, 94, 150, 141, 215, 255, 255,
+ 80, 102, 11, 146, 141, 215, 255, 255,
+ 136, 25, 0, 0,
+ 36, 128, 0, 3,
+ 128, 0, 0, 0,
+ 0, 0, 0, 0,
+
+ 92, 0,
+ 68, 0, 101, 0, 118, 0, 105, 0, 99, 0, 101, 0,
+ 92, 0,
+ 72, 0, 97, 0, 114, 0, 100, 0, 100, 0, 105, 0,
+ 115, 0, 107, 0,
+ 86, 0, 111, 0, 108, 0, 117, 0, 109, 0, 101, 0,
+ 51, 0,
+ 92, 0,
+ 87, 0, 73, 0, 78, 0, 68, 0, 79, 0, 87, 0,
+ 83, 0,
+ 92, 0,
+ 65, 0, 112, 0, 112, 0,
+ 67, 0, 111, 0, 109, 0, 112, 0, 97, 0, 116, 0,
+ 92, 0,
+ 80, 0, 114, 0, 111, 0, 103, 0, 114, 0, 97, 0,
+ 109, 0, 115, 0,
+ 92, 0,
+ 65, 0, 109, 0, 99, 0, 97, 0, 99, 0, 104, 0,
+ 101, 0, 46, 0, 104, 0, 118, 0, 101, 0,
+ 0, 0,
+ },
+ },
+ {
+ name: "FileOpEnd", opcode: FileOpEndID,
+ assertions: func(t *testing.T, e *Event) {
+ assert.Len(t, e.Params, 3)
+ assert.Equal(t, uint64(0xffffd78d973df0f8), e.Params.MustGetUint64(params.FileIrpPtr))
+ assert.Equal(t, uint32(0), e.Params.MustGetUint32(params.NTStatus))
+ assert.Equal(t, uint64(0x28), e.Params.MustGetUint64(params.FileExtraInfo))
+ },
+ buf: []byte{
+ 248, 240, 61, 151, 141, 215, 255, 255,
+ 40, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ },
+ {
+ name: "MapViewFile", opcode: MapViewFileID,
+ assertions: func(t *testing.T, e *Event) {
+ assert.Len(t, e.Params, 7)
+ assert.Equal(t, uint64(0xffffb58b75fb7e10), e.Params.MustGetUint64(params.FileKey))
+ assert.Equal(t, uint64(0), e.Params.MustGetUint64(params.FileOffset))
+ assert.Equal(t, uint32(1716), e.Params.MustGetUint32(params.ProcessID))
+ assert.Equal(t, "READONLY", e.GetParamAsString(params.MemProtect))
+ assert.Equal(t, "PAGEFILE", e.GetParamAsString(params.FileViewSectionType))
+ assert.Equal(t, uint64(0x191ab210000), e.Params.MustGetUint64(params.FileViewBase))
+ assert.Equal(t, uint64(4096), e.Params.MustGetUint64(params.FileViewSize))
+ },
+ buf: []byte{
+ 0, 0, 33, 171, 145, 1, 0, 0,
+ 16, 126, 251, 117, 139, 181, 255, 255,
+ 0, 0, 0, 0, 0, 0, 193, 0,
+ 0, 16, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 180, 6, 0, 0,
+ },
+ },
+ {
+ name: "UnmapViewFile", opcode: UnmapViewFileID,
+ assertions: func(t *testing.T, e *Event) {
+ assert.Len(t, e.Params, 7)
+ assert.Equal(t, uint64(0xffffb58bc1f91010), e.Params.MustGetUint64(params.FileKey))
+ assert.Equal(t, uint64(0), e.Params.MustGetUint64(params.FileOffset))
+ assert.Equal(t, uint32(12448), e.Params.MustGetUint32(params.ProcessID))
+ assert.Equal(t, "READWRITE", e.GetParamAsString(params.MemProtect))
+ assert.Equal(t, "PAGEFILE", e.GetParamAsString(params.FileViewSectionType))
+ assert.Equal(t, uint64(0x1675e410000), e.Params.MustGetUint64(params.FileViewBase))
+ assert.Equal(t, uint64(921600), e.Params.MustGetUint64(params.FileViewSize))
+ },
+ buf: []byte{
+ 0, 0, 65, 94, 103, 1, 0, 0,
+ 16, 16, 249, 193, 139, 181, 255, 255,
+ 0, 0, 0, 0, 0, 0, 196, 0,
+ 0, 16, 14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 160, 48, 0, 0,
+ },
+ },
+ {
+ name: "SetFileInformation", opcode: SetFileInformationID,
+ assertions: func(t *testing.T, e *Event) {
+ assert.Len(t, e.Params, 6)
+ assert.Equal(t, "Allocation", e.GetParamAsString(params.FileInfoClass))
+ assert.Equal(t, uint64(524288), e.Params.MustGetUint64(params.FileExtraInfo))
+ assert.Equal(t, uint64(0xffffb58b80ccc180), e.Params.MustGetUint64(params.FileKey))
+ assert.Equal(t, uint64(0xffffd78d76403780), e.Params.MustGetUint64(params.FileObject))
+ assert.Equal(t, uint64(0xffffd78d9b6470f8), e.Params.MustGetUint64(params.FileIrpPtr))
+ assert.Equal(t, uint32(16404), e.Params.MustGetTid())
+ },
+ buf: []byte{
+ 248, 112, 100, 155, 141, 215, 255, 255,
+ 128, 55, 64, 118, 141, 215, 255, 255,
+ 128, 193, 204, 128, 139, 181, 255, 255,
+ 0, 0, 8, 0, 0, 0, 0, 0,
+ 20, 64, 0, 0,
+ 19, 0, 0, 0,
+ },
+ },
+ {
+ name: "DeleteFile", opcode: DeleteFileID,
+ assertions: func(t *testing.T, e *Event) {
+ assert.Len(t, e.Params, 6)
+ assert.Equal(t, "Disposition Extended", e.GetParamAsString(params.FileInfoClass))
+ assert.Equal(t, uint64(1), e.Params.MustGetUint64(params.FileExtraInfo))
+ assert.Equal(t, uint64(0xffffb58bc5e64180), e.Params.MustGetUint64(params.FileKey))
+ assert.Equal(t, uint64(0xffffd78d9b6c7d80), e.Params.MustGetUint64(params.FileObject))
+ assert.Equal(t, uint64(0xffffd78d7c5860f8), e.Params.MustGetUint64(params.FileIrpPtr))
+ assert.Equal(t, uint32(13656), e.Params.MustGetTid())
+ },
+ buf: []byte{
+ 248, 96, 88, 124, 141, 215, 255, 255,
+ 128, 125, 108, 155, 141, 215, 255, 255,
+ 128, 65, 230, 197, 139, 181, 255, 255,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 88, 53, 0, 0,
+ 64, 0, 0, 0,
+ },
+ },
+ {
+ name: "ReleaseFile", opcode: ReleaseFileID,
+ assertions: func(t *testing.T, e *Event) {
+ assert.Len(t, e.Params, 4)
+ assert.Equal(t, uint64(0xffffb58b9268d180), e.Params.MustGetUint64(params.FileKey))
+ assert.Equal(t, uint64(0xffffd78d9b4552b0), e.Params.MustGetUint64(params.FileObject))
+ assert.Equal(t, uint64(0xffffd78d7ca0b0f8), e.Params.MustGetUint64(params.FileIrpPtr))
+ assert.Equal(t, uint32(3096), e.Params.MustGetTid())
+ },
+ buf: []byte{
+ 248, 176, 160, 124, 141, 215, 255, 255,
+ 176, 82, 69, 155, 141, 215, 255, 255,
+ 128, 209, 104, 146, 139, 181, 255, 255,
+ 24, 12, 0, 0,
+ },
+ },
+ {
+ name: "WriteFile", opcode: WriteFileID,
+ assertions: func(t *testing.T, e *Event) {
+ assert.Len(t, e.Params, 6)
+ assert.Equal(t, uint64(0xffffb58b74e78b10), e.Params.MustGetUint64(params.FileKey))
+ assert.Equal(t, uint64(0xffffd78d6970ae80), e.Params.MustGetUint64(params.FileObject))
+ assert.Equal(t, uint64(0xffffd78d9a786a08), e.Params.MustGetUint64(params.FileIrpPtr))
+ assert.Equal(t, uint32(392), e.Params.MustGetTid())
+ assert.Equal(t, uint64(573440), e.Params.MustGetUint64(params.FileOffset))
+ assert.Equal(t, uint32(1073741824), e.Params.MustGetUint32(params.FileIoSize))
+ },
+ buf: []byte{
+ 0, 192, 8, 0, 0, 0, 0, 0,
+ 8, 106, 120, 154, 141, 215, 255, 255,
+ 128, 174, 112, 105, 141, 215, 255, 255,
+ 16, 139, 231, 116, 139, 181, 255, 255,
+ 136, 1, 0, 0,
+ 0, 64, 1, 0,
+ 1, 10, 6, 0,
+ 0, 0, 0, 0,
+ },
+ },
+ {name: "EnumDirectory", opcode: EnumDirectoryID,
+ assertions: func(t *testing.T, e *Event) {
+ assert.Len(t, e.Params, 6)
+ assert.Equal(t, uint64(0xffffde0dfb917590), e.Params.MustGetUint64(params.FileKey))
+ assert.Equal(t, uint64(0xffff8084cb43c990), e.Params.MustGetUint64(params.FileObject))
+ assert.Equal(t, `git"*`, e.Params.MustGetString(params.FilePath))
+ assert.Equal(t, uint64(0xffff8084da3e7788), e.Params.MustGetUint64(params.FileIrpPtr))
+ assert.Equal(t, uint32(12860), e.Params.MustGetTid())
+ },
+ buf: []byte{
+ 136, 119, 62, 218, 132, 128, 255, 255,
+ 144, 201, 67, 203, 132, 128, 255, 255,
+ 144, 117, 145, 251, 13, 222, 255, 255,
+ 60, 50, 0, 0, 116, 2, 0, 0,
+ 79, 0, 0, 0, 0, 0, 0, 0,
+ 103, 0, 105, 0, 116, 0, 34, 0, 42, 0, 0, 0,
+ },
+ },
+ {
+ name: "FileRundown", opcode: FileRundownID,
+ assertions: func(t *testing.T, e *Event) {
+ assert.Len(t, e.Params, 2)
+ assert.Equal(t, `\Device\HarddiskVolume3\Windows\System32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\Microsoft-Windows-TerminalServices-AppServerClient-Opt-WOW64-Package~31bf3856ad364e35~wow64~~10.0.26100.8115.cat`, e.Params.MustGetString(params.FilePath))
+ },
+ buf: []byte{
+ 80, 71, 18, 158, 139, 181, 255, 255,
+ 92, 0, 68, 0, 101, 0, 118, 0,
+ 105, 0, 99, 0, 101, 0, 92, 0,
+ 72, 0, 97, 0, 114, 0, 100, 0,
+ 100, 0, 105, 0, 115, 0, 107, 0,
+ 86, 0, 111, 0, 108, 0, 117, 0,
+ 109, 0, 101, 0, 51, 0, 92, 0,
+ 87, 0, 105, 0, 110, 0, 100, 0,
+ 111, 0, 119, 0, 115, 0, 92, 0,
+ 83, 0, 121, 0, 115, 0, 116, 0,
+ 101, 0, 109, 0, 51, 0, 50, 0,
+ 92, 0, 67, 0, 97, 0, 116, 0,
+ 82, 0, 111, 0, 111, 0, 116, 0,
+ 92, 0,
+ 123, 0, 70, 0, 55, 0, 53, 0, 48, 0,
+ 69, 0, 54, 0, 67, 0, 51, 0, 45, 0,
+ 51, 0, 56, 0, 69, 0, 69, 0, 45, 0,
+ 49, 0, 49, 0, 68, 0, 49, 0, 45, 0,
+ 56, 0, 53, 0, 69, 0, 53, 0, 45, 0,
+ 48, 0, 48, 0, 67, 0, 48, 0, 52, 0,
+ 70, 0, 67, 0, 50, 0, 57, 0, 53, 0,
+ 69, 0, 69, 0, 125, 0,
+ 92, 0,
+ 77, 0, 105, 0, 99, 0, 114, 0, 111, 0,
+ 115, 0, 111, 0, 102, 0, 116, 0, 45, 0,
+ 87, 0, 105, 0, 110, 0, 100, 0, 111, 0,
+ 119, 0, 115, 0, 45, 0,
+ 84, 0, 101, 0, 114, 0, 109, 0, 105, 0,
+ 110, 0, 97, 0, 108, 0,
+ 83, 0, 101, 0, 114, 0, 118, 0, 105, 0,
+ 99, 0, 101, 0, 115, 0, 45, 0,
+ 65, 0, 112, 0, 112, 0, 83, 0, 101, 0,
+ 114, 0, 118, 0, 101, 0, 114, 0,
+ 67, 0, 108, 0, 105, 0, 101, 0, 110, 0,
+ 116, 0, 45, 0,
+ 79, 0, 112, 0, 116, 0, 45, 0,
+ 87, 0, 79, 0, 87, 0, 54, 0, 52, 0,
+ 45, 0,
+ 80, 0, 97, 0, 99, 0, 107, 0, 97, 0,
+ 103, 0, 101, 0,
+ 126, 0, 51, 0, 49, 0, 98, 0, 102, 0,
+ 51, 0, 56, 0, 53, 0, 54, 0, 97, 0,
+ 100, 0, 51, 0, 54, 0, 52, 0, 101, 0,
+ 51, 0, 53, 0, 126, 0,
+ 119, 0, 111, 0, 119, 0, 54, 0, 52, 0,
+ 126, 0, 126, 0,
+ 49, 0, 48, 0, 46, 0, 48, 0, 46, 0,
+ 50, 0, 54, 0, 49, 0, 48, 0, 48, 0,
+ 46, 0, 56, 0, 49, 0, 49, 0, 53, 0,
+ 46, 0,
+ 99, 0, 97, 0, 116, 0,
+ 0, 0,
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ r := initEventRecord(tt.opcode, 0, tt.buf)
+ e := &Event{Params: make(Params)}
+ paramDecoder.DecodeFile(r, e)
+ tt.assertions(t, e)
+ })
+ }
+}
+
+func TestDecodeProcess(t *testing.T) {
+ buf := []byte{
+ 192, 48, 161, 124, 141, 215, 255, 255,
+ 124, 78, 0, 0,
+ 128, 52, 0, 0,
+ 1, 0, 0, 0,
+ 3, 1, 0, 0,
+ 0, 96, 231, 68, 3, 0, 0, 0,
+ 0, 0, 0, 0,
+ 160, 162, 152, 216, 139, 181, 255, 255,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 1, 5, 0, 0, 0, 0, 0, 5,
+ 21, 0, 0, 0,
+ 226, 73, 191, 35, 149, 112, 61, 68,
+ 44, 66, 142, 178, 234, 3, 0, 0,
+
+ 99, 111, 110, 104, 111, 115, 116, 46, 101, 120, 101, 0,
+
+ 92, 0, 63, 0, 63, 0, 92, 0,
+ 67, 0, 58, 0, 92, 0, 87, 0, 73, 0, 78, 0, 68, 0, 79, 0, 87, 0, 83, 0,
+ 92, 0, 115, 0, 121, 0, 115, 0, 116, 0, 101, 0, 109, 0, 51, 0, 50, 0,
+ 92, 0, 99, 0, 111, 0, 110, 0, 104, 0, 111, 0, 115, 0, 116, 0, 46, 0,
+ 101, 0, 120, 0, 101, 0,
+
+ 32, 0, 48, 0, 120, 0, 102, 0, 102, 0, 102, 0, 102, 0, 102, 0, 102, 0, 102, 0,
+ 32, 0, 45, 0, 70, 0, 111, 0, 114, 0, 99, 0, 101, 0, 86, 0, 49, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }
+
+ r := initEventRecord(0, 0, buf)
+ e := &Event{Params: make(Params)}
+ paramDecoder.DecodeProcess(r, e)
+
+ assert.Len(t, e.Params, 11)
+ assert.Equal(t, `\??\C:\WINDOWS\system32\conhost.exe 0xfffffff -ForceV1`, e.Params.MustGetString(params.Cmdline))
+ assert.Equal(t, uint64(0x344e76000), e.Params.MustGetUint64(params.DTB))
+ assert.Equal(t, uint32(0x103), e.Params.MustGetUint32(params.ExitStatus))
+ assert.Equal(t, uint64(0xffffd78d7ca130c0), e.Params.MustGetUint64(params.ProcessObject))
+ assert.Equal(t, "conhost.exe", e.Params.MustGetString(params.ProcessName))
+ assert.Equal(t, uint32(20092), e.Params.MustGetPid())
+ assert.Equal(t, uint32(13440), e.Params.MustGetPpid())
+ assert.Equal(t, uint32(13440), e.Params.MustGetUint32(params.ProcessRealParentID))
+ assert.Equal(t, uint32(1), e.Params.MustGetUint32(params.SessionID))
+ assert.Equal(t, "S-1-5-21-599738850-1144877205-2995667500-1002", e.GetParamAsString(params.UserSID))
+}
+
+func TestDecodeProcessInternal(t *testing.T) {
+ buf := []byte{
+ 88, 77, 0, 0,
+ 13, 195, 0, 0,
+ 0, 0, 0, 0,
+
+ 102, 161, 153, 7, 34, 222, 220, 1,
+
+ 172, 26, 0, 0,
+ 11, 195, 0, 0,
+ 0, 0, 0, 0,
+
+ 1, 0, 0, 0,
+ 0, 0, 0, 0,
+ 2, 0, 0, 0,
+ 1, 0, 0, 0,
+ 1, 1, 0, 0,
+
+ 0, 0, 0, 16,
+ 0, 48, 0, 0,
+
+ 92, 0,
+ 68, 0, 101, 0, 118, 0, 105, 0, 99, 0, 101, 0,
+ 92, 0,
+ 72, 0, 97, 0, 114, 0, 100, 0, 100, 0, 105, 0,
+ 115, 0, 107, 0,
+ 86, 0, 111, 0, 108, 0, 117, 0, 109, 0, 101, 0,
+ 51, 0,
+ 92, 0,
+ 80, 0, 114, 0, 111, 0, 103, 0, 114, 0, 97, 0,
+ 109, 0,
+ 32, 0,
+ 70, 0, 105, 0, 108, 0, 101, 0, 115, 0,
+ 92, 0,
+ 71, 0, 105, 0, 116, 0,
+ 92, 0,
+ 109, 0, 105, 0, 110, 0, 103, 0, 119, 0, 54, 0,
+ 52, 0,
+ 92, 0,
+ 98, 0, 105, 0, 110, 0,
+ 92, 0,
+ 103, 0, 105, 0, 116, 0, 46, 0, 101, 0, 120, 0,
+ 101, 0,
+ 0, 0,
+
+ 95, 10, 66, 0,
+ 139, 104, 27, 105,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }
+
+ r := initEventRecord(0, 0, buf)
+ e := &Event{Params: make(Params)}
+ paramDecoder.DecodeProcessInternal(r, e)
+
+ assert.Len(t, e.Params, 10)
+ assert.Equal(t, `\Device\HarddiskVolume3\Program Files\Git\mingw64\bin\git.exe`, e.Params.MustGetString(params.Exe))
+ assert.Equal(t, uint64(0xc30d), e.Params.MustGetUint64(params.ProcessObject))
+ assert.Equal(t, uint32(19800), e.Params.MustGetPid())
+ assert.Equal(t, uint32(6828), e.Params.MustGetPpid())
+ assert.Equal(t, uint32(1), e.Params.MustGetUint32(params.SessionID))
+ assert.Equal(t, "FULL", e.GetParamAsString(params.ProcessTokenElevationType))
+ assert.Equal(t, "HIGH", e.GetParamAsString(params.ProcessTokenIntegrityLevel))
+ assert.True(t, e.Params.MustGetBool(params.ProcessTokenIsElevated))
+}
+
+func TestDecodeModule(t *testing.T) {
+ buf := []byte{
+ 0, 0, 32, 9, 253, 127, 0, 0,
+ 0, 128, 0, 0, 0, 0, 0, 0,
+ 168, 21, 0, 0,
+ 93, 190, 0, 0,
+ 32, 96, 25, 187, 12, 7, 0, 0,
+
+ 0, 0, 32, 9, 253, 127, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 92, 0,
+ 68, 0, 101, 0, 118, 0, 105, 0, 99, 0, 101, 0,
+ 92, 0,
+ 72, 0, 97, 0, 114, 0, 100, 0, 100, 0, 105, 0,
+ 115, 0, 107, 0,
+ 86, 0, 111, 0, 108, 0, 117, 0, 109, 0, 101, 0,
+ 51, 0,
+ 92, 0,
+ 87, 0, 105, 0, 110, 0, 100, 0, 111, 0, 119, 0,
+ 115, 0,
+ 92, 0,
+ 83, 0, 121, 0, 115, 0, 116, 0, 101, 0, 109, 0,
+ 51, 0, 50, 0,
+ 92, 0,
+ 110, 0, 111, 0, 114, 0, 109, 0, 97, 0, 108, 0,
+ 105, 0, 122, 0, 46, 0,
+ 100, 0, 108, 0, 108, 0,
+ 0, 0,
+ }
+
+ r := initEventRecord(0, 0, buf)
+ e := &Event{Params: make(Params)}
+ paramDecoder.DecodeModule(r, e)
+
+ assert.Len(t, e.Params, 8)
+ assert.Equal(t, uint64(0x7ffd09200000), e.Params.MustGetUint64(params.ModuleBase))
+ assert.Equal(t, uint32(48733), e.Params.MustGetUint32(params.ModuleCheckSum))
+ assert.Equal(t, uint64(0x7ffd09200000), e.Params.MustGetUint64(params.ModuleDefaultBase))
+ assert.Equal(t, `\Device\HarddiskVolume3\Windows\System32\normaliz.dll`, e.Params.MustGetString(params.ModulePath))
+ assert.Equal(t, uint64(32768), e.Params.MustGetUint64(params.ModuleSize))
+ assert.Equal(t, uint32(5544), e.Params.MustGetPid())
+ assert.Equal(t, "WINDOWS", e.GetParamAsString(params.ModuleSignatureLevel))
+ assert.Equal(t, "FILE_VERIFIED", e.GetParamAsString(params.ModuleSignatureType))
+}
+
+func TestDecodeModuleInternal(t *testing.T) {
+ buf := []byte{
+ 0, 0, 150, 252, 252, 127, 0, 0,
+ 0, 96, 8, 0, 0, 0, 0, 0,
+ 96, 68, 0, 0,
+ 231, 125, 8, 0,
+ 42, 234, 60, 109, 0, 0,
+
+ 150, 252, 252, 127, 0, 0,
+
+ 92, 0,
+ 68, 0, 101, 0, 118, 0, 105, 0, 99, 0, 101, 0,
+ 92, 0,
+ 72, 0, 97, 0, 114, 0, 100, 0, 100, 0, 105, 0,
+ 115, 0, 107, 0,
+ 86, 0, 111, 0, 108, 0, 117, 0, 109, 0, 101, 0,
+ 51, 0,
+ 92, 0,
+ 87, 0, 105, 0, 110, 0, 100, 0, 111, 0, 119, 0,
+ 115, 0,
+ 92, 0,
+ 83, 0, 121, 0, 115, 0, 116, 0, 101, 0, 109, 0,
+ 51, 0, 50, 0,
+ 92, 0,
+ 70, 0, 87, 0, 80, 0, 85, 0, 67, 0, 76, 0,
+ 78, 0, 84, 0, 46, 0,
+ 68, 0, 76, 0, 76, 0,
+ 0, 0,
+ }
+
+ r := initEventRecord(0, 0, buf)
+ e := &Event{Params: make(Params)}
+ paramDecoder.DecodeModuleInternal(r, e)
+
+ assert.Len(t, e.Params, 6)
+ assert.Equal(t, uint64(0x7ffcfc960000), e.Params.MustGetUint64(params.ModuleBase))
+ assert.Equal(t, uint32(556519), e.Params.MustGetUint32(params.ModuleCheckSum))
+ assert.Equal(t, uint64(0x7ffcfc960000), e.Params.MustGetUint64(params.ModuleDefaultBase))
+ assert.Equal(t, `\Device\HarddiskVolume3\Windows\System32\FWPUCLNT.DLL`, e.Params.MustGetString(params.ModulePath))
+ assert.Equal(t, uint64(548864), e.Params.MustGetUint64(params.ModuleSize))
+ assert.Equal(t, uint32(17504), e.Params.MustGetPid())
+}
+
+func TestDecodeOpenProcess(t *testing.T) {
+ buf := []byte{
+ 112, 22, 0, 0,
+ 0, 16, 0, 0,
+ 0, 0, 0, 0,
+ }
+
+ r := initEventRecord(0, 0, buf)
+ e := &Event{Params: make(Params)}
+ paramDecoder.DecodeOpenProcess(r, e)
+
+ assert.Len(t, e.Params, 4)
+ assert.Equal(t, "QUERY_LIMITED_INFORMATION", e.GetParamAsString(params.DesiredAccess))
+ assert.Equal(t, uint32(5744), e.Params.MustGetPid())
+ assert.Equal(t, uint32(0), e.Params.MustGetUint32(params.NTStatus))
+}
+
+func TestDecodeThread(t *testing.T) {
+ buf := []byte{
+ 8, 20, 0, 0,
+ 228, 6, 0, 0,
+ 0, 128,
+ 128, 12, 10, 252, 255, 255,
+ 0, 16,
+ 128, 12, 10, 252, 255, 255,
+ 0, 0,
+ 16, 206, 88, 0, 0, 0, 0, 128,
+ 15, 206, 88, 0, 0, 0, 255, 255,
+ 0, 0, 0, 0,
+ 128, 90, 99, 9, 253, 127, 0, 0,
+ 0, 240, 233, 205, 88, 0, 0, 0,
+ 0, 0, 0, 0,
+ 8, 5, 2, 0,
+ 0, 0,
+ }
+
+ r := initEventRecord(0, 0, buf)
+ e := &Event{Params: make(Params)}
+ paramDecoder.DecodeThread(r, e)
+
+ assert.Len(t, e.Params, 11)
+ assert.Equal(t, uint8(2), e.Params.MustGetUint8(params.BasePrio))
+ assert.Equal(t, uint8(0), e.Params.MustGetUint8(params.IOPrio))
+ assert.Equal(t, uint8(0), e.Params.MustGetUint8(params.PagePrio))
+ assert.Equal(t, uint64(0xfffffc0a0c808000), e.Params.MustGetUint64(params.KstackBase))
+ assert.Equal(t, uint64(0xfffffc0a0c801000), e.Params.MustGetUint64(params.KstackLimit))
+ assert.Equal(t, uint32(5128), e.Params.MustGetPid())
+ assert.Equal(t, uint32(1764), e.Params.MustGetTid())
+ assert.Equal(t, uint64(0xf00000007ffd0963), e.Params.MustGetUint64(params.StartAddress))
+ assert.Equal(t, uint64(0x58cde9), e.Params.MustGetUint64(params.TEB))
+ assert.Equal(t, uint64(0x58ce100000), e.Params.MustGetUint64(params.UstackBase))
+ assert.Equal(t, uint64(0x58ce0f8000), e.Params.MustGetUint64(params.UstackLimit))
+}
+
+func TestDecodeOpenThread(t *testing.T) {
+ buf := []byte{
+ 104, 17, 0, 0,
+ 76, 47, 0, 0,
+ 255, 255, 31, 0,
+ 0, 0, 0, 0,
+ }
+
+ r := initEventRecord(0, 0, buf)
+ e := &Event{Params: make(Params)}
+ paramDecoder.DecodeOpenThread(r, e)
+
+ assert.Len(t, e.Params, 5)
+ assert.Equal(t, "ALL_ACCESS", e.GetParamAsString(params.DesiredAccess))
+ assert.Equal(t, uint32(4456), e.Params.MustGetPid())
+ assert.Equal(t, uint32(12108), e.Params.MustGetTid())
+ assert.Equal(t, uint32(0), e.Params.MustGetUint32(params.NTStatus))
+}
+
+func TestDecodeSetThreadContext(t *testing.T) {
+ buf := []byte{
+ 0, 0, 0, 0,
+ }
+ r := initEventRecord(0, 0, buf)
+ e := &Event{Params: make(Params)}
+ paramDecoder.DecodeSetThreadContext(r, e)
+
+ assert.Len(t, e.Params, 2)
+ assert.Equal(t, uint32(0), e.Params.MustGetUint32(params.NTStatus))
+}
+
+func TestDecodeCreateSymbolicLinkObject(t *testing.T) {
+ buf := []byte{
+ 83, 0, 101, 0, 115, 0, 115, 0,
+ 105, 0, 111, 0, 110, 0, 0, 0,
+
+ 92, 0, 83, 0, 101, 0, 115, 0,
+ 115, 0, 105, 0, 111, 0, 110, 0,
+ 115, 0, 92, 0,
+ 49, 0,
+ 92, 0,
+ 65, 0, 112, 0, 112, 0,
+ 67, 0, 111, 0, 110, 0, 116, 0,
+ 97, 0, 105, 0, 110, 0, 101, 0,
+ 114, 0,
+ 78, 0, 97, 0, 109, 0, 101, 0,
+ 100, 0,
+ 79, 0, 98, 0, 106, 0, 101, 0,
+ 99, 0, 116, 0, 115, 0,
+ 92, 0,
+
+ 83, 0, 45, 0,
+ 49, 0, 45, 0,
+ 49, 0, 53, 0, 45, 0,
+ 50, 0, 45, 0,
+ 49, 0, 54, 0, 48, 0, 57, 0,
+ 52, 0, 55, 0, 51, 0, 55, 0,
+ 57, 0, 56, 0, 45, 0,
+ 49, 0, 50, 0, 51, 0, 49, 0,
+ 57, 0, 50, 0, 51, 0, 48, 0,
+ 49, 0, 55, 0, 45, 0,
+ 54, 0, 56, 0, 52, 0, 50, 0,
+ 54, 0, 56, 0, 49, 0, 53, 0,
+ 51, 0, 45, 0,
+ 52, 0, 50, 0, 54, 0, 56, 0,
+ 53, 0, 49, 0, 52, 0, 51, 0,
+ 50, 0, 56, 0, 45, 0,
+ 56, 0, 56, 0, 50, 0, 55, 0,
+ 55, 0, 51, 0, 54, 0, 52, 0,
+ 54, 0, 45, 0,
+ 50, 0, 55, 0, 54, 0, 48, 0,
+ 53, 0, 56, 0, 53, 0, 55, 0,
+ 55, 0, 51, 0, 45, 0,
+ 49, 0, 55, 0, 54, 0, 48, 0,
+ 57, 0, 51, 0, 56, 0, 49, 0,
+ 53, 0, 55, 0,
+ 0, 0,
+
+ 1, 0,
+ 15, 0,
+ 0, 0, 0, 0,
+ }
+
+ r := initEventRecord(0, 0, buf)
+ e := &Event{Params: make(Params)}
+ paramDecoder.DecodeCreateSymbolicLinkObject(r, e)
+
+ assert.Len(t, e.Params, 5)
+ assert.Equal(t, "DELETE|READ_CONTROL|WRITE_DAC|WRITE_OWNER", e.GetParamAsString(params.DesiredAccess))
+ assert.Equal(t, "Session", e.GetParamAsString(params.LinkSource))
+ assert.Equal(t, `\Sessions\1\AppContainerNamedObjects\S-1-15-2-1609473798-1231923017-684268153-4268514328-882773646-2760585773-1760938157`, e.GetParamAsString(params.LinkTarget))
+ assert.Equal(t, uint32(0), e.Params.MustGetUint32(params.NTStatus))
+}
+
+func TestDecodeStackWalk(t *testing.T) {
+ buf := []byte{
+ 41, 41, 119, 69, 58, 0, 0, 0,
+ 12, 15, 0, 0,
+ 160, 29, 0, 0,
+
+ 148, 12, 254, 189, 5, 248, 255, 255,
+ 175, 137, 229, 189, 5, 248, 255, 255,
+ 134, 47, 242, 189, 5, 248, 255, 255,
+ 36, 109, 255, 80, 5, 248, 255, 255,
+ 175, 186, 130, 79, 5, 248, 255, 255,
+ 160, 177, 130, 79, 5, 248, 255, 255,
+ 224, 104, 137, 79, 5, 248, 255, 255,
+ 59, 149, 250, 189, 5, 248, 255, 255,
+ 179, 148, 250, 189, 5, 248, 255, 255,
+ 59, 168, 73, 190, 5, 248, 255, 255,
+ 218, 136, 73, 190, 5, 248, 255, 255,
+ 227, 101, 73, 190, 5, 248, 255, 255,
+ 196, 202, 73, 190, 5, 248, 255, 255,
+ 85, 217, 43, 190, 5, 248, 255, 255,
+
+ 20, 69, 114, 9, 253, 127, 0, 0,
+ 31, 51, 25, 6, 253, 127, 0, 0,
+ 105, 96, 138, 36, 246, 127, 0, 0,
+ 109, 37, 146, 36, 246, 127, 0, 0,
+ 227, 37, 146, 36, 246, 127, 0, 0,
+ }
+
+ r := initEventRecord(0, 0, buf)
+ e := &Event{Params: make(Params)}
+ paramDecoder.DecodeStackwalk(r, e)
+
+ assert.Len(t, e.Params, 3)
+ assert.Equal(t, uint32(3852), e.Params.MustGetPid())
+ assert.Equal(t, uint32(7584), e.Params.MustGetTid())
+ assert.Equal(t, []va.Address{0xfffff805bdfe0c94, 0xfffff805bde589af, 0xfffff805bdf22f86, 0xfffff80550ff6d24, 0xfffff8054f82baaf, 0xfffff8054f82b1a0, 0xfffff8054f8968e0, 0xfffff805bdfa953b, 0xfffff805bdfa94b3, 0xfffff805be49a83b, 0xfffff805be4988da, 0xfffff805be4965e3, 0xfffff805be49cac4, 0xfffff805be2bd955, 0x7ffd09724514, 0x7ffd0619331f, 0x7ff6248a6069, 0x7ff62492256d, 0x7ff6249225e3}, e.Params.MustGetSlice(params.Callstack))
+}
+
+func TestDecodeMemory(t *testing.T) {
+ buf := []byte{
+ 0, 176, 27, 242, 110, 2, 0, 0,
+ 0, 16, 0, 0, 0, 0, 0, 0,
+ 112, 13, 0, 0,
+ 0, 16, 0, 0,
+ }
+
+ r := initEventRecord(0, 0, buf)
+ e := &Event{Params: make(Params)}
+ paramDecoder.DecodeMemory(r, e)
+
+ assert.Len(t, e.Params, 4)
+ assert.Equal(t, uint32(3440), e.Params.MustGetPid())
+ assert.Equal(t, uint64(4096), e.Params.MustGetUint64(params.MemRegionSize))
+ assert.Equal(t, uint64(0x26ef21bb000), e.Params.MustGetUint64(params.MemBaseAddress))
+ assert.Equal(t, "COMMIT", e.GetParamAsString(params.MemAllocType))
+}
+
+func TestDecodeNetwork(t *testing.T) {
+ var tests = []struct {
+ name string
+ opcode uint8
+ buf []byte
+ assertions func(t *testing.T, e *Event)
+ }{
+ {
+ name: "SendTCPv4", opcode: SendV4ID,
+ assertions: func(t *testing.T, e *Event) {
+ assert.Len(t, e.Params, 6)
+ assert.Equal(t, "172.64.148.235", e.GetParamAsString(params.NetDIP))
+ assert.Equal(t, uint16(443), e.Params.MustGetUint16(params.NetDport))
+ assert.Equal(t, "192.168.1.44", e.GetParamAsString(params.NetSIP))
+ assert.Equal(t, uint16(61552), e.Params.MustGetUint16(params.NetSport))
+ assert.Equal(t, uint32(12448), e.Params.MustGetPid())
+ assert.Equal(t, uint32(28), e.Params.MustGetUint32(params.NetSize))
+ },
+ buf: []byte{
+ 160, 48, 0, 0,
+ 28, 0, 0, 0,
+ 172, 64, 148, 235,
+ 192, 168, 1, 44,
+ 1, 187, 240, 112,
+ 106, 198, 40, 0,
+ 107, 198, 40, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ },
+ {
+ name: "ConnectTCPv4", opcode: ConnectTCPv4ID,
+ assertions: func(t *testing.T, e *Event) {
+ assert.Len(t, e.Params, 6)
+ assert.Equal(t, "151.101.193.91", e.GetParamAsString(params.NetDIP))
+ assert.Equal(t, uint16(443), e.Params.MustGetUint16(params.NetDport))
+ assert.Equal(t, "192.168.1.44", e.GetParamAsString(params.NetSIP))
+ assert.Equal(t, uint16(61931), e.Params.MustGetUint16(params.NetSport))
+ assert.Equal(t, uint32(12448), e.Params.MustGetPid())
+ assert.Equal(t, uint32(0), e.Params.MustGetUint32(params.NetSize))
+ },
+ buf: []byte{
+ 160, 48, 0, 0,
+ 0, 0, 0, 0,
+ 151, 101, 193, 91,
+ 192, 168, 1, 44,
+ 1, 187, 241, 235,
+ 0, 0, 1, 0,
+ 255, 255, 0, 0,
+ 8, 0, 9, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ },
+ {
+ name: "RecvUDPv6", opcode: RecvV6ID,
+ assertions: func(t *testing.T, e *Event) {
+ assert.Len(t, e.Params, 6)
+ assert.Equal(t, "ff02::c", e.GetParamAsString(params.NetDIP))
+ assert.Equal(t, uint16(1900), e.Params.MustGetUint16(params.NetDport))
+ assert.Equal(t, "fe80::1", e.GetParamAsString(params.NetSIP))
+ assert.Equal(t, uint16(56797), e.Params.MustGetUint16(params.NetSport))
+ assert.Equal(t, uint32(5128), e.Params.MustGetPid())
+ assert.Equal(t, uint32(127), e.Params.MustGetUint32(params.NetSize))
+ },
+ buf: []byte{
+ 8, 20, 0, 0,
+ 127, 0, 0, 0,
+ 255, 2, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 12,
+ 254, 128, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 1, 7, 108,
+ 221, 221, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ r := initEventRecord(tt.opcode, 0, tt.buf)
+ e := &Event{Params: make(Params)}
+ paramDecoder.DecodeNetwork(r, e)
+ tt.assertions(t, e)
+ })
+ }
+}
+
+func TestDecodeDNS(t *testing.T) {
+ buf := []byte{
+ 105, 0, 109, 0, 103, 0, 45, 0,
+ 112, 0, 114, 0, 111, 0, 100, 0,
+ 46, 0,
+ 112, 0, 111, 0, 99, 0, 107, 0,
+ 101, 0, 116, 0, 46, 0,
+ 112, 0, 114, 0, 111, 0, 100, 0,
+ 46, 0,
+ 99, 0, 108, 0, 111, 0, 117, 0,
+ 100, 0, 111, 0, 112, 0, 115, 0,
+ 46, 0,
+ 109, 0, 111, 0, 122, 0, 103, 0,
+ 99, 0, 112, 0, 46, 0,
+ 110, 0, 101, 0, 116, 0,
+ 0, 0,
+
+ 28, 0, 0, 0,
+ 193, 8, 16, 0,
+ 0, 128, 0, 0,
+ 0, 0, 0, 0,
+
+ 50, 0, 54, 0, 48, 0, 48, 0,
+ 58, 0, 49, 0, 57, 0, 48, 0,
+ 49, 0, 58, 0, 48, 0,
+ 58, 0, 101, 0, 57, 0, 56, 0,
+ 56, 0, 58, 0, 58, 0,
+ 59, 0,
+ 0, 0,
+ }
+
+ r := initEventRecord(0, ReplyDNSID, buf)
+ e := &Event{Params: make(Params)}
+ paramDecoder.DecodeDNS(r, e)
+
+ assert.Len(t, e.Params, 5)
+ assert.Equal(t, []string{"2600:1901:0:e988::", ""}, e.Params.MustGetSlice(params.DNSAnswers))
+ assert.Equal(t, "img-prod.pocket.prod.cloudops.mozgcp.net", e.Params.MustGetString(params.DNSName))
+ assert.Equal(t, "ACCEPT_TRUNCATED_RESPONSE|NO_NETBT|NO_MULTICAST|DONT_RESET_TTL_VALUES", e.GetParamAsString(params.DNSOpts))
+ assert.Equal(t, "NOERROR", e.GetParamAsString(params.DNSRcode))
+ assert.Equal(t, "AAAA", e.GetParamAsString(params.DNSRR))
+}
+
+func initEventRecord(opcode uint8, id uint16, buf []byte) *etw.EventRecord {
+ return &etw.EventRecord{
+ Header: etw.EventHeader{
+ ProcessID: 13440,
+ EventDescriptor: etw.EventDescriptor{
+ Opcode: opcode,
+ ID: id,
+ },
+ },
+ BufferLen: uint16(len(buf)),
+ Buffer: uintptr(unsafe.Pointer(&buf[0])),
+ }
+}
diff --git a/pkg/event/param_windows.go b/pkg/event/param_windows.go
index 322f7be9e..b5f437f1e 100644
--- a/pkg/event/param_windows.go
+++ b/pkg/event/param_windows.go
@@ -19,31 +19,24 @@
package event
import (
- "encoding/binary"
"expvar"
"fmt"
"net"
- "path/filepath"
"strconv"
"strings"
"time"
"unsafe"
- "github.com/rabbitstack/fibratus/pkg/util/utf16"
-
"github.com/rabbitstack/fibratus/pkg/event/params"
"github.com/rabbitstack/fibratus/pkg/fs"
htypes "github.com/rabbitstack/fibratus/pkg/handle/types"
"github.com/rabbitstack/fibratus/pkg/sys"
"github.com/rabbitstack/fibratus/pkg/sys/etw"
- "github.com/rabbitstack/fibratus/pkg/util/filetime"
"github.com/rabbitstack/fibratus/pkg/util/ip"
"github.com/rabbitstack/fibratus/pkg/util/key"
"github.com/rabbitstack/fibratus/pkg/util/ntstatus"
- "github.com/rabbitstack/fibratus/pkg/util/signature"
"github.com/rabbitstack/fibratus/pkg/util/va"
"golang.org/x/sys/windows"
- "golang.org/x/sys/windows/registry"
)
// unknownKeysCount counts the number of times the registry key failed to convert from native format
@@ -215,716 +208,55 @@ func (pars Params) MustGetSID() *windows.SID {
return sid
}
-// produceParams parses the event binary layout to extract
+var paramDecoder = &ParamDecoder{}
+
+// decodeParams parses the event binary layout to extract
// the parameters. Each event is annotated with the schema
// version number which helps us determine when the event
// schema changes in order to parse new fields.
-func (e *Event) produceParams(evt *etw.EventRecord) {
- switch e.Type {
- case ProcessRundown, CreateProcess, TerminateProcess:
- var (
- kproc uint64
- pid, ppid uint32
- sessionID uint32
- exitStatus uint32
- dtb uint64
- flags uint32
- sid []byte
- name string
- cmdline string
- )
- var offset uint16
- var soffset uint16
- var noffset uint16
- if evt.Version() >= 1 {
- pid = evt.ReadUint32(8)
- ppid = evt.ReadUint32(12)
- sessionID = evt.ReadUint32(16)
- exitStatus = evt.ReadUint32(20)
- }
- if evt.Version() >= 2 {
- kproc = evt.ReadUint64(0)
- }
- if evt.Version() >= 3 {
- dtb = evt.ReadUint64(24)
+func (e *Event) decodeParams(r *etw.EventRecord) {
+ switch r.Header.ProviderID {
+ case RegistryEventGUID:
+ paramDecoder.DecodeRegistry(r, e)
+ case FileEventGUID:
+ paramDecoder.DecodeFile(r, e)
+ case StackWalkEventGUID:
+ paramDecoder.DecodeStackwalk(r, e)
+ case AuditAPIEventGUID:
+ switch r.Header.EventDescriptor.ID {
+ case OpenProcessID:
+ paramDecoder.DecodeOpenProcess(r, e)
+ case OpenThreadID:
+ paramDecoder.DecodeOpenThread(r, e)
+ case SetThreadContextID:
+ paramDecoder.DecodeSetThreadContext(r, e)
+ case CreateSymbolicLinkObjectID:
+ paramDecoder.DecodeCreateSymbolicLinkObject(r, e)
+ }
+ case MemEventGUID:
+ paramDecoder.DecodeMemory(r, e)
+ case NetworkTCPEventGUID, NetworkUDPEventGUID:
+ paramDecoder.DecodeNetwork(r, e)
+ case DNSEventGUID:
+ paramDecoder.DecodeDNS(r, e)
+ case ProcessEventGUID:
+ paramDecoder.DecodeProcess(r, e)
+ case ModuleEventGUID:
+ paramDecoder.DecodeModule(r, e)
+ case ThreadEventGUID:
+ paramDecoder.DecodeThread(r, e)
+ case ThreadpoolEventGUID:
+ paramDecoder.DecodeThreadpool(r, e)
+ case HandleEventGUID:
+ paramDecoder.DecodeHandle(r, e)
+ case RegistryKernelEventGUID:
+ paramDecoder.DecodeRegSetValueInternal(r, e)
+ case ProcessKernelEventGUID:
+ switch r.Header.EventDescriptor.ID {
+ case CreateProcessInternalID, ProcessRundownInternalID:
+ paramDecoder.DecodeProcessInternal(r, e)
+ case LoadModuleInternalID:
+ paramDecoder.DecodeModuleInternal(r, e)
}
- if evt.Version() >= 4 {
- flags = evt.ReadUint32(32)
- }
- switch {
- case evt.Version() >= 4:
- offset = 36
- case evt.Version() >= 3:
- offset = 32
- default:
- offset = 24
- }
- sid, soffset = evt.ReadSID(offset, true)
- name, noffset = evt.ReadAnsiString(soffset)
- cmdline, _ = evt.ReadUTF16String(noffset)
- e.AppendParam(params.ProcessObject, params.Address, kproc)
- e.AppendParam(params.ProcessID, params.PID, pid)
- e.AppendParam(params.ProcessParentID, params.PID, ppid)
- e.AppendParam(params.ProcessRealParentID, params.PID, evt.Header.ProcessID)
- e.AppendParam(params.SessionID, params.Uint32, sessionID)
- e.AppendParam(params.ExitStatus, params.Status, exitStatus)
- e.AppendParam(params.DTB, params.Address, dtb)
- e.AppendParam(params.ProcessFlags, params.Flags, flags, WithFlags(PsCreationFlags))
- e.AppendParam(params.UserSID, params.WbemSID, sid)
- e.AppendParam(params.ProcessName, params.AnsiString, name)
- e.AppendParam(params.Cmdline, params.UnicodeString, cmdline)
- case CreateProcessInternal, ProcessRundownInternal:
- var (
- pid uint32
- createTime windows.Filetime
- ppid uint32
- sessionID uint32
- flags uint32
- tokenElevationType uint32
- tokenIsElevated uint32
- tokenMandatoryLabel []byte
- exe string
- )
-
- pid = evt.ReadUint32(0)
-
- if (e.IsCreateProcessInternal() && evt.Version() >= 3) || (e.IsProcessRundownInternal() && evt.Version() >= 1) {
- createTime = windows.NsecToFiletime(int64(evt.ReadUint64(12))) // skip sequence number (8 bytes)
-
- ppid = evt.ReadUint32(20)
- sessionID = evt.ReadUint32(32) // skip parent sequence number (8 bytes)
- flags = evt.ReadUint32(36)
- tokenElevationType = evt.ReadUint32(40)
- tokenIsElevated = evt.ReadUint32(44)
-
- tokenMandatoryLabel, _ = evt.ReadSID(48, false) // integrity level SID size is 12 bytes
-
- exe, _ = evt.ReadNTUnicodeString(60)
- } else {
- createTime = windows.NsecToFiletime(int64(evt.ReadUint64(8)))
- ppid = evt.ReadUint32(16)
- sessionID = evt.ReadUint32(20)
- flags = evt.ReadUint32(24)
- exe, _ = evt.ReadNTUnicodeString(28)
- }
-
- e.AppendParam(params.ProcessID, params.PID, pid)
- e.AppendParam(params.StartTime, params.Time, filetime.ToEpoch(uint64(createTime.Nanoseconds())))
- e.AppendParam(params.ProcessParentID, params.PID, ppid)
- e.AppendParam(params.SessionID, params.Uint32, sessionID)
- e.AppendParam(params.ProcessFlags, params.Flags, flags, WithFlags(PsCreationFlags))
- e.AppendParam(params.ProcessTokenElevationType, params.Enum, tokenElevationType, WithEnum(PsTokenElevationTypes))
- e.AppendParam(params.ProcessTokenIsElevated, params.Bool, tokenIsElevated > 0)
- e.AppendParam(params.ProcessTokenIntegrityLevel, params.SID, tokenMandatoryLabel)
- e.AppendParam(params.Exe, params.DOSPath, exe)
- case OpenProcess:
- processID := evt.ReadUint32(0)
- desiredAccess := evt.ReadUint32(4)
- status := evt.ReadUint32(8)
- e.AppendParam(params.ProcessID, params.PID, processID)
- e.AppendParam(params.DesiredAccess, params.Flags, desiredAccess, WithFlags(PsAccessRightFlags))
- e.AppendParam(params.NTStatus, params.Status, status)
-
- // append callstack for interested flags
- if desiredAccess == AllAccess || ((desiredAccess & windows.PROCESS_VM_READ) != 0) || ((desiredAccess & windows.PROCESS_VM_WRITE) != 0) ||
- ((desiredAccess & windows.PROCESS_VM_OPERATION) != 0) || ((desiredAccess & windows.PROCESS_DUP_HANDLE) != 0) ||
- ((desiredAccess & windows.PROCESS_TERMINATE) != 0) || ((desiredAccess & windows.PROCESS_CREATE_PROCESS) != 0) ||
- ((desiredAccess & windows.PROCESS_CREATE_THREAD) != 0) || ((desiredAccess & windows.PROCESS_SET_INFORMATION) != 0) {
- e.AppendParam(params.Callstack, params.Slice, evt.Callstack())
- }
- case CreateThread, TerminateThread, ThreadRundown:
- var (
- pid uint32
- tid uint32
- kstack, klimit uint64
- ustack, ulimit uint64
- startAddress uint64
- teb uint64
- basePrio uint8
- pagePrio uint8
- ioPrio uint8
- )
- if evt.Version() >= 1 {
- pid = evt.ReadUint32(0)
- tid = evt.ReadUint32(4)
- } else {
- pid = evt.ReadUint32(4)
- tid = evt.ReadUint32(0)
- }
- if evt.Version() >= 2 {
- kstack = evt.ReadUint64(8)
- klimit = evt.ReadUint64(16)
- ustack = evt.ReadUint64(24)
- ulimit = evt.ReadUint64(32)
- startAddress = evt.ReadUint64(48)
- teb = evt.ReadUint64(56)
- }
- if evt.Version() >= 3 {
- basePrio = evt.ReadByte(69)
- pagePrio = evt.ReadByte(70)
- ioPrio = evt.ReadByte(71)
- }
- e.AppendParam(params.ProcessID, params.PID, pid)
- e.AppendParam(params.ThreadID, params.TID, tid)
- e.AppendParam(params.KstackBase, params.Address, kstack)
- e.AppendParam(params.KstackLimit, params.Address, klimit)
- e.AppendParam(params.UstackBase, params.Address, ustack)
- e.AppendParam(params.UstackLimit, params.Address, ulimit)
- e.AppendParam(params.StartAddress, params.Address, startAddress)
- e.AppendParam(params.TEB, params.Address, teb)
- e.AppendParam(params.BasePrio, params.Uint8, basePrio)
- e.AppendParam(params.PagePrio, params.Uint8, pagePrio)
- e.AppendParam(params.IOPrio, params.Uint8, ioPrio)
- case OpenThread:
- processID := evt.ReadUint32(0)
- threadID := evt.ReadUint32(4)
- desiredAccess := evt.ReadUint32(8)
- status := evt.ReadUint32(12)
- e.AppendParam(params.ProcessID, params.PID, processID)
- e.AppendParam(params.ThreadID, params.TID, threadID)
- e.AppendParam(params.DesiredAccess, params.Flags, desiredAccess, WithFlags(ThreadAccessRightFlags))
- e.AppendParam(params.NTStatus, params.Status, status)
-
- // append callstack for interested flags
- if desiredAccess == AllAccess || ((desiredAccess & windows.THREAD_SET_CONTEXT) != 0) || ((desiredAccess & windows.THREAD_SET_THREAD_TOKEN) != 0) ||
- ((desiredAccess & windows.THREAD_IMPERSONATE) != 0) || ((desiredAccess & windows.THREAD_DIRECT_IMPERSONATION) != 0) ||
- ((desiredAccess & windows.THREAD_SUSPEND_RESUME) != 0) || ((desiredAccess & windows.THREAD_TERMINATE) != 0) ||
- ((desiredAccess & windows.THREAD_SET_INFORMATION) != 0) {
- e.AppendParam(params.Callstack, params.Slice, evt.Callstack())
- }
- case SetThreadContext:
- status := evt.ReadUint32(0)
- e.AppendParam(params.NTStatus, params.Status, status)
- if evt.HasStackTrace() {
- e.AppendParam(params.Callstack, params.Slice, evt.Callstack())
- }
- case CreateHandle, CloseHandle:
- object := evt.ReadUint64(0)
- handleID := evt.ReadUint32(8)
- typeID := evt.ReadUint16(12)
- var handleName string
- if evt.BufferLen >= 16 {
- handleName = evt.ConsumeUTF16String(14)
- }
- e.AppendParam(params.HandleObject, params.Address, object)
- e.AppendParam(params.HandleID, params.Uint32, handleID)
- e.AppendParam(params.HandleObjectTypeID, params.HandleType, typeID)
- e.AppendParam(params.HandleObjectName, params.UnicodeString, handleName)
- case DuplicateHandle:
- object := evt.ReadUint64(0)
- srcHandleID := evt.ReadUint32(8)
- dstHandleID := evt.ReadUint32(12)
- targetPID := evt.ReadUint32(16)
- typeID := evt.ReadUint16(20)
- sourcePID := evt.ReadUint32(22)
- e.AppendParam(params.HandleObject, params.Address, object)
- e.AppendParam(params.HandleID, params.Uint32, dstHandleID)
- e.AppendParam(params.HandleSourceID, params.Uint32, srcHandleID)
- e.AppendParam(params.HandleObjectTypeID, params.HandleType, typeID)
- e.AppendParam(params.ProcessID, params.PID, sourcePID)
- e.AppendParam(params.TargetProcessID, params.PID, targetPID)
- case LoadModule, UnloadModule, ModuleRundown:
- var (
- pid uint32
- checksum uint32
- defaultBase uint64
- filename string
- sigLevel, sigType uint8
- )
- var offset uint16
- imageBase := evt.ReadUint64(0)
- imageSize := evt.ReadUint64(8)
- if evt.Version() >= 1 {
- pid = evt.ReadUint32(16)
- }
- if evt.Version() >= 2 {
- checksum = evt.ReadUint32(20)
- defaultBase = evt.ReadUint64(30)
- }
- if evt.Version() >= 3 {
- sigLevel = evt.ReadByte(28)
- sigType = evt.ReadByte(29)
- defaultBase = evt.ReadUint64(32)
- }
- switch {
- case evt.Version() >= 3:
- offset = 56
- case evt.Version() >= 2:
- offset = 54
- case evt.Version() >= 1:
- offset = 20
- default:
- offset = 16
- }
- filename = evt.ConsumeUTF16String(offset)
- e.AppendParam(params.ProcessID, params.PID, pid)
- e.AppendParam(params.ModuleCheckSum, params.Uint32, checksum)
- e.AppendParam(params.ModuleDefaultBase, params.Address, defaultBase)
- e.AppendParam(params.ModuleBase, params.Address, imageBase)
- e.AppendParam(params.ModuleSize, params.Uint64, imageSize)
- e.AppendParam(params.ModulePath, params.DOSPath, filename)
- e.AppendParam(params.ModuleSignatureLevel, params.Enum, uint32(sigLevel), WithEnum(signature.Levels))
- e.AppendParam(params.ModuleSignatureType, params.Enum, uint32(sigType), WithEnum(signature.Types))
- case LoadModuleInternal:
- var (
- pid uint32
- checksum uint32
- defaultBase uint64
- imageBase uint64
- imageSize uint64
- filename string
- )
-
- imageBase = evt.ReadUint64(0)
- imageSize = evt.ReadUint64(8)
- pid = evt.ReadUint32(16)
- checksum = evt.ReadUint32(20)
- defaultBase = evt.ReadUint64(28) // skip timestamp (4 bytes)
- filename = evt.ConsumeUTF16String(36)
-
- e.AppendParam(params.ProcessID, params.PID, pid)
- e.AppendParam(params.ModuleCheckSum, params.Uint32, checksum)
- e.AppendParam(params.ModuleDefaultBase, params.Address, defaultBase)
- e.AppendParam(params.ModuleBase, params.Address, imageBase)
- e.AppendParam(params.ModuleSize, params.Uint64, imageSize)
- e.AppendParam(params.ModulePath, params.DOSPath, filename)
- case RegOpenKey, RegCloseKey,
- RegCreateKCB, RegDeleteKCB,
- RegKCBRundown, RegCreateKey,
- RegDeleteKey, RegDeleteValue,
- RegQueryKey, RegQueryValue,
- RegSetValue:
- var (
- status uint32
- keyHandle uint64
- keyName string
- )
- if evt.Version() >= 2 {
- status = evt.ReadUint32(8)
- keyHandle = evt.ReadUint64(16)
- } else {
- status = evt.ReadUint32(0)
- keyHandle = evt.ReadUint64(4)
- }
- if evt.Version() >= 1 {
- keyName = evt.ConsumeUTF16String(24)
- } else {
- keyName = evt.ConsumeUTF16String(20)
- }
- e.AppendParam(params.RegKeyHandle, params.Address, keyHandle)
- e.AppendParam(params.RegPath, params.Key, keyName)
- e.AppendParam(params.NTStatus, params.Status, status)
- case RegSetValueInternal:
- keyObject := evt.ReadUint64(0)
- status := evt.ReadUint32(8)
- valueType := evt.ReadUint32(12)
- keyName, koffset := evt.ReadUTF16String(20) // skip data size param (4 bytes)
- valueName, voffset := evt.ReadUTF16String(koffset)
- capturedSize := evt.ReadUint16(voffset)
- capturedData := evt.ReadBytes(2+voffset, capturedSize)
-
- // copy the buffer as it points to invalid
- // memory when the callback function returns
- b := make([]byte, capturedSize)
- copy(b, capturedData)
-
- e.AppendParam(params.RegKeyHandle, params.Address, keyObject)
- e.AppendParam(params.NTStatus, params.Status, status)
- e.AppendParam(params.RegPath, params.Key, filepath.Join(keyName, valueName))
- e.AppendEnum(params.RegValueType, valueType, key.RegistryValueTypes)
-
- if len(b) > 0 {
- switch valueType {
- case registry.SZ, registry.MULTI_SZ, registry.EXPAND_SZ:
- e.AppendParam(params.RegData, params.UnicodeString, utf16.BytesToString(b, binary.LittleEndian))
- case registry.BINARY:
- e.AppendParam(params.RegData, params.Binary, b)
- case registry.DWORD:
- var v uint32
- switch len(b) {
- case 4:
- v = binary.LittleEndian.Uint32(b)
- case 2:
- v = uint32(binary.LittleEndian.Uint16(b))
- case 1:
- v = uint32(b[0])
- }
- e.AppendParam(params.RegData, params.Uint32, v)
- case registry.DWORD_BIG_ENDIAN:
- var v uint32
- switch len(b) {
- case 4:
- v = binary.BigEndian.Uint32(b)
- case 2:
- v = uint32(binary.BigEndian.Uint16(b))
- case 1:
- v = uint32(b[0])
- }
- e.AppendParam(params.RegData, params.Uint32, v)
- case registry.QWORD:
- var v uint64
- switch len(b) {
- case 8:
- v = binary.LittleEndian.Uint64(b)
- case 4:
- v = uint64(binary.LittleEndian.Uint32(b))
- case 2:
- v = uint64(binary.LittleEndian.Uint16(b))
- case 1:
- v = uint64(b[0])
- }
- e.AppendParam(params.RegData, params.Uint64, v)
- }
- }
- case CreateFile:
- var (
- irp uint64
- fileObject uint64
- tid uint32
- createOptions uint32
- fileAttributes uint32
- shareAccess uint32
- filename string
- )
- if evt.Version() >= 2 {
- irp = evt.ReadUint64(0)
- fileObject = evt.ReadUint64(8)
- tid = evt.ReadUint32(16)
- createOptions = evt.ReadUint32(20)
- fileAttributes = evt.ReadUint32(24)
- shareAccess = evt.ReadUint32(28)
- filename = evt.ConsumeUTF16String(32)
- } else {
- fileObject = evt.ReadUint64(0)
- filename = evt.ConsumeUTF16String(8)
- }
- e.AppendParam(params.FileIrpPtr, params.Address, irp)
- e.AppendParam(params.FileObject, params.Address, fileObject)
- e.AppendParam(params.ThreadID, params.TID, tid)
- e.AppendParam(params.FileShareMask, params.Flags, shareAccess, WithFlags(FileShareModeFlags))
- e.AppendParam(params.FileAttributes, params.Flags, fileAttributes, WithFlags(FileAttributeFlags))
- e.AppendParam(params.FileCreateOptions, params.Flags, createOptions, WithFlags(FileCreateOptionsFlags))
- e.AppendParam(params.FilePath, params.DOSPath, filename)
- case FileOpEnd:
- var (
- irp uint64
- extraInfo uint64
- status uint32
- )
- if evt.Version() >= 2 {
- irp = evt.ReadUint64(0)
- extraInfo = evt.ReadUint64(8)
- status = evt.ReadUint32(16)
- }
- e.AppendParam(params.FileIrpPtr, params.Address, irp)
- e.AppendParam(params.FileExtraInfo, params.Address, extraInfo)
- e.AppendParam(params.NTStatus, params.Status, status)
- case FileRundown:
- var (
- fileObject uint64
- filename string
- )
- if evt.Version() >= 2 {
- fileObject = evt.ReadUint64(0)
- filename = evt.ConsumeUTF16String(8)
- }
- e.AppendParam(params.FileObject, params.Address, fileObject)
- e.AppendParam(params.FilePath, params.DOSPath, filename)
- case ReleaseFile, CloseFile:
- var (
- irp uint64
- fileObject uint64
- fileKey uint64
- tid uint32
- )
- if evt.Version() >= 2 {
- irp = evt.ReadUint64(0)
- }
- if evt.Version() >= 3 {
- fileObject = evt.ReadUint64(8)
- fileKey = evt.ReadUint64(16)
- tid = evt.ReadUint32(24)
- }
- e.AppendParam(params.FileIrpPtr, params.Address, irp)
- e.AppendParam(params.FileObject, params.Address, fileObject)
- e.AppendParam(params.FileKey, params.Address, fileKey)
- e.AppendParam(params.ThreadID, params.TID, tid)
- case DeleteFile, RenameFile, SetFileInformation:
- var (
- irp uint64
- fileObject uint64
- fileKey uint64
- tid uint32
- extraInfo uint64
- infoClass uint32
- )
- if evt.Version() >= 2 {
- irp = evt.ReadUint64(0)
- }
- if evt.Version() >= 3 {
- fileObject = evt.ReadUint64(8)
- fileKey = evt.ReadUint64(16)
- extraInfo = evt.ReadUint64(24)
- tid = evt.ReadUint32(32)
- infoClass = evt.ReadUint32(36)
- } else {
- tid = evt.ReadUint32(8)
- fileObject = evt.ReadUint64(12)
- fileKey = evt.ReadUint64(18)
- extraInfo = evt.ReadUint64(28)
- }
- e.AppendParam(params.FileIrpPtr, params.Address, irp)
- e.AppendParam(params.FileObject, params.Address, fileObject)
- e.AppendParam(params.FileKey, params.Address, fileKey)
- e.AppendParam(params.ThreadID, params.TID, tid)
- e.AppendParam(params.FileExtraInfo, params.Uint64, extraInfo)
- e.AppendParam(params.FileInfoClass, params.Enum, infoClass, WithEnum(fs.FileInfoClasses))
- case ReadFile, WriteFile:
- var (
- irp uint64
- offset uint64
- fileObject uint64
- fileKey uint64
- tid uint32
- size uint32
- )
- if evt.Version() >= 2 {
- offset = evt.ReadUint64(0)
- irp = evt.ReadUint64(8)
- }
- if evt.Version() >= 3 {
- fileObject = evt.ReadUint64(16)
- fileKey = evt.ReadUint64(24)
- tid = evt.ReadUint32(32)
- size = evt.ReadUint32(34)
- } else {
- fileObject = evt.ReadUint64(20)
- fileKey = evt.ReadUint64(28)
- tid = evt.ReadUint32(16)
- }
- e.AppendParam(params.FileIrpPtr, params.Address, irp)
- e.AppendParam(params.FileObject, params.Address, fileObject)
- e.AppendParam(params.FileKey, params.Address, fileKey)
- e.AppendParam(params.ThreadID, params.TID, tid)
- e.AppendParam(params.FileOffset, params.Uint64, offset)
- e.AppendParam(params.FileIoSize, params.Uint32, size)
- case EnumDirectory:
- var (
- irp uint64
- fileObject uint64
- fileKey uint64
- tid uint32
- infoClass uint32
- filename string
- )
- if evt.Version() >= 2 {
- irp = evt.ReadUint64(0)
- }
- if evt.Version() >= 3 {
- fileObject = evt.ReadUint64(8)
- fileKey = evt.ReadUint64(16)
- tid = evt.ReadUint32(24)
- infoClass = evt.ReadUint32(32)
- filename = evt.ConsumeUTF16String(38)
- } else {
- tid = evt.ReadUint32(8)
- fileObject = evt.ReadUint64(12)
- fileKey = evt.ReadUint64(20)
- }
- e.AppendParam(params.FileIrpPtr, params.Address, irp)
- e.AppendParam(params.FileObject, params.Address, fileObject)
- e.AppendParam(params.ThreadID, params.TID, tid)
- e.AppendParam(params.FileKey, params.Address, fileKey)
- e.AppendParam(params.FilePath, params.UnicodeString, filename)
- e.AppendParam(params.FileInfoClass, params.Enum, infoClass, WithEnum(fs.FileInfoClasses))
- case MapViewFile, UnmapViewFile, MapFileRundown:
- var (
- viewBase uint64
- fileKey uint64
- extraInfo uint64
- viewSize uint64
- pid uint32
- offset uint64
- )
- viewBase = evt.ReadUint64(0)
- fileKey = evt.ReadUint64(8)
- extraInfo = evt.ReadUint64(16)
- viewSize = evt.ReadUint64(24)
- if evt.Version() >= 3 {
- offset = evt.ReadUint64(32)
- }
- if evt.Version() >= 3 {
- pid = evt.ReadUint32(40)
- } else {
- pid = evt.ReadUint32(32)
- }
- protect := uint32(extraInfo >> 32)
- section := uint32(extraInfo >> 52)
- e.AppendParam(params.FileViewBase, params.Address, viewBase)
- e.AppendParam(params.FileKey, params.Address, fileKey)
- e.AppendParam(params.FileViewSize, params.Uint64, viewSize)
- e.AppendParam(params.FileOffset, params.Uint64, offset)
- e.AppendParam(params.ProcessID, params.PID, pid)
- e.AppendParam(params.MemProtect, params.Flags, protect, WithFlags(ViewProtectionFlags))
- e.AppendParam(params.FileViewSectionType, params.Enum, section, WithEnum(ViewSectionTypes))
- case SendTCPv4,
- SendUDPv4,
- RecvTCPv4,
- RecvUDPv4,
- DisconnectTCPv4,
- RetransmitTCPv4,
- ReconnectTCPv4,
- ConnectTCPv4,
- AcceptTCPv4:
- var (
- pid uint32
- size uint32
- dip uint32
- sip uint32
- dport uint16
- sport uint16
- )
- if evt.Version() >= 1 {
- pid = evt.ReadUint32(0)
- size = evt.ReadUint32(4)
- dip = evt.ReadUint32(8)
- sip = evt.ReadUint32(12)
- dport = evt.ReadUint16(16)
- sport = evt.ReadUint16(18)
- } else {
- dip = evt.ReadUint32(0)
- sip = evt.ReadUint32(4)
- dport = evt.ReadUint16(8)
- sport = evt.ReadUint16(10)
- size = evt.ReadUint32(12)
- pid = evt.ReadUint32(16)
- }
- e.AppendParam(params.ProcessID, params.PID, pid)
- e.AppendParam(params.NetSize, params.Uint32, size)
- e.AppendParam(params.NetDIP, params.IPv4, dip)
- e.AppendParam(params.NetSIP, params.IPv4, sip)
- e.AppendParam(params.NetDport, params.Port, dport)
- e.AppendParam(params.NetSport, params.Port, sport)
- case SendTCPv6,
- SendUDPv6,
- RecvTCPv6,
- RecvUDPv6,
- DisconnectTCPv6,
- RetransmitTCPv6,
- ReconnectTCPv6,
- ConnectTCPv6,
- AcceptTCPv6:
- var (
- pid uint32
- size uint32
- dip []byte
- sip []byte
- dport uint16
- sport uint16
- )
- if evt.Version() >= 2 {
- pid = evt.ReadUint32(0)
- size = evt.ReadUint32(4)
- dip = evt.ReadBytes(8, 16)
- sip = evt.ReadBytes(24, 16)
- dport = evt.ReadUint16(40)
- sport = evt.ReadUint16(42)
- }
- e.AppendParam(params.ProcessID, params.PID, pid)
- e.AppendParam(params.NetSize, params.Uint32, size)
- e.AppendParam(params.NetDIP, params.IPv6, dip)
- e.AppendParam(params.NetSIP, params.IPv6, sip)
- e.AppendParam(params.NetDport, params.Port, dport)
- e.AppendParam(params.NetSport, params.Port, sport)
- case VirtualAlloc, VirtualFree:
- var (
- baseAddress uint64
- regionSize uint64
- pid uint32
- flags uint32
- )
- if evt.Version() >= 1 {
- baseAddress = evt.ReadUint64(0)
- regionSize = evt.ReadUint64(8)
- pid = evt.ReadUint32(16)
- flags = evt.ReadUint32(20)
- }
- e.AppendParam(params.MemBaseAddress, params.Address, baseAddress)
- e.AppendParam(params.MemRegionSize, params.Uint64, regionSize)
- e.AppendParam(params.ProcessID, params.PID, pid)
- e.AppendParam(params.MemAllocType, params.Flags, flags, WithFlags(MemAllocationFlags))
- case QueryDNS, ReplyDNS:
- var (
- name string
- rr uint32
- opts uint64
- )
- var offset uint16
- name, offset = evt.ReadUTF16String(0)
- rr = evt.ReadUint32(offset)
- opts = evt.ReadUint64(offset + 4)
- e.AppendParam(params.DNSName, params.UnicodeString, name)
- e.AppendParam(params.DNSRR, params.Enum, rr, WithEnum(DNSRecordTypes))
- e.AppendParam(params.DNSOpts, params.Flags64, opts, WithFlags(DNSOptsFlags))
- if e.Type == ReplyDNS {
- rcode := evt.ReadUint32(offset + 12)
- answers := evt.ConsumeUTF16String(offset + 16)
- e.AppendParam(params.DNSRcode, params.Enum, rcode, WithEnum(DNSResponseCodes))
- e.AppendParam(params.DNSAnswers, params.Slice, strings.Split(sanitizeDNSAnswers(answers), ";"))
- }
- case StackWalk:
- e.AppendParam(params.ProcessID, params.PID, evt.ReadUint32(8))
- e.AppendParam(params.ThreadID, params.TID, evt.ReadUint32(12))
- var n uint16
- var offset uint16 = 16
- frames := (evt.BufferLen - offset) / 8
- callstack := make([]va.Address, frames)
- for n < frames {
- callstack[n] = va.Address(evt.ReadUint64(offset))
- offset += 8
- n++
- }
- e.AppendParam(params.Callstack, params.Slice, callstack)
- case CreateSymbolicLinkObject:
- source, offset := evt.ReadUTF16String(0)
- target, offset := evt.ReadUTF16String(offset)
- desiredAccess := evt.ReadUint32(offset)
- status := evt.ReadUint32(offset + 4)
- e.AppendParam(params.LinkSource, params.UnicodeString, source)
- e.AppendParam(params.LinkTarget, params.UnicodeString, target)
- e.AppendParam(params.DesiredAccess, params.Flags, desiredAccess, WithFlags(AccessMaskFlags))
- e.AppendParam(params.NTStatus, params.Status, status)
- if evt.HasStackTrace() {
- e.AppendParam(params.Callstack, params.Slice, evt.Callstack())
- }
- case SubmitThreadpoolWork, SubmitThreadpoolCallback:
- poolID := evt.ReadUint64(0)
- taskID := evt.ReadUint64(8)
- callback := evt.ReadUint64(16)
- ctx := evt.ReadUint64(24)
- tag := evt.ReadUint64(32)
- e.AppendParam(params.ThreadpoolPoolID, params.Address, poolID)
- e.AppendParam(params.ThreadpoolTaskID, params.Address, taskID)
- e.AppendParam(params.ThreadpoolCallback, params.Address, callback)
- e.AppendParam(params.ThreadpoolContext, params.Address, ctx)
- e.AppendParam(params.ThreadpoolSubprocessTag, params.Address, tag)
- case SetThreadpoolTimer:
- duetime := evt.ReadUint64(0)
- subqueue := evt.ReadUint64(8)
- timer := evt.ReadUint64(16)
- period := evt.ReadUint32(24)
- window := evt.ReadUint32(28)
- absolute := evt.ReadUint32(32)
- e.AppendParam(params.ThreadpoolTimerDuetime, params.Uint64, duetime)
- e.AppendParam(params.ThreadpoolTimerSubqueue, params.Address, subqueue)
- e.AppendParam(params.ThreadpoolTimer, params.Address, timer)
- e.AppendParam(params.ThreadpoolTimerPeriod, params.Uint32, period)
- e.AppendParam(params.ThreadpoolTimerWindow, params.Uint32, window)
- e.AppendParam(params.ThreadpoolTimerAbsolute, params.Bool, absolute > 0)
}
}
-
-// sanitizeDNSAnswers removes the "type" string from DNS answers.
-func sanitizeDNSAnswers(answers string) string {
- return strings.ReplaceAll(answers, "type: 5 ", "")
-}
diff --git a/pkg/event/types_windows.go b/pkg/event/types_windows.go
index 157ed50de..93ff22551 100644
--- a/pkg/event/types_windows.go
+++ b/pkg/event/types_windows.go
@@ -31,7 +31,7 @@ import (
type Source uint8
const (
- // SystemLogger event is emitted by the system provider
+ // SystemLogger event is emitted by the system provider.
SystemLogger Source = iota
// SecurityTelemetryLogger event is emitted by the combination of multiple providers.
// Most notably, DNS, thread pool, and kernel audit API providers are in charge of
@@ -65,174 +65,257 @@ var (
AuditAPIEventGUID = windows.GUID{Data1: 0xe02a841c, Data2: 0x75a3, Data3: 0x4fa7, Data4: [8]byte{0xaf, 0xc8, 0xae, 0x09, 0xcf, 0x9b, 0x7f, 0x23}}
// DNSEventGUID represents DNS provider event GUID
DNSEventGUID = windows.GUID{Data1: 0x1c95126e, Data2: 0x7eea, Data3: 0x49a9, Data4: [8]byte{0xa3, 0xfe, 0xa3, 0x78, 0xb0, 0x3d, 0xdb, 0x4d}}
- // ThreadpoolGUID represents the thread pool event GUID
- ThreadpoolGUID = windows.GUID{Data1: 0xc861d0e2, Data2: 0xa2c1, Data3: 0x4d36, Data4: [8]byte{0x9f, 0x9c, 0x97, 0x0b, 0xab, 0x94, 0x3a, 0x12}}
+ // ThreadpoolEventGUID represents the thread pool event GUID
+ ThreadpoolEventGUID = windows.GUID{Data1: 0xc861d0e2, Data2: 0xa2c1, Data3: 0x4d36, Data4: [8]byte{0x9f, 0x9c, 0x97, 0x0b, 0xab, 0x94, 0x3a, 0x12}}
// ProcessKernelEventGUID represents the Process Kernel event GUID
ProcessKernelEventGUID = windows.GUID{Data1: 0x22fb2cd6, Data2: 0x0e7b, Data3: 0x422b, Data4: [8]byte{0xa0, 0xc7, 0x2f, 0xad, 0x1f, 0xd0, 0xe7, 0x16}}
// RegistryKernelEventGUID represents the Registry Kernel event GUID
RegistryKernelEventGUID = windows.GUID{Data1: 0x70eb4f03, Data2: 0xc1de, Data3: 0x4f73, Data4: [8]byte{0xa0, 0x51, 0x33, 0xd1, 0x3d, 0x54, 0x13, 0xbd}}
+ // StackWalkEventGUID represents the StackWalk event GUID
+ StackWalkEventGUID = windows.GUID{Data1: 0xdef2fe46, Data2: 0x7bd6, Data3: 0x4b80, Data4: [8]byte{0xbd, 0x94, 0xf5, 0x7f, 0xe2, 0x0d, 0x0c, 0xe3}}
+)
+
+const (
+ CreateProcessID uint8 = 1
+ CreateProcessInternalID uint16 = 1
+ TerminateProcessID uint8 = 2
+ ProcessRundownID uint8 = 3
+ OpenProcessID uint16 = 5
+ ProcessRundownInternalID uint16 = 15
+
+ CreateThreadID uint8 = 1
+ TerminateThreadID uint8 = 2
+ ThreadRundownID uint8 = 3
+ SetThreadContextID uint16 = 4
+ OpenThreadID uint16 = 6
+
+ UnloadModuleID uint8 = 2
+ ModuleRundownID uint8 = 3
+ LoadModuleInternalID uint16 = 5
+ LoadModuleID uint8 = 10
+
+ FileRundownID uint8 = 36
+ MapViewFileID uint8 = 37
+ UnmapViewFileID uint8 = 38
+ MapFileRundownID uint8 = 39
+ CreateFileID uint8 = 64
+ ReleaseFileID uint8 = 65
+ CloseFileID uint8 = 66
+ ReadFileID uint8 = 67
+ WriteFileID uint8 = 68
+ SetFileInformationID uint8 = 69
+ DeleteFileID uint8 = 70
+ RenameFileID uint8 = 71
+ EnumDirectoryID uint8 = 72
+ FileOpEndID uint8 = 76
+
+ RegCreateKeyID uint8 = 10
+ RegOpenKeyID uint8 = 11
+ RegDeleteKeyID uint8 = 12
+ RegQueryKeyID uint8 = 13
+ RegSetValueID uint8 = 14
+ RegDeleteValueID uint8 = 15
+ RegQueryValueID uint8 = 16
+ RegCreateKCBID uint8 = 22
+ RegDeleteKCBID uint8 = 23
+ RegKCBRundownID uint8 = 25
+ RegCloseKeyID uint8 = 27
+ RegSetValueInternalID uint16 = 36
+
+ AcceptTCPv4ID uint8 = 15
+ AcceptTCPv6ID uint8 = 31
+ SendV4ID uint8 = 10
+ SendV6ID uint8 = 26
+ RecvV4ID uint8 = 11
+ RecvV6ID uint8 = 27
+ ConnectTCPv4ID uint8 = 12
+ ConnectTCPv6ID uint8 = 28
+ DisconnectTCPv4ID uint8 = 13
+ DisconnectTCPv6ID uint8 = 29
+ ReconnectTCPv4ID uint8 = 16
+ ReconnectTCPv6ID uint8 = 32
+ RetransmitTCPv4ID uint8 = 14
+ RetransmitTCPv6ID uint8 = 30
+
+ VirtualAllocID uint8 = 98
+ VirtualFreeID uint8 = 99
+
+ CreateHandleID uint8 = 32
+ CloseHandleID uint8 = 33
+ DuplicateHandleID uint8 = 34
+
+ QueryDNSID uint16 = 3006
+ ReplyDNSID uint16 = 3008
+
+ CreateSymbolicLinkObjectID uint16 = 3
+
+ StackWalkID uint8 = 32
+
+ SubmitThreadpoolWorkID uint8 = 32
+ SubmitThreadpoolCallbackID uint8 = 34
+ SetThreadpoolTimerID uint8 = 44
)
var (
// CreateProcess identifies process creation kernel events
- CreateProcess = pack(ProcessEventGUID, 1)
+ CreateProcess = pack(ProcessEventGUID, uint16(CreateProcessID))
// TerminateProcess identifies process termination kernel events
- TerminateProcess = pack(ProcessEventGUID, 2)
+ TerminateProcess = pack(ProcessEventGUID, uint16(TerminateProcessID))
// ProcessRundown represents the start data collection process event that enumerates processes that are currently running at the time the kernel session starts
- ProcessRundown = pack(ProcessEventGUID, 3)
+ ProcessRundown = pack(ProcessEventGUID, uint16(ProcessRundownID))
// OpenProcess identifies the kernel events that are triggered when the process handle is acquired
- OpenProcess = pack(AuditAPIEventGUID, 5)
+ OpenProcess = pack(AuditAPIEventGUID, OpenProcessID)
// CreateProcessInternal identifies the process creation event emitted by the Microsoft Windows Kernel Process provider.
// The only purpose of this event is to enrich the process state with some extra attributes, and populates the snapshotter
// for events running in the Security Telemetry session that might miss process lookups because the core NT Kernel Provider
// hasn't still published the CreateProcess or ProcessRundown event
- CreateProcessInternal = pack(ProcessKernelEventGUID, 1)
+ CreateProcessInternal = pack(ProcessKernelEventGUID, CreateProcessInternalID)
// ProcessRundownInternal same as above but for process rundown events originating from the Microsoft Windows Kernel Process provider.
- ProcessRundownInternal = pack(ProcessKernelEventGUID, 15)
+ ProcessRundownInternal = pack(ProcessKernelEventGUID, ProcessRundownInternalID)
// CreateThread identifies thread creation kernel events
- CreateThread = pack(ThreadEventGUID, 1)
+ CreateThread = pack(ThreadEventGUID, uint16(CreateThreadID))
// TerminateThread identifies thread termination kernel events
- TerminateThread = pack(ThreadEventGUID, 2)
+ TerminateThread = pack(ThreadEventGUID, uint16(TerminateThreadID))
// ThreadRundown represents the start data collection thread event that enumerates threads that are currently running at the time the kernel session starts
- ThreadRundown = pack(ThreadEventGUID, 3)
+ ThreadRundown = pack(ThreadEventGUID, uint16(ThreadRundownID))
// OpenThread identifies the kernel events that are triggered when the process acquires a thread handle
- OpenThread = pack(AuditAPIEventGUID, 6)
+ OpenThread = pack(AuditAPIEventGUID, OpenThreadID)
// SetThreadContext identifies the kernel event that is fired when the thread context is changed
- SetThreadContext = pack(AuditAPIEventGUID, 4)
+ SetThreadContext = pack(AuditAPIEventGUID, SetThreadContextID)
// MapViewFile represents events that map a view of a file mapping into the address space of a calling process
- MapViewFile = pack(FileEventGUID, 37)
+ MapViewFile = pack(FileEventGUID, uint16(MapViewFileID))
// UnmapViewFile represents events that unmap a view of a file mapping from the address space of a calling process
- UnmapViewFile = pack(FileEventGUID, 38)
+ UnmapViewFile = pack(FileEventGUID, uint16(UnmapViewFileID))
// MapFileRundown represents the event that is emitted at the start of the tracing session to enumerate I/O mapped files
- MapFileRundown = pack(FileEventGUID, 39)
+ MapFileRundown = pack(FileEventGUID, uint16(MapFileRundownID))
// FileRundown events are generated by kernel rundown logger to enumerate all open files on the start of the kernel session
- FileRundown = pack(FileEventGUID, 36)
+ FileRundown = pack(FileEventGUID, uint16(FileRundownID))
// CreateFile represents events that create/open a file or I/O device
- CreateFile = pack(FileEventGUID, 64)
+ CreateFile = pack(FileEventGUID, uint16(CreateFileID))
// ReleaseFile represents events that occur when the last file handle is disposed
- ReleaseFile = pack(FileEventGUID, 65)
+ ReleaseFile = pack(FileEventGUID, uint16(ReleaseFileID))
// CloseFile represents events that dispose existing kernel file objects
- CloseFile = pack(FileEventGUID, 66)
+ CloseFile = pack(FileEventGUID, uint16(CloseFileID))
// ReadFile represents events that read data from the file or I/O device
- ReadFile = pack(FileEventGUID, 67)
+ ReadFile = pack(FileEventGUID, uint16(ReadFileID))
// WriteFile represents events that write data to the file or I/O device
- WriteFile = pack(FileEventGUID, 68)
+ WriteFile = pack(FileEventGUID, uint16(WriteFileID))
// SetFileInformation represents events that set file information
- SetFileInformation = pack(FileEventGUID, 69)
+ SetFileInformation = pack(FileEventGUID, uint16(SetFileInformationID))
// DeleteFile identifies file deletion events
- DeleteFile = pack(FileEventGUID, 70)
+ DeleteFile = pack(FileEventGUID, uint16(DeleteFileID))
// RenameFile identifies events that are responsible for renaming files
- RenameFile = pack(FileEventGUID, 71)
+ RenameFile = pack(FileEventGUID, uint16(RenameFileID))
// EnumDirectory identifies enumerate directory and directory notification events
- EnumDirectory = pack(FileEventGUID, 72)
+ EnumDirectory = pack(FileEventGUID, uint16(EnumDirectoryID))
// FileOpEnd signals the finalization of the file operation
- FileOpEnd = pack(FileEventGUID, 76)
+ FileOpEnd = pack(FileEventGUID, uint16(FileOpEndID))
// RegCreateKey represents registry key creation kernel events
- RegCreateKey = pack(RegistryEventGUID, 10)
+ RegCreateKey = pack(RegistryEventGUID, uint16(RegCreateKeyID))
// RegOpenKey represents registry open key kernel events
- RegOpenKey = pack(RegistryEventGUID, 11)
+ RegOpenKey = pack(RegistryEventGUID, uint16(RegOpenKeyID))
// RegCloseKey represents registry close key kernel event.
- RegCloseKey = pack(RegistryEventGUID, 27)
+ RegCloseKey = pack(RegistryEventGUID, uint16(RegCloseKeyID))
// RegDeleteKey represents registry key deletion kernel events
- RegDeleteKey = pack(RegistryEventGUID, 12)
+ RegDeleteKey = pack(RegistryEventGUID, uint16(RegDeleteKeyID))
// RegQueryKey represents registry query key kernel events
- RegQueryKey = pack(RegistryEventGUID, 13)
+ RegQueryKey = pack(RegistryEventGUID, uint16(RegQueryKeyID))
// RegSetValue represents registry set value kernel events
- RegSetValue = pack(RegistryEventGUID, 14)
+ RegSetValue = pack(RegistryEventGUID, uint16(RegSetValueID))
// RegDeleteValue are kernel events for registry value removals
- RegDeleteValue = pack(RegistryEventGUID, 15)
+ RegDeleteValue = pack(RegistryEventGUID, uint16(RegDeleteValueID))
// RegQueryValue are kernel events for registry value queries
- RegQueryValue = pack(RegistryEventGUID, 16)
+ RegQueryValue = pack(RegistryEventGUID, uint16(RegQueryValueID))
// RegCreateKCB represents kernel events for KCB (Key Control Block) creation requests
- RegCreateKCB = pack(RegistryEventGUID, 22)
+ RegCreateKCB = pack(RegistryEventGUID, uint16(RegCreateKCBID))
// RegDeleteKCB represents kernel events for KCB(Key Control Block) closures
- RegDeleteKCB = pack(RegistryEventGUID, 23)
+ RegDeleteKCB = pack(RegistryEventGUID, uint16(RegDeleteKCBID))
// RegKCBRundown enumerates the registry keys open at the start of the kernel session.
- RegKCBRundown = pack(RegistryEventGUID, 25)
+ RegKCBRundown = pack(RegistryEventGUID, uint16(RegKCBRundownID))
// RegSetValueInternal is the internal event that is used to
// enrich the corresponding public RegSetValue event with
// extra attributes
- RegSetValueInternal = pack(RegistryKernelEventGUID, 36)
+ RegSetValueInternal = pack(RegistryKernelEventGUID, RegSetValueInternalID)
// UnloadModule represents unload module kernel events
- UnloadModule = pack(ModuleEventGUID, 2)
+ UnloadModule = pack(ModuleEventGUID, uint16(UnloadModuleID))
// ModuleRundown represents kernel events that is triggered to enumerate all loaded modules
- ModuleRundown = pack(ModuleEventGUID, 3)
+ ModuleRundown = pack(ModuleEventGUID, uint16(ModuleRundownID))
// LoadModule represents module load kernel events that are triggered when a DLL or executable file is loaded
- LoadModule = pack(ModuleEventGUID, 10)
+ LoadModule = pack(ModuleEventGUID, uint16(LoadModuleID))
// LoadModuleInternal same as for process internal event originating from the Microsoft Windows Kernel Process provider
- LoadModuleInternal = pack(ProcessKernelEventGUID, 5)
+ LoadModuleInternal = pack(ProcessKernelEventGUID, LoadModuleInternalID)
// AcceptTCPv4 represents the TCPv4 kernel events for accepting connection requests from the socket queue.
- AcceptTCPv4 = pack(NetworkTCPEventGUID, 15)
+ AcceptTCPv4 = pack(NetworkTCPEventGUID, uint16(AcceptTCPv4ID))
// AcceptTCPv6 represents the TCPv6 kernel events for accepting connection requests from the socket queue.
- AcceptTCPv6 = pack(NetworkTCPEventGUID, 31)
+ AcceptTCPv6 = pack(NetworkTCPEventGUID, uint16(AcceptTCPv6ID))
// SendTCPv4 represents the TCPv4 kernel events for sending data to the connected socket.
- SendTCPv4 = pack(NetworkTCPEventGUID, 10)
+ SendTCPv4 = pack(NetworkTCPEventGUID, uint16(SendV4ID))
// SendTCPv6 represents the TCPv6 kernel events for sending data to the connected socket.
- SendTCPv6 = pack(NetworkTCPEventGUID, 26)
+ SendTCPv6 = pack(NetworkTCPEventGUID, uint16(SendV6ID))
// SendUDPv4 represents the UDPv4 kernel events for sending datagrams to connectionless sockets.
- SendUDPv4 = pack(NetworkUDPEventGUID, 10)
+ SendUDPv4 = pack(NetworkUDPEventGUID, uint16(SendV4ID))
// SendUDPv6 represents the UDPv6 kernel events for sending datagrams to connectionless sockets.
- SendUDPv6 = pack(NetworkUDPEventGUID, 26)
+ SendUDPv6 = pack(NetworkUDPEventGUID, uint16(SendV6ID))
// RecvTCPv4 represents the TCP IPv4 network receive event.
- RecvTCPv4 = pack(NetworkTCPEventGUID, 11)
+ RecvTCPv4 = pack(NetworkTCPEventGUID, uint16(RecvV4ID))
// RecvTCPv6 represents the TCP IPv6 network receive event.
- RecvTCPv6 = pack(NetworkTCPEventGUID, 27)
+ RecvTCPv6 = pack(NetworkTCPEventGUID, uint16(RecvV6ID))
// RecvUDPv4 represents the UDP IPv4 network receive event.
- RecvUDPv4 = pack(NetworkUDPEventGUID, 11)
+ RecvUDPv4 = pack(NetworkUDPEventGUID, uint16(RecvV4ID))
// RecvUDPv6 represents the UDP IPv6 network receive event.
- RecvUDPv6 = pack(NetworkUDPEventGUID, 27)
+ RecvUDPv6 = pack(NetworkUDPEventGUID, uint16(RecvV6ID))
// ConnectTCPv4 represents the TCP IPv4 network connect event.
- ConnectTCPv4 = pack(NetworkTCPEventGUID, 12)
+ ConnectTCPv4 = pack(NetworkTCPEventGUID, uint16(ConnectTCPv4ID))
// ConnectTCPv6 represents the TCP IPv6 network connect event.
- ConnectTCPv6 = pack(NetworkTCPEventGUID, 28)
+ ConnectTCPv6 = pack(NetworkTCPEventGUID, uint16(ConnectTCPv6ID))
// DisconnectTCPv4 is the TCP IPv4 network disconnect event.
- DisconnectTCPv4 = pack(NetworkTCPEventGUID, 13)
+ DisconnectTCPv4 = pack(NetworkTCPEventGUID, uint16(DisconnectTCPv4ID))
// DisconnectTCPv6 is the TCP IPv6 network disconnect event.
- DisconnectTCPv6 = pack(NetworkTCPEventGUID, 29)
+ DisconnectTCPv6 = pack(NetworkTCPEventGUID, uint16(DisconnectTCPv6ID))
// ReconnectTCPv4 is the TCP IPv4 network reconnect event.
- ReconnectTCPv4 = pack(NetworkTCPEventGUID, 16)
+ ReconnectTCPv4 = pack(NetworkTCPEventGUID, uint16(ReconnectTCPv4ID))
// ReconnectTCPv6 is the TCP IPv6 network reconnect event.
- ReconnectTCPv6 = pack(NetworkTCPEventGUID, 32)
+ ReconnectTCPv6 = pack(NetworkTCPEventGUID, uint16(ReconnectTCPv6ID))
// RetransmitTCPv4 is the TCP IPv4 network retransmit event.
- RetransmitTCPv4 = pack(NetworkTCPEventGUID, 14)
+ RetransmitTCPv4 = pack(NetworkTCPEventGUID, uint16(RetransmitTCPv4ID))
// RetransmitTCPv6 is the TCP IPv6 network retransmit event.
- RetransmitTCPv6 = pack(NetworkTCPEventGUID, 30)
+ RetransmitTCPv6 = pack(NetworkTCPEventGUID, uint16(RetransmitTCPv6ID))
// CreateHandle represents handle creation event
- CreateHandle = pack(HandleEventGUID, 32)
+ CreateHandle = pack(HandleEventGUID, uint16(CreateHandleID))
// CloseHandle represents handle closure event
- CloseHandle = pack(HandleEventGUID, 33)
+ CloseHandle = pack(HandleEventGUID, uint16(CloseHandleID))
// DuplicateHandle represents handle duplication event
- DuplicateHandle = pack(HandleEventGUID, 34)
+ DuplicateHandle = pack(HandleEventGUID, uint16(DuplicateHandleID))
// VirtualAlloc represents virtual memory allocation event
- VirtualAlloc = pack(MemEventGUID, 98)
+ VirtualAlloc = pack(MemEventGUID, uint16(VirtualAllocID))
// VirtualFree represents virtual memory release event
- VirtualFree = pack(MemEventGUID, 99)
+ VirtualFree = pack(MemEventGUID, uint16(VirtualFreeID))
// QueryDNS represents DNS query events
- QueryDNS = pack(DNSEventGUID, 3006)
+ QueryDNS = pack(DNSEventGUID, QueryDNSID)
// ReplyDNS represents the DNS response events
- ReplyDNS = pack(DNSEventGUID, 3008)
+ ReplyDNS = pack(DNSEventGUID, ReplyDNSID)
// StackWalk represents stack walk event with the collection of return addresses
- StackWalk = pack(windows.GUID{Data1: 0xdef2fe46, Data2: 0x7bd6, Data3: 0x4b80, Data4: [8]byte{0xbd, 0x94, 0xf5, 0x7f, 0xe2, 0x0d, 0x0c, 0xe3}}, 32)
+ StackWalk = pack(StackWalkEventGUID, uint16(StackWalkID))
// CreateSymbolicLinkObject represents the event emitted by the object manager when the new symbolic link is created within the object manager directory
- CreateSymbolicLinkObject = pack(AuditAPIEventGUID, 3)
+ CreateSymbolicLinkObject = pack(AuditAPIEventGUID, CreateSymbolicLinkObjectID)
// SubmitThreadpoolWork represents the event that enqueues the work item to the thread pool
- SubmitThreadpoolWork = pack(ThreadpoolGUID, 32)
+ SubmitThreadpoolWork = pack(ThreadpoolEventGUID, uint16(SubmitThreadpoolWorkID))
//SubmitThreadpoolCallback represents the event that submits the thread pool callback for execution within the work item
- SubmitThreadpoolCallback = pack(ThreadpoolGUID, 34)
+ SubmitThreadpoolCallback = pack(ThreadpoolEventGUID, uint16(SubmitThreadpoolCallbackID))
// SetThreadpoolTimer represents the event that sets the thread pool timer object
- SetThreadpoolTimer = pack(ThreadpoolGUID, 44)
+ SetThreadpoolTimer = pack(ThreadpoolEventGUID, uint16(SetThreadpoolTimerID))
// UnknownType designates unknown event type
UnknownType = pack(windows.GUID{}, 0)
@@ -609,7 +692,7 @@ func (t Type) ID() uint {
// Source designates the provenance of this event type.
func (t Type) Source() Source {
switch t.GUID() {
- case AuditAPIEventGUID, DNSEventGUID, ThreadpoolGUID, ProcessKernelEventGUID, RegistryKernelEventGUID:
+ case AuditAPIEventGUID, DNSEventGUID, ThreadpoolEventGUID, ProcessKernelEventGUID, RegistryKernelEventGUID:
return SecurityTelemetryLogger
default:
return SystemLogger