diff --git a/pkg/filter/accessor.go b/pkg/filter/accessor.go index 8c2604613..f18891c5c 100644 --- a/pkg/filter/accessor.go +++ b/pkg/filter/accessor.go @@ -171,6 +171,8 @@ func (f *filter) narrowAccessors() { switch { case field.Name.IsKevtField(), field.Name.IsEvtField(): removeEvtAccessor = false + case field.Name.IsPeField(): + removePEAccessor = false case field.Name.IsPsField(): removePsAccessor = false case field.Name.IsThreadField(): @@ -185,8 +187,6 @@ func (f *filter) narrowAccessors() { removeNetworkAccessor = false case field.Name.IsHandleField(): removeHandleAccessor = false - case field.Name.IsPeField(): - removePEAccessor = false case field.Name.IsMemField(): removeMemAccessor = false case field.Name.IsDNSField(): diff --git a/pkg/filter/accessor_windows.go b/pkg/filter/accessor_windows.go index c4721ba75..c891fa859 100644 --- a/pkg/filter/accessor_windows.go +++ b/pkg/filter/accessor_windows.go @@ -1074,6 +1074,7 @@ func (pa *peAccessor) Get(f Field, e *event.Event) (params.Value, error) { if err != nil { return nil, err } + e.PS.PE = p } // here we determine if the PE was tampered. This check @@ -1115,54 +1116,52 @@ func (pa *peAccessor) Get(f Field, e *event.Event) (params.Value, error) { p.VerifySignature() } - e.PS.PE = p - switch f.Name { - case fields.PeEntrypoint: + case fields.PeEntrypoint, fields.PsPeEntrypoint: return p.EntryPoint, nil - case fields.PeBaseAddress: + case fields.PeBaseAddress, fields.PsPeBaseAddress: return p.ImageBase, nil - case fields.PeNumSections: + case fields.PeNumSections, fields.PsPeNumSections: return p.NumberOfSections, nil - case fields.PeNumSymbols: + case fields.PeNumSymbols, fields.PsPeNumSymbols: return p.NumberOfSymbols, nil - case fields.PeSymbols: + case fields.PeSymbols, fields.PsPeSymbols: return p.Symbols, nil - case fields.PeImports: + case fields.PeImports, fields.PsPeImports: return p.Imports, nil - case fields.PeImphash: + case fields.PeImphash, fields.PsPeImphash: return p.Imphash, nil - case fields.PeIsDotnet: + case fields.PeIsDotnet, fields.PsPeIsDotnet: return p.IsDotnet, nil - case fields.PeAnomalies: + case fields.PeAnomalies, fields.PsPeAnomalies: return p.Anomalies, nil - case fields.PeIsSigned: + case fields.PeIsSigned, fields.PsSignatureExists: return p.IsSigned, nil - case fields.PeIsTrusted: + case fields.PeIsTrusted, fields.PsSignatureIsTrusted: return p.IsTrusted, nil case fields.PeIsModified: return p.IsModified, nil - case fields.PeCertIssuer: + case fields.PeCertIssuer, fields.PsSignatureIssuer: if p.Cert == nil { return nil, ErrPeNilCertificate } return p.Cert.Issuer, nil - case fields.PeCertSubject: + case fields.PeCertSubject, fields.PsSignatureSubject: if p.Cert == nil { return nil, ErrPeNilCertificate } return p.Cert.Subject, nil - case fields.PeCertSerial: + case fields.PeCertSerial, fields.PsSignatureSerial: if p.Cert == nil { return nil, ErrPeNilCertificate } return p.Cert.SerialNumber, nil - case fields.PeCertAfter: + case fields.PeCertAfter, fields.PsSignatureAfter: if p.Cert == nil { return nil, ErrPeNilCertificate } return p.Cert.NotAfter, nil - case fields.PeCertBefore: + case fields.PeCertBefore, fields.PsSignatureBefore: if p.Cert == nil { return nil, ErrPeNilCertificate } @@ -1173,23 +1172,23 @@ func (pa *peAccessor) Get(f Field, e *event.Event) (params.Value, error) { return e.Params.GetBool(params.FileIsDriver) case fields.PeIsExecutable: return e.Params.GetBool(params.FileIsExecutable) - case fields.PeCompany: + case fields.PeCompany, fields.PsPeCompany: return p.VersionResources[pe.Company], nil - case fields.PeCopyright: + case fields.PeCopyright, fields.PsPeCopyright: return p.VersionResources[pe.LegalCopyright], nil - case fields.PeDescription: + case fields.PeDescription, fields.PsPeDescription: return p.VersionResources[pe.FileDescription], nil - case fields.PeFileName: + case fields.PeFileName, fields.PsPeFileName: return p.VersionResources[pe.OriginalFilename], nil - case fields.PeFileVersion: + case fields.PeFileVersion, fields.PsPeFileVersion: return p.VersionResources[pe.FileVersion], nil - case fields.PeProduct: + case fields.PeProduct, fields.PsPeProduct: return p.VersionResources[pe.ProductName], nil - case fields.PeProductVersion: + case fields.PeProductVersion, fields.PsPeProductVersion: return p.VersionResources[pe.ProductVersion], nil - case fields.PeSections: + case fields.PeSections, fields.PsPeSections: return p.Sections, nil - case fields.PeResources: + case fields.PeResources, fields.PsPeResources: // return a single version resource indicated by the arg. // For example, pe.resources[FileDescription] returns the // original file description present in the resource directory diff --git a/pkg/filter/accessor_windows_test.go b/pkg/filter/accessor_windows_test.go index 949077f27..cedd97acb 100644 --- a/pkg/filter/accessor_windows_test.go +++ b/pkg/filter/accessor_windows_test.go @@ -19,13 +19,14 @@ package filter import ( + "reflect" + "testing" + "github.com/rabbitstack/fibratus/pkg/callstack" "github.com/rabbitstack/fibratus/pkg/event" ptypes "github.com/rabbitstack/fibratus/pkg/ps/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "reflect" - "testing" ) func TestNarrowAccessors(t *testing.T) { @@ -42,7 +43,7 @@ func TestNarrowAccessors(t *testing.T) { 1, }, { - New(`handle.type = 'Section' and pe.nsections > 1 and evt.name = 'CreateHandle'`, cfg), + New(`handle.type = 'Section' and ps.pe.nsections > 1 and evt.name = 'CreateHandle'`, cfg), 3, }, { diff --git a/pkg/filter/fields/fields_windows.go b/pkg/filter/fields/fields_windows.go index ec3ab55d5..01c70f2f5 100644 --- a/pkg/filter/fields/fields_windows.go +++ b/pkg/filter/fields/fields_windows.go @@ -129,6 +129,59 @@ const ( PsParentTokenIsElevated = "ps.parent.token.is_elevated" // PsTokenElevationType represents the field that indicates if the parent process token elevation type PsParentTokenElevationType = "ps.parent.token.elevation_type" + // PsSignatureExists is the field which indicates if the binary is signed, either by embedded or catalog signature + PsSignatureExists Field = "ps.signature.exists" + // PsSignatureIsTrusted is the field which indicates if the binary signature is trusted + PsSignatureIsTrusted Field = "ps.signature.is_trusted" + // PsSignatureIssuer is the field which indicates the certificate issuer + PsSignatureIssuer Field = "ps.signature.issuer" + // PsSignatureSubject is the field which indicates the certificate subject + PsSignatureSubject Field = "ps.signature.subject" + // PsSignatureSerial is the field which indicates the certificate serial + PsSignatureSerial Field = "ps.signature.serial" + // PsSignatureAfter is the field which indicates the timestamp after certificate is no longer valid + PsSignatureAfter Field = "ps.signature.after" + // PsSignatureBefore is the field which indicates the timestamp of the certificate enrollment date + PsSignatureBefore Field = "ps.signature.before" + + // PsPeNumSections represents the number of sections + PsPeNumSections Field = "ps.pe.nsections" + // PsPeNumSymbols represents the number of exported symbols + PsPeNumSymbols Field = "ps.pe.nsymbols" + // PsPeSymbols represents imported symbols + PsPeSymbols Field = "ps.pe.symbols" + // PeImports represents imported libraries (e.g. kernel32.dll) + PsPeImports Field = "ps.pe.imports" + // PeTimestamp is the PE build timestamp + PsPeTimestamp Field = "ps.pe.timestamp" + // PeBaseAddress represents the base address when the binary is loaded + PsPeBaseAddress Field = "ps.pe.address.base" + // PeEntrypoint is the address of the entrypoint function + PsPeEntrypoint Field = "ps.pe.address.entrypoint" + // PeResources represents PE resources + PsPeResources Field = "ps.pe.resources" + // PeCompany represents the company name resource + PsPeCompany Field = "ps.pe.company" + // PeDescription represents the internal description of the file + PsPeDescription Field = "ps.pe.description" + // PeFileVersion represents the internal file version + PsPeFileVersion Field = "ps.pe.file.version" + // PeFileName represents the original file name provided at compile-time. + PsPeFileName Field = "ps.pe.file.name" + // PeCopyright represents the copyright notice emitted at compile-time + PsPeCopyright Field = "ps.pe.copyright" + // PeProduct represents the product name provided at compile-time + PsPeProduct Field = "ps.pe.product" + // PeProductVersion represents the internal product version provided at compile-time + PsPeProductVersion Field = "ps.pe.product.version" + // PeAnomalies represents the field that contains PE anomalies detected during parsing + PsPeAnomalies Field = "ps.pe.anomalies" + // PsPeImphash is the field that yields the PE import hash + PsPeImphash Field = "ps.pe.imphash" + // PsPeIsDotnet is the field which indicates if the binary contains the .NET assembly + PsPeIsDotnet Field = "ps.pe.is_dotnet" + // PsPeIsModified is the field that indicates whether disk and in-memory PE headers differ + PsPeIsModified Field = "ps.pe.is_modified" // ThreadBasePrio is the base thread priority ThreadBasePrio Field = "thread.prio" @@ -562,39 +615,46 @@ func (f Field) String() string { return string(f) } // Type returns the data type that this field contains. func (f Field) Type() params.Type { return fields[f].Type } -func (f Field) IsPsField() bool { return strings.HasPrefix(string(f), "ps.") } -func (f Field) IsKevtField() bool { return strings.HasPrefix(string(f), "kevt.") } -func (f Field) IsEvtField() bool { return strings.HasPrefix(string(f), "evt.") } -func (f Field) IsThreadField() bool { return strings.HasPrefix(string(f), "thread.") } -func (f Field) IsImageField() bool { return strings.HasPrefix(string(f), "image.") } -func (f Field) IsFileField() bool { return strings.HasPrefix(string(f), "file.") } -func (f Field) IsRegistryField() bool { return strings.HasPrefix(string(f), "registry.") } -func (f Field) IsNetworkField() bool { return strings.HasPrefix(string(f), "net.") } -func (f Field) IsHandleField() bool { return strings.HasPrefix(string(f), "handle.") } -func (f Field) IsPeField() bool { return strings.HasPrefix(string(f), "pe.") } +func (f Field) IsPsField() bool { return strings.HasPrefix(string(f), "ps.") } +func (f Field) IsKevtField() bool { return strings.HasPrefix(string(f), "kevt.") } +func (f Field) IsEvtField() bool { return strings.HasPrefix(string(f), "evt.") } +func (f Field) IsThreadField() bool { return strings.HasPrefix(string(f), "thread.") } +func (f Field) IsImageField() bool { return strings.HasPrefix(string(f), "image.") } +func (f Field) IsFileField() bool { return strings.HasPrefix(string(f), "file.") } +func (f Field) IsRegistryField() bool { return strings.HasPrefix(string(f), "registry.") } +func (f Field) IsNetworkField() bool { return strings.HasPrefix(string(f), "net.") } +func (f Field) IsHandleField() bool { return strings.HasPrefix(string(f), "handle.") } +func (f Field) IsPeField() bool { + return strings.HasPrefix(string(f), "pe.") || strings.HasPrefix(string(f), "ps.pe.") || strings.HasPrefix(string(f), "ps.signature.") +} func (f Field) IsMemField() bool { return strings.HasPrefix(string(f), "mem.") } func (f Field) IsDNSField() bool { return strings.HasPrefix(string(f), "dns.") } func (f Field) IsThreadpoolField() bool { return strings.HasPrefix(string(f), "threadpool.") } -func (f Field) IsPeSection() bool { return f == PeNumSections } -func (f Field) IsPeSymbol() bool { return f == PeSymbols || f == PeNumSymbols || f == PeImports } +func (f Field) IsPeSection() bool { return f == PeNumSections || f == PsPeNumSections } +func (f Field) IsPeSymbol() bool { + return f == PeSymbols || f == PeNumSymbols || f == PeImports || f == PsPeSymbols || f == PsPeNumSymbols || f == PsPeImports +} func (f Field) IsPeVersionResource() bool { - return f == PeCompany || f == PeCopyright || f == PeDescription || f == PeFileName || f == PeFileVersion || f == PeProduct || f == PeProductVersion + return f == PeCompany || f == PeCopyright || f == PeDescription || f == PeFileName || f == PeFileVersion || f == PeProduct || f == PeProductVersion || + f == PsPeCompany || f == PsPeCopyright || f == PsPeDescription || f == PsPeFileName || f == PsPeFileVersion || f == PsPeProduct || f == PsPeProductVersion } -func (f Field) IsPeVersionResources() bool { return f == PeResources } -func (f Field) IsPeImphash() bool { return f == PeImphash } -func (f Field) IsPeDotnet() bool { return f == PeIsDotnet } -func (f Field) IsPeAnomalies() bool { return f == PeAnomalies } +func (f Field) IsPeVersionResources() bool { return f == PeResources || f == PsPeResources } +func (f Field) IsPeImphash() bool { return f == PeImphash || f == PsPeImphash } +func (f Field) IsPeDotnet() bool { return f == PeIsDotnet || f == PsPeIsDotnet } +func (f Field) IsPeAnomalies() bool { return f == PeAnomalies || f == PsPeAnomalies } func (f Field) IsPeSignature() bool { - return f == PeIsTrusted || f == PeIsSigned || f == PeCertIssuer || f == PeCertSerial || f == PeCertSubject || f == PeCertBefore || f == PeCertAfter + return f == PeIsTrusted || f == PeIsSigned || f == PeCertIssuer || f == PeCertSerial || f == PeCertSubject || f == PeCertBefore || f == PeCertAfter || strings.HasPrefix(string(f), "ps.signature.") } -func (f Field) IsPeIsTrusted() bool { return f == PeIsTrusted } -func (f Field) IsPeIsSigned() bool { return f == PeIsSigned } +func (f Field) IsPeIsTrusted() bool { return f == PeIsTrusted || f == PsSignatureIsTrusted } +func (f Field) IsPeIsSigned() bool { return f == PeIsSigned || f == PsSignatureExists } -func (f Field) IsPeCert() bool { return strings.HasPrefix(string(f), "pe.cert.") } +func (f Field) IsPeCert() bool { + return strings.HasPrefix(string(f), "pe.cert.") || f == PsSignatureIssuer || f == PsSignatureSubject || f == PsSignatureSerial || f == PsSignatureAfter || f == PsSignatureBefore +} func (f Field) IsImageCert() bool { return strings.HasPrefix(string(f), "image.cert.") } -func (f Field) IsPeModified() bool { return f == PeIsModified } +func (f Field) IsPeModified() bool { return f == PeIsModified || f == PsPeIsModified } // Segment represents the type alias for the segment. Segment // denotes the property anchored to the bound field reference. @@ -694,8 +754,9 @@ var allowedSegments = map[Field][]Segment{ PsAncestors: {NameSegment, PIDSegment, CmdlineSegment, ExeSegment, ArgsSegment, CwdSegment, SIDSegment, SessionIDSegment, UsernameSegment, DomainSegment, TokenIntegrityLevelSegment, TokenIsElevatedSegment, TokenElevationTypeSegment}, PsThreads: {TidSegment, StartAddressSegment, UserStackBaseSegment, UserStackLimitSegment, KernelStackBaseSegment, KernelStackLimitSegment}, PsModules: {PathSegment, NameSegment, AddressSegment, SizeSegment, ChecksumSegment}, - PsMmaps: {AddressSegment, TypeSegment, AddressSegment, SizeSegment, ProtectionSegment, PathSegment}, + PsMmaps: {AddressSegment, TypeSegment, SizeSegment, ProtectionSegment, PathSegment}, PeSections: {NameSegment, SizeSegment, EntropySegment, MD5Segment}, + PsPeSections: {NameSegment, SizeSegment, EntropySegment, MD5Segment}, ThreadCallstack: {AddressSegment, OffsetSegment, SymbolSegment, ModuleSegment, AllocationSizeSegment, ProtectionSegment, IsUnbackedSegment, CallsiteLeadingAssemblySegment, CallsiteTrailingAssemblySegment, ModuleSignatureIsSignedSegment, ModuleSignatureIsTrustedSegment, ModuleSignatureCertIssuerSegment, ModuleSignatureCertSubjectSegment}, } @@ -746,15 +807,16 @@ var ( PsThreads Field = "ps._threads" PsMmaps Field = "ps._mmaps" PsAncestors Field = "ps._ancestors" + PsPeSections Field = "ps.pe._sections" ThreadCallstack Field = "thread._callstack" PeSections Field = "pe._sections" ) func IsPseudoField(f Field) bool { - return f == PsAncestors || f == PsModules || f == PsThreads || f == PsMmaps || f == ThreadCallstack || f == PeSections + return f == PsAncestors || f == PsModules || f == PsThreads || f == PsMmaps || f == ThreadCallstack || f == PeSections || f == PsPeSections } -func (f Field) IsPeSectionsPseudo() bool { return f == PeSections } +func (f Field) IsPeSectionsPseudo() bool { return f == PeSections || f == PsPeSections } var fields = map[Field]FieldInfo{ EvtSeq: {EvtSeq, "event sequence number", params.Uint64, []string{"evt.seq > 666"}, nil, nil}, @@ -877,6 +939,44 @@ var fields = map[Field]FieldInfo{ PsParentTokenIntegrityLevel: {PsParentTokenIntegrityLevel, "parent process token integrity level", params.UnicodeString, []string{"ps.parent.token.integrity_level = 'HIGH'"}, nil, nil}, PsParentTokenIsElevated: {PsParentTokenIsElevated, "indicates if the parent process token is elevated", params.Bool, []string{"ps.parent.token.is_elevated = true"}, nil, nil}, PsParentTokenElevationType: {PsParentTokenElevationType, "parent process token elevation type", params.AnsiString, []string{"ps.parent.token.elevation_type = 'LIMITED'"}, nil, nil}, + PsSignatureExists: {PsSignatureExists, "indicates if the process executable has a valid signature", params.Bool, []string{"ps.signature.exists"}, nil, nil}, + PsSignatureIsTrusted: {PsSignatureIsTrusted, "indicates if the process executable signature certificate chain is trusted", params.Bool, []string{"ps.signature.is_trusted"}, nil, nil}, + PsSignatureSerial: {PsSignatureSerial, "represents signature serial number", params.UnicodeString, []string{"ps.signature.serial = '330000023241fb59996dcc4dff000000000232'"}, nil, nil}, + PsSignatureSubject: {PsSignatureSubject, "represents signature subject", params.UnicodeString, []string{"ps.signature.subject contains 'Washington, Redmond, Microsoft Corporation'"}, nil, nil}, + PsSignatureIssuer: {PsSignatureIssuer, "represents signature CA", params.UnicodeString, []string{"ps.signature.issuer contains 'Washington, Redmond, Microsoft Corporation'"}, nil, nil}, + PsSignatureAfter: {PsSignatureAfter, "represents certificate expiration date", params.Time, []string{"ps.signature.after contains '2024-02-01 00:05:42 +0000 UTC'"}, nil, nil}, + PsSignatureBefore: {PsSignatureBefore, "represents certificate enrollment date", params.Time, []string{"ps.signature.before contains '2024-02-01 00:05:42 +0000 UTC'"}, nil, nil}, + + PsPeNumSections: {PsPeNumSections, "number of PE sections", params.Uint16, []string{"ps.pe.nsections < 5"}, nil, nil}, + PsPeNumSymbols: {PsPeNumSymbols, "number of entries in the symbol table", params.Uint32, []string{"ps.pe.nsymbols > 230"}, nil, nil}, + PsPeBaseAddress: {PsPeBaseAddress, "executable base address", params.Address, []string{"ps.pe.address.base = '140000000'"}, nil, nil}, + PsPeEntrypoint: {PsPeEntrypoint, "address of the entrypoint function", params.Address, []string{"ps.pe.address.entrypoint = '20110'"}, nil, nil}, + PsPeSymbols: {PsPeSymbols, "imported symbols", params.Slice, []string{"ps.pe.symbols in ('GetTextFaceW', 'GetProcessHeap')"}, nil, nil}, + PsPeImports: {PsPeImports, "imported dynamic linked libraries", params.Slice, []string{"ps.pe.imports in ('msvcrt.dll', 'GDI32.dll'"}, nil, nil}, + PsPeResources: {PsPeResources, "version resources", params.Map, []string{"ps.pe.resources[FileDescription] = 'Notepad'"}, nil, &Argument{Optional: true, Pattern: "[a-zA-Z0-9_]+", ValidationFunc: func(s string) bool { + for _, c := range s { + switch { + case unicode.IsLower(c): + case unicode.IsUpper(c): + case unicode.IsNumber(c): + case c == '_': + default: + return false + } + } + return true + }}}, + PsPeCompany: {PsPeCompany, "internal company name of the file provided at compile-time", params.UnicodeString, []string{"ps.pe.company = 'Microsoft Corporation'"}, nil, nil}, + PsPeCopyright: {PsPeCopyright, "copyright notice for the file emitted at compile-time", params.UnicodeString, []string{"ps.pe.copyright = '© Microsoft Corporation'"}, nil, nil}, + PsPeDescription: {PsPeDescription, "internal description of the file provided at compile-time", params.UnicodeString, []string{"ps.pe.description = 'Notepad'"}, nil, nil}, + PsPeFileName: {PsPeFileName, "original file name supplied at compile-time", params.UnicodeString, []string{"ps.pe.file.name = 'NOTEPAD.EXE'"}, nil, nil}, + PsPeFileVersion: {PsPeFileVersion, "file version supplied at compile-time", params.UnicodeString, []string{"ps.pe.file.version = '10.0.18362.693 (WinBuild.160101.0800)'"}, nil, nil}, + PsPeProduct: {PsPeProduct, "internal product name of the file provided at compile-time", params.UnicodeString, []string{"ps.pe.product = 'Microsoft® Windows® Operating System'"}, nil, nil}, + PsPeProductVersion: {PsPeProductVersion, "internal product version of the file provided at compile-time", params.UnicodeString, []string{"ps.pe.product.version = '10.0.18362.693'"}, nil, nil}, + PsPeImphash: {PsPeImphash, "import hash", params.AnsiString, []string{"pe.impash = '5d3861c5c547f8a34e471ba273a732b2'"}, nil, nil}, + PsPeIsDotnet: {PsPeIsDotnet, "indicates if PE contains CLR data", params.Bool, []string{"ps.pe.is_dotnet"}, nil, nil}, + PsPeAnomalies: {PsPeAnomalies, "contains PE anomalies detected during parsing", params.Slice, []string{"ps.pe.anomalies in ('number of sections is 0')"}, nil, nil}, + PsPeIsModified: {PsPeIsModified, "indicates if disk and in-memory PE headers differ", params.Bool, []string{"ps.pe.is_modified"}, nil, nil}, ThreadBasePrio: {ThreadBasePrio, "scheduler priority of the thread", params.Int8, []string{"thread.prio = 5"}, nil, nil}, ThreadIOPrio: {ThreadIOPrio, "I/O priority hint for scheduling I/O operations", params.Int8, []string{"thread.io.prio = 4"}, nil, nil}, @@ -987,14 +1087,14 @@ var fields = map[Field]FieldInfo{ HandleName: {HandleName, "handle name", params.UnicodeString, []string{"handle.name = '\\Device\\NamedPipe\\chrome.12644.28.105826381'"}, nil, nil}, HandleType: {HandleType, "handle type", params.AnsiString, []string{"handle.type = 'Mutant'"}, nil, nil}, - PeNumSections: {PeNumSections, "number of sections", params.Uint16, []string{"pe.nsections < 5"}, nil, nil}, - PeNumSymbols: {PeNumSymbols, "number of entries in the symbol table", params.Uint32, []string{"pe.nsymbols > 230"}, nil, nil}, - PeBaseAddress: {PeBaseAddress, "image base address", params.Address, []string{"pe.address.base = '140000000'"}, nil, nil}, - PeEntrypoint: {PeEntrypoint, "address of the entrypoint function", params.Address, []string{"pe.address.entrypoint = '20110'"}, nil, nil}, - PeSymbols: {PeSymbols, "imported symbols", params.Slice, []string{"pe.symbols in ('GetTextFaceW', 'GetProcessHeap')"}, nil, nil}, - PeImports: {PeImports, "imported dynamic linked libraries", params.Slice, []string{"pe.imports in ('msvcrt.dll', 'GDI32.dll'"}, nil, nil}, + PeNumSections: {PeNumSections, "number of sections", params.Uint16, []string{"pe.nsections < 5"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsPeNumSections}}, nil}, + PeNumSymbols: {PeNumSymbols, "number of entries in the symbol table", params.Uint32, []string{"pe.nsymbols > 230"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsPeNumSymbols}}, nil}, + PeBaseAddress: {PeBaseAddress, "image base address", params.Address, []string{"pe.address.base = '140000000'"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsPeBaseAddress}}, nil}, + PeEntrypoint: {PeEntrypoint, "address of the entrypoint function", params.Address, []string{"pe.address.entrypoint = '20110'"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsPeEntrypoint}}, nil}, + PeSymbols: {PeSymbols, "imported symbols", params.Slice, []string{"pe.symbols in ('GetTextFaceW', 'GetProcessHeap')"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsPeSymbols}}, nil}, + PeImports: {PeImports, "imported dynamic linked libraries", params.Slice, []string{"pe.imports in ('msvcrt.dll', 'GDI32.dll'"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsPeImports}}, nil}, - PeResources: {PeResources, "version resources", params.Map, []string{"pe.resources[FileDescription] = 'Notepad'"}, nil, &Argument{Optional: true, Pattern: "[a-zA-Z0-9_]+", ValidationFunc: func(s string) bool { + PeResources: {PeResources, "version resources", params.Map, []string{"pe.resources[FileDescription] = 'Notepad'"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsPeResources}}, &Argument{Optional: true, Pattern: "[a-zA-Z0-9_]+", ValidationFunc: func(s string) bool { for _, c := range s { switch { case unicode.IsLower(c): @@ -1008,27 +1108,27 @@ var fields = map[Field]FieldInfo{ return true }}}, - PeCompany: {PeCompany, "internal company name of the file provided at compile-time", params.UnicodeString, []string{"pe.company = 'Microsoft Corporation'"}, nil, nil}, - PeCopyright: {PeCopyright, "copyright notice for the file emitted at compile-time", params.UnicodeString, []string{"pe.copyright = '© Microsoft Corporation'"}, nil, nil}, - PeDescription: {PeDescription, "internal description of the file provided at compile-time", params.UnicodeString, []string{"pe.description = 'Notepad'"}, nil, nil}, - PeFileName: {PeFileName, "original file name supplied at compile-time", params.UnicodeString, []string{"pe.file.name = 'NOTEPAD.EXE'"}, nil, nil}, - PeFileVersion: {PeFileVersion, "file version supplied at compile-time", params.UnicodeString, []string{"pe.file.version = '10.0.18362.693 (WinBuild.160101.0800)'"}, nil, nil}, - PeProduct: {PeProduct, "internal product name of the file provided at compile-time", params.UnicodeString, []string{"pe.product = 'Microsoft® Windows® Operating System'"}, nil, nil}, - PeProductVersion: {PeProductVersion, "internal product version of the file provided at compile-time", params.UnicodeString, []string{"pe.product.version = '10.0.18362.693'"}, nil, nil}, + PeCompany: {PeCompany, "internal company name of the file provided at compile-time", params.UnicodeString, []string{"pe.company = 'Microsoft Corporation'"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsPeCompany}}, nil}, + PeCopyright: {PeCopyright, "copyright notice for the file emitted at compile-time", params.UnicodeString, []string{"pe.copyright = '© Microsoft Corporation'"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsPeCopyright}}, nil}, + PeDescription: {PeDescription, "internal description of the file provided at compile-time", params.UnicodeString, []string{"pe.description = 'Notepad'"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsPeDescription}}, nil}, + PeFileName: {PeFileName, "original file name supplied at compile-time", params.UnicodeString, []string{"pe.file.name = 'NOTEPAD.EXE'"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsPeFileName}}, nil}, + PeFileVersion: {PeFileVersion, "file version supplied at compile-time", params.UnicodeString, []string{"pe.file.version = '10.0.18362.693 (WinBuild.160101.0800)'"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsPeFileVersion}}, nil}, + PeProduct: {PeProduct, "internal product name of the file provided at compile-time", params.UnicodeString, []string{"pe.product = 'Microsoft® Windows® Operating System'"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsPeProduct}}, nil}, + PeProductVersion: {PeProductVersion, "internal product version of the file provided at compile-time", params.UnicodeString, []string{"pe.product.version = '10.0.18362.693'"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsPeProductVersion}}, nil}, PeIsDLL: {PeIsDLL, "indicates if the loaded image or created file is a DLL", params.Bool, []string{"pe.is_dll'"}, &Deprecation{Since: "2.0.0", Fields: []Field{FileIsDLL, ImageIsDLL}}, nil}, PeIsDriver: {PeIsDriver, "indicates if the loaded image or created file is a driver", params.Bool, []string{"pe.is_driver'"}, &Deprecation{Since: "2.0.0", Fields: []Field{FileIsDriver, ImageIsDriver}}, nil}, PeIsExecutable: {PeIsExecutable, "indicates if the loaded image or created file is an executable", params.Bool, []string{"pe.is_exec'"}, &Deprecation{Since: "2.0.0", Fields: []Field{FileIsExecutable, ImageIsExecutable}}, nil}, - PeImphash: {PeImphash, "import hash", params.AnsiString, []string{"pe.impash = '5d3861c5c547f8a34e471ba273a732b2'"}, nil, nil}, - PeIsDotnet: {PeIsDotnet, "indicates if PE contains CLR data", params.Bool, []string{"pe.is_dotnet"}, nil, nil}, - PeAnomalies: {PeAnomalies, "contains PE anomalies detected during parsing", params.Slice, []string{"pe.anomalies in ('number of sections is 0')"}, nil, nil}, - PeIsSigned: {PeIsSigned, "indicates if the PE has embedded or catalog signature", params.Bool, []string{"pe.is_signed"}, nil, nil}, - PeIsTrusted: {PeIsTrusted, "indicates if the PE certificate chain is trusted", params.Bool, []string{"pe.is_trusted"}, nil, nil}, - PeCertSerial: {PeCertSerial, "PE certificate serial number", params.UnicodeString, []string{"pe.cert.serial = '330000023241fb59996dcc4dff000000000232'"}, nil, nil}, - PeCertSubject: {PeCertSubject, "PE certificate subject", params.UnicodeString, []string{"pe.cert.subject contains 'Washington, Redmond, Microsoft Corporation'"}, nil, nil}, - PeCertIssuer: {PeCertIssuer, "PE certificate CA", params.UnicodeString, []string{"pe.cert.issuer contains 'Washington, Redmond, Microsoft Corporation'"}, nil, nil}, - PeCertAfter: {PeCertAfter, "PE certificate expiration date", params.Time, []string{"pe.cert.after contains '2024-02-01 00:05:42 +0000 UTC'"}, nil, nil}, - PeCertBefore: {PeCertBefore, "PE certificate enrollment date", params.Time, []string{"pe.cert.before contains '2024-02-01 00:05:42 +0000 UTC'"}, nil, nil}, - PeIsModified: {PeIsModified, "indicates if disk and in-memory PE headers differ", params.Bool, []string{"pe.is_modified"}, nil, nil}, + PeImphash: {PeImphash, "import hash", params.AnsiString, []string{"pe.impash = '5d3861c5c547f8a34e471ba273a732b2'"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsPeImphash}}, nil}, + PeIsDotnet: {PeIsDotnet, "indicates if PE contains CLR data", params.Bool, []string{"pe.is_dotnet"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsPeIsDotnet}}, nil}, + PeAnomalies: {PeAnomalies, "contains PE anomalies detected during parsing", params.Slice, []string{"pe.anomalies in ('number of sections is 0')"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsPeAnomalies}}, nil}, + PeIsSigned: {PeIsSigned, "indicates if the PE has embedded or catalog signature", params.Bool, []string{"pe.is_signed"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsSignatureExists}}, nil}, + PeIsTrusted: {PeIsTrusted, "indicates if the PE certificate chain is trusted", params.Bool, []string{"pe.is_trusted"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsSignatureIsTrusted}}, nil}, + PeCertSerial: {PeCertSerial, "PE certificate serial number", params.UnicodeString, []string{"pe.cert.serial = '330000023241fb59996dcc4dff000000000232'"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsSignatureSerial}}, nil}, + PeCertSubject: {PeCertSubject, "PE certificate subject", params.UnicodeString, []string{"pe.cert.subject contains 'Washington, Redmond, Microsoft Corporation'"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsSignatureSubject}}, nil}, + PeCertIssuer: {PeCertIssuer, "PE certificate CA", params.UnicodeString, []string{"pe.cert.issuer contains 'Washington, Redmond, Microsoft Corporation'"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsSignatureIssuer}}, nil}, + PeCertAfter: {PeCertAfter, "PE certificate expiration date", params.Time, []string{"pe.cert.after contains '2024-02-01 00:05:42 +0000 UTC'"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsSignatureAfter}}, nil}, + PeCertBefore: {PeCertBefore, "PE certificate enrollment date", params.Time, []string{"pe.cert.before contains '2024-02-01 00:05:42 +0000 UTC'"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsSignatureBefore}}, nil}, + PeIsModified: {PeIsModified, "indicates if disk and in-memory PE headers differ", params.Bool, []string{"pe.is_modified"}, &Deprecation{Since: "3.0.0", Fields: []Field{PsPeIsModified}}, nil}, MemBaseAddress: {MemBaseAddress, "region base address", params.Address, []string{"mem.address = '211d13f2000'"}, nil, nil}, MemRegionSize: {MemRegionSize, "region size", params.Uint64, []string{"mem.size > 438272"}, nil, nil}, diff --git a/pkg/filter/filter_test.go b/pkg/filter/filter_test.go index cb00d0f5c..8ad4833df 100644 --- a/pkg/filter/filter_test.go +++ b/pkg/filter/filter_test.go @@ -1137,18 +1137,18 @@ func TestPEFilter(t *testing.T) { matches bool }{ - {`foreach(pe._sections, $section, $section.entropy = 6.368381)`, true}, - {`foreach(pe._sections, $section, $section.entropy > 4.45)`, true}, - {`foreach(pe._sections, $section, $section.name = '.rdata' and $section.entropy < 9.45)`, true}, - {`foreach(pe._sections, $section, $section.size = 132608)`, true}, - {`foreach(pe._sections, $section, $section.md5 = 'ffa5c960b421ca9887e54966588e97e8')`, true}, - {`pe.symbols IN ('GetTextFaceW', 'GetProcessHeap')`, true}, - {`pe.resources[FileDesc] = 'Notepad'`, true}, - {`pe.resources[CompanyName] = 'Microsoft Corporation'`, true}, - {`pe.resources in ('FileDescription:Notepad')`, true}, - {`pe.nsymbols = 10 AND pe.nsections = 2`, true}, - {`pe.nsections > 1`, true}, - {`pe.address.base = '140000000' AND pe.address.entrypoint = '20110'`, true}, + {`foreach(ps.pe._sections, $section, $section.entropy = 6.368381)`, true}, + {`foreach(ps.pe._sections, $section, $section.entropy > 4.45)`, true}, + {`foreach(ps.pe._sections, $section, $section.name = '.rdata' and $section.entropy < 9.45)`, true}, + {`foreach(ps.pe._sections, $section, $section.size = 132608)`, true}, + {`foreach(ps.pe._sections, $section, $section.md5 = 'ffa5c960b421ca9887e54966588e97e8')`, true}, + {`ps.pe.symbols IN ('GetTextFaceW', 'GetProcessHeap')`, true}, + {`ps.pe.resources[FileDesc] = 'Notepad'`, true}, + {`ps.pe.resources[CompanyName] = 'Microsoft Corporation'`, true}, + {`ps.pe.resources in ('FileDescription:Notepad')`, true}, + {`ps.pe.nsymbols = 10 AND ps.pe.nsections = 2`, true}, + {`ps.pe.nsections > 1`, true}, + {`ps.pe.address.base = '140000000' AND ps.pe.address.entrypoint = '20110'`, true}, } for i, tt := range tests { @@ -1181,21 +1181,21 @@ func TestLazyPEFilter(t *testing.T) { filter string matches bool }{ - {`foreach(pe._sections, $s, $s.entropy > 1.23)`, true}, - {`pe.symbols IN ('GetTextFaceW', 'GetProcessHeap')`, true}, + {`foreach(ps.pe._sections, $s, $s.entropy > 1.23)`, true}, + {`ps.pe.symbols IN ('GetTextFaceW', 'GetProcessHeap')`, true}, {`pe.is_dll`, true}, - {`length(pe.imphash) > 0`, true}, - {`pe.is_dotnet`, false}, - {`pe.resources[FileDesc] icontains 'Notepad'`, true}, - {`pe.file.name ~= 'NOTEPAD.EXE'`, true}, - {`pe.nsymbols > 10 AND pe.nsections > 2`, true}, - {`pe.nsections > 1`, true}, - {`length(pe.anomalies) = 0`, true}, - {`pe.is_signed`, true}, - {`pe.is_trusted`, true}, - {`pe.cert.subject icontains 'microsoft'`, true}, - {`pe.cert.issuer icontains 'microsoft'`, true}, - {`length(pe.cert.serial) > 0`, true}, + {`length(ps.pe.imphash) > 0`, true}, + {`ps.pe.is_dotnet`, false}, + {`ps.pe.resources[FileDesc] icontains 'Notepad'`, true}, + {`ps.pe.file.name ~= 'NOTEPAD.EXE'`, true}, + {`ps.pe.nsymbols > 10 AND pe.nsections > 2`, true}, + {`ps.pe.nsections > 1`, true}, + {`length(ps.pe.anomalies) = 0`, true}, + {`ps.signature.exists`, true}, + {`ps.signature.is_trusted`, true}, + {`ps.signature.subject icontains 'microsoft'`, true}, + {`ps.signature.issuer icontains 'microsoft'`, true}, + {`length(ps.signature.serial) > 0`, true}, } for i, tt := range tests { diff --git a/rules/credential_access_credential_access_from_backups_via_rundll32.yml b/rules/credential_access_credential_access_from_backups_via_rundll32.yml index 2021cc850..fffaf2a42 100644 --- a/rules/credential_access_credential_access_from_backups_via_rundll32.yml +++ b/rules/credential_access_credential_access_from_backups_via_rundll32.yml @@ -1,6 +1,6 @@ name: Credentials access from backups via Rundll32 id: ff43852c-486c-4870-a318-ce976d2231a5 -version: 1.0.3 +version: 1.0.4 description: | Detects an attempt to obtain credentials from credential backups. labels: @@ -16,7 +16,7 @@ labels: condition: > spawn_process and - (ps.name ~= 'rundll32.exe' or pe.file.name ~= 'rundll32.exe') and + (ps.name ~= 'rundll32.exe' or ps.pe.file.name ~= 'rundll32.exe') and (ps.args iin ('keymgr.dll') and ps.args iin ('KRShowKeyMgr')) min-engine-version: 3.0.0 diff --git a/rules/credential_access_credential_discovery_via_vaultcmd.yml b/rules/credential_access_credential_discovery_via_vaultcmd.yml index bfd8eb210..11a08213a 100644 --- a/rules/credential_access_credential_discovery_via_vaultcmd.yml +++ b/rules/credential_access_credential_discovery_via_vaultcmd.yml @@ -1,6 +1,6 @@ name: Credential discovery via VaultCmd tool id: 2ce607d3-5a14-4628-be8a-22bcde97dab5 -version: 1.1.3 +version: 1.1.4 description: | Detects the usage of the VaultCmd tool to list Windows Credentials. VaultCmd creates, displays and deletes stored credentials. An adversary may abuse this to list or dump @@ -18,7 +18,7 @@ labels: condition: > spawn_process and - (ps.name ~= 'VaultCmd.exe' or pe.file.name ~= 'vaultcmd.exe') and + (ps.name ~= 'VaultCmd.exe' or ps.pe.file.name ~= 'vaultcmd.exe') and ps.cmdline imatches '*/list*' severity: medium diff --git a/rules/credential_access_remote_thread_creation_into_lsass.yml b/rules/credential_access_remote_thread_creation_into_lsass.yml index 3555cd888..70bbf4790 100644 --- a/rules/credential_access_remote_thread_creation_into_lsass.yml +++ b/rules/credential_access_remote_thread_creation_into_lsass.yml @@ -1,6 +1,6 @@ name: Remote thread creation into LSASS id: e3ce8d6f-c260-48d6-9398-3c1c71726297 -version: 1.0.3 +version: 1.0.4 description: | Identifies the creation of a remote thread in LSASS (Local Security And Authority Subsystem Service) by untrusted or suspicious processes. This may indicate attempts to execute code inside the LSASS process @@ -19,6 +19,6 @@ labels: condition: > create_remote_thread and evt.arg[exe] imatches '?:\\Windows\\System32\\lsass.exe' and - (ps.name iin script_interpreters or ps.name ~= 'rundll32.exe' or pe.is_signed = false or pe.is_trusted = false) + (ps.name iin script_interpreters or ps.name ~= 'rundll32.exe' or ps.signature.exists = false or ps.signature.is_trusted = false) min-engine-version: 3.0.0 diff --git a/rules/defense_evasion_appdomain_manager_injection_via_clr_search_order_hijacking.yml b/rules/defense_evasion_appdomain_manager_injection_via_clr_search_order_hijacking.yml index 4b409c6d4..2d08ef5a1 100644 --- a/rules/defense_evasion_appdomain_manager_injection_via_clr_search_order_hijacking.yml +++ b/rules/defense_evasion_appdomain_manager_injection_via_clr_search_order_hijacking.yml @@ -1,6 +1,6 @@ name: AppDomain Manager injection via CLR search order hijacking id: 9319fafd-b7dc-4d85-b41a-54a8d4f1ab18 -version: 1.0.5 +version: 1.0.6 description: | Adversaries may execute their own malicious payloads by hijacking how the .NET AppDomainManager loads assemblies. The .NET framework uses the AppDomainManager class to create and manage one or more isolated runtime environments @@ -27,7 +27,7 @@ references: condition: > (load_unsigned_or_untrusted_module) and ps.exe != '' and ((base(dir(image.path)) ~= base(image.path, false)) or (ps.envs[APPDOMAIN_MANAGER_ASM] istartswith image.name)) and - pe.is_dotnet and (image.is_dotnet or thread.callstack.symbols imatches ('clr.dll!ParseManifest*')) + ps.pe.is_dotnet and (image.is_dotnet or thread.callstack.symbols imatches ('clr.dll!ParseManifest*')) output: > Process %ps.exe loaded untrusted .NET assembly %image.path from suspicious location diff --git a/rules/defense_evasion_dll_sideloading_via_copied_binary.yml b/rules/defense_evasion_dll_sideloading_via_copied_binary.yml index 50c703581..c9360d701 100644 --- a/rules/defense_evasion_dll_sideloading_via_copied_binary.yml +++ b/rules/defense_evasion_dll_sideloading_via_copied_binary.yml @@ -25,7 +25,8 @@ condition: > thread.callstack.symbols imatches ('*CopyFile*', '*MoveFile*') | by file.path |(load_dll) and - dir(image.path) ~= dir(ps.exe) and pe.cert.subject icontains 'Microsoft' and pe.is_trusted and + dir(image.path) ~= dir(ps.exe) and + ps.signature.subject icontains 'Microsoft' and ps.signature.is_trusted and (image.signature.type = 'NONE' or image.signature.level = 'UNCHECKED' or image.signature.level = 'UNSIGNED') | by ps.exe diff --git a/rules/defense_evasion_dll_sideloading_via_microsoft_office_dropped_file.yml b/rules/defense_evasion_dll_sideloading_via_microsoft_office_dropped_file.yml index 8814aa4c0..5cd7cda55 100644 --- a/rules/defense_evasion_dll_sideloading_via_microsoft_office_dropped_file.yml +++ b/rules/defense_evasion_dll_sideloading_via_microsoft_office_dropped_file.yml @@ -1,6 +1,6 @@ name: DLL Side-Loading via Microsoft Office dropped file id: d808175d-c4f8-459d-b17f-ca9a88890c04 -version: 1.0.2 +version: 1.0.3 description: | Identifies Microsoft Office process creating a DLL or other variant of an executable object which is later loaded by a trusted binary. Adversaries may exploit this behavior by delivering malicious @@ -23,8 +23,8 @@ condition: > (file.extension iin ('.dll', '.cpl', '.ocx') or file.is_dll) and ps.name iin msoffice_binaries | by file.path - |(load_unsigned_or_untrusted_dll) - and pe.is_signed = true and ps.name not iin msoffice_binaries and + |(load_unsigned_or_untrusted_dll) and + ps.name not iin msoffice_binaries and ps.signature.is_trusted = true and image.path not imatches '?:\\Windows\\assembly\\NativeImages_*' and ps.exe not imatches ( diff --git a/rules/defense_evasion_dotnet_assembly_loaded_by_unmanaged_process.yml b/rules/defense_evasion_dotnet_assembly_loaded_by_unmanaged_process.yml index fc625ebfe..57ac8b9e6 100644 --- a/rules/defense_evasion_dotnet_assembly_loaded_by_unmanaged_process.yml +++ b/rules/defense_evasion_dotnet_assembly_loaded_by_unmanaged_process.yml @@ -1,6 +1,6 @@ name: .NET assembly loaded by unmanaged process id: 34be8bd1-1143-4fa8-bed4-ae2566b1394a -version: 1.0.8 +version: 1.0.9 description: | Identifies the loading of the .NET assembly by an unmanaged process. Adversaries can load the CLR runtime inside unmanaged process and execute the assembly via the ICLRRuntimeHost::ExecuteInDefaultAppDomain method. @@ -17,7 +17,7 @@ references: condition: > (load_unsigned_or_untrusted_module) and - ps.exe != '' and pe.is_dotnet = false and + ps.exe != '' and ps.pe.is_dotnet = false and (image.is_dotnet or thread.callstack.modules imatches ('*clr.dll')) and image.path not imatches ( diff --git a/rules/defense_evasion_regsvr32_scriptlet_execution.yml b/rules/defense_evasion_regsvr32_scriptlet_execution.yml index 4bd20a3e8..58e118f30 100644 --- a/rules/defense_evasion_regsvr32_scriptlet_execution.yml +++ b/rules/defense_evasion_regsvr32_scriptlet_execution.yml @@ -1,6 +1,6 @@ name: Regsvr32 scriptlet execution id: 128f5254-67c9-43ac-b901-18b3731b1d0b -version: 1.0.4 +version: 1.0.5 description: | Identifies the execution of a scriptlet file by regsvr32.exe process. regsvr32.exe allows attackers to run arbitrary scripts to proxy execution of malicious code. @@ -17,7 +17,7 @@ labels: condition: > spawn_process and - (ps.name ~= 'regsvr32.exe' or pe.file.name ~= 'regsvr32.exe') and + (ps.name ~= 'regsvr32.exe' or ps.pe.file.name ~= 'regsvr32.exe') and ( (ps.cmdline imatches '*scrobj*' and ps.cmdline imatches diff --git a/rules/defense_evasion_suspicious_html_application_script_execution.yml b/rules/defense_evasion_suspicious_html_application_script_execution.yml index 870bf0d56..47369388b 100644 --- a/rules/defense_evasion_suspicious_html_application_script_execution.yml +++ b/rules/defense_evasion_suspicious_html_application_script_execution.yml @@ -1,7 +1,7 @@ name: Suspicious HTML Application script execution id: 4ec64ac2-851d-41b4-b7d2-910c21de334d -version: 1.0.6 -description: | +version: 1.0.7 +description: | Identifies the execution of scripts via Microsoft HTML Application Host interpreter. Adversaries can proxy the execution of arbitrary script code through a trusted, signed utility to evade defenses. labels: @@ -20,7 +20,7 @@ references: condition: > spawn_process and - (ps.name ~= 'mshta.exe' or pe.file.name ~= 'mshta.exe') and + (ps.name ~= 'mshta.exe' or ps.pe.file.name ~= 'mshta.exe') and ps.cmdline imatches ( '*WScript.Shell*', diff --git a/rules/defense_evasion_suspicious_object_symbolic_link_creation.yml b/rules/defense_evasion_suspicious_object_symbolic_link_creation.yml index 7553d6cb5..4dc4b133c 100644 --- a/rules/defense_evasion_suspicious_object_symbolic_link_creation.yml +++ b/rules/defense_evasion_suspicious_object_symbolic_link_creation.yml @@ -1,6 +1,6 @@ name: Suspicious object symbolic link creation id: f9306355-1f5f-4a06-9779-195aa681db80 -version: 1.0.4 +version: 1.0.5 description: | Identifies the creation of the object symbolic link inside the object manager namespace by untrusted or unusual processes. @@ -19,7 +19,7 @@ references: condition: > create_symbolic_link_object and evt.pid != 4 and - (pe.is_signed = false or pe.is_trusted = false or + (ps.signature.exists = false or ps.signature.is_trusted = false or ps.exe not imatches ( '?:\\ProgramData\\Microsoft\\Windows Defender\\*\\MsMpEng.exe', diff --git a/rules/defense_evasion_suspicious_windows_defender_exclusions_registry_modification.yml b/rules/defense_evasion_suspicious_windows_defender_exclusions_registry_modification.yml index 83d96506b..8d0d39323 100644 --- a/rules/defense_evasion_suspicious_windows_defender_exclusions_registry_modification.yml +++ b/rules/defense_evasion_suspicious_windows_defender_exclusions_registry_modification.yml @@ -1,6 +1,6 @@ name: Suspicious Windows Defender exclusions registry modification id: 92fdbbea-e177-494e-8a6a-d8b055daf0e9 -version: 1.0.2 +version: 1.0.3 description: | Identifies the modification of the Windows Defender process, path, or IP address registry key exclusions by suspicious processes. Adversaries may alter the Windows Defender exclusions to bypass defenses. @@ -27,7 +27,7 @@ condition: > '?:\\ProgramData\\*' ) or ps.name iin ('pwsh.exe', 'rundll32.exe', 'regsvr32.exe', 'cscript.exe', 'reg.exe', 'wscript.exe', 'mshta.exe', 'msbuild.exe', 'powershell.exe', 'cmd.exe') or - pe.is_signed = false or pe.is_trusted = false + ps.signature.exists = false or ps.signature.is_trusted = false ) and ps.exe not imatches ( diff --git a/rules/defense_evasion_suspicious_xsl_script_execution.yml b/rules/defense_evasion_suspicious_xsl_script_execution.yml index 7b8753958..f4af7e06c 100644 --- a/rules/defense_evasion_suspicious_xsl_script_execution.yml +++ b/rules/defense_evasion_suspicious_xsl_script_execution.yml @@ -1,6 +1,6 @@ name: Suspicious XSL script execution id: 65136b30-14ae-46dd-b8e5-9dfa99690d74 -version: 1.0.5 +version: 1.0.6 description: | Identifies a suspicious execution of XSL script via Windows Management Instrumentation command line tool or XSL transformation utility. Adversaries may bypass application control and obscure the execution of code by embedding @@ -21,7 +21,7 @@ condition: > maxspan 3m by ps.uuid |spawn_process and - (((ps.name ~= 'wmic.exe' or pe.file.name ~= 'wmic.exe') and + (((ps.name ~= 'wmic.exe' or ps.pe.file.name ~= 'wmic.exe') and ps.cmdline imatches ('* format*:*', '*/format*:*', '*-format*:*') and ps.cmdline not imatches ( @@ -36,7 +36,7 @@ condition: > '*format:csv*' ) ) or - ps.name ~= 'msxsl.exe' or pe.file.name ~= 'msxsl.exe' + ps.name ~= 'msxsl.exe' or ps.pe.file.name ~= 'msxsl.exe' ) | |load_dll and image.name iin ('scrobj.dll', 'vbscript.dll', 'jscript.dll', 'jscript9.dll')| diff --git a/rules/defense_evasion_system_binary_proxy_execution_via_rundll32.yml b/rules/defense_evasion_system_binary_proxy_execution_via_rundll32.yml index fb9537488..62c874eba 100644 --- a/rules/defense_evasion_system_binary_proxy_execution_via_rundll32.yml +++ b/rules/defense_evasion_system_binary_proxy_execution_via_rundll32.yml @@ -1,6 +1,6 @@ name: System Binary Proxy Execution via Rundll32 id: 43d76718-cc46-485e-8f47-996eb7a9f83b -version: 1.0.4 +version: 1.0.5 description: | Detects the execution of rundll32.exe process with suspicious command line followed by the creation of a possibly malicious child process. @@ -25,7 +25,7 @@ condition: > sequence maxspan 1m |spawn_process and - (ps.name ~= 'rundll32.exe' or pe.file.name ~= 'rundll32.exe') and + (ps.name ~= 'rundll32.exe' or ps.pe.file.name ~= 'rundll32.exe') and ( ps.cmdline imatches ( diff --git a/rules/initial_access_suspicious_execution_via_wmi_from_microsoft_office_process.yml b/rules/initial_access_suspicious_execution_via_wmi_from_microsoft_office_process.yml index bab5186ed..8e44d96b1 100644 --- a/rules/initial_access_suspicious_execution_via_wmi_from_microsoft_office_process.yml +++ b/rules/initial_access_suspicious_execution_via_wmi_from_microsoft_office_process.yml @@ -1,6 +1,6 @@ name: Suspicious execution via WMI from a Microsoft Office process id: cc3f0bbe-ec53-40a7-9eed-f0a8a3f7d7fa -version: 1.0.4 +version: 1.0.5 description: | Identifies a suspicious process execution via Windows Management Instrumentation (WMI) originated from the Microsoft Office process loading an unusual WMI DLL. This technique @@ -57,7 +57,7 @@ condition: > 'wmic.exe', 'msiexec.exe' ) or - pe.file.name iin + ps.pe.file.name iin ( 'rundll32.exe', 'regsvr32.exe', diff --git a/rules/persistence_script_interpreter_or_untrusted_process_persistence.yml b/rules/persistence_script_interpreter_or_untrusted_process_persistence.yml index 8fe860338..a458a0d22 100644 --- a/rules/persistence_script_interpreter_or_untrusted_process_persistence.yml +++ b/rules/persistence_script_interpreter_or_untrusted_process_persistence.yml @@ -1,6 +1,6 @@ name: Script interpreter host or untrusted process persistence id: cc41ee3a-6e44-4903-85a4-0147ec6a7eea -version: 1.1.2 +version: 1.1.3 description: | Identifies the script interpreter or untrusted process writing to commonly abused run keys or the Startup folder locations. @@ -17,7 +17,7 @@ labels: condition: > (((modify_registry) or (create_file)) and evt.pid != 4) and - (ps.name in script_interpreters or ps.parent.name in script_interpreters or pe.is_trusted = false) and + (ps.name in script_interpreters or ps.parent.name in script_interpreters or ps.signature.is_trusted = false) and (registry.path imatches registry_run_keys or file.path imatches startup_locations) and not (ps.exe imatches ( @@ -35,7 +35,7 @@ condition: > '?:\\Program Files\\Google\\Drive File Stream\\*\\GoogleDriveFS.exe', '?:\\Users\\*\\AppData\\Local\\Dropbox\\Dropbox.exe' ) or - (pe.is_signed = true and pe.cert.subject imatches '*Microsoft*')) + (ps.signature.exists = true and ps.signature.subject imatches '*Microsoft*')) action: - name: kill diff --git a/rules/persistence_suspicious_netsh_helper_dll_execution.yml b/rules/persistence_suspicious_netsh_helper_dll_execution.yml index a484b2bcc..45446b357 100644 --- a/rules/persistence_suspicious_netsh_helper_dll_execution.yml +++ b/rules/persistence_suspicious_netsh_helper_dll_execution.yml @@ -1,6 +1,6 @@ name: Suspicious Netsh Helper DLL execution id: bd17781d-38ca-4b9a-a12a-f807a1eb45e0 -version: 1.0.3 +version: 1.0.4 description: | Identifies the execution of a suspicious Netsh Helper DLL. Adversaries may establish persistence by executing malicious content triggered by Netsh Helper DLLs. Netsh.exe is a command-line scripting @@ -25,7 +25,7 @@ condition: > maxspan 1m by ps.uuid |spawn_process and - (ps.name ~= 'netsh.exe' or pe.file.name ~= 'netsh.exe') + (ps.name ~= 'netsh.exe' or ps.pe.file.name ~= 'netsh.exe') | |create_thread and foreach(thread._callstack, $frame, $frame.symbol imatches '*!InitHelperDll' and ($frame.module.signature.is_signed = false or $frame.module.signature.is_trusted = false)) diff --git a/rules/persistence_suspicious_persistence_via_registry_modification.yml b/rules/persistence_suspicious_persistence_via_registry_modification.yml index f2189f6d8..58a44ae56 100644 --- a/rules/persistence_suspicious_persistence_via_registry_modification.yml +++ b/rules/persistence_suspicious_persistence_via_registry_modification.yml @@ -1,6 +1,6 @@ name: Suspicious persistence via registry modification id: 1f496a17-4f0c-491a-823b-7a70adb9919c -version: 1.0.4 +version: 1.0.5 description: | Adversaries may abuse the registry to achieve persistence by modifying the keys that are unlikely modified by legitimate @@ -21,7 +21,7 @@ condition: > ( (ps.name in script_interpreters or ps.name in ('reg.exe', 'rundll32.exe', 'regsvr32.exe')) or ps.exe imatches '?:\\Users\\Public\\*' or - pe.is_signed = false or pe.is_trusted = false + ps.signature.exists = false or ps.signature.is_trusted = false ) and registry.path imatches registry_persistence_keys