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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ require (
go4.org/netipx v0.0.0-20220725152314-7e7bdc8411bf // indirect
golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/sync v0.12.0 // indirect
golang.org/x/sync v0.21.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
honnef.co/go/tools v0.3.2 // indirect
)
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down
5 changes: 4 additions & 1 deletion internal/bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ package bootstrap
import (
"context"
"errors"
"os"

"github.com/rabbitstack/fibratus/internal/evasion"
"github.com/rabbitstack/fibratus/pkg/aggregator"
"github.com/rabbitstack/fibratus/pkg/alertsender"
Expand All @@ -36,11 +38,11 @@ import (
"github.com/rabbitstack/fibratus/pkg/sys"
"github.com/rabbitstack/fibratus/pkg/util/multierror"
"github.com/rabbitstack/fibratus/pkg/util/signals"
"github.com/rabbitstack/fibratus/pkg/util/signature"
"github.com/rabbitstack/fibratus/pkg/util/version"
"github.com/rabbitstack/fibratus/pkg/yara"
log "github.com/sirupsen/logrus"
"golang.org/x/sys/windows"
"os"
)

// ErrAlreadyRunning signals a Fibratus process is already running in the system
Expand Down Expand Up @@ -427,6 +429,7 @@ func (f *App) stop() {
if f.signals != nil {
f.signals <- struct{}{}
}
signature.GetSignatures().Close()
}

// isSingleInstance checks if there is a single instance
Expand Down
15 changes: 15 additions & 0 deletions internal/etw/processors/fs_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
htypes "github.com/rabbitstack/fibratus/pkg/handle/types"
"github.com/rabbitstack/fibratus/pkg/ps"
"github.com/rabbitstack/fibratus/pkg/sys"
"github.com/rabbitstack/fibratus/pkg/util/signature"
"github.com/rabbitstack/fibratus/pkg/util/va"
"golang.org/x/sys/windows"
)
Expand Down Expand Up @@ -140,6 +141,12 @@ func (f *fsProcessor) processEvent(e *event.Event) (*event.Event, error) {
e.AppendEnum(params.FileType, uint32(fileinfo.Type), fs.FileTypes)
}

// invalidate signature cache
dispo := e.Params.MustGetUint32(params.FileOperation)
if dispo == windows.FILE_OVERWRITE || dispo == windows.FILE_OVERWRITE_IF {
signature.GetSignatures().RemoveSignature(e.GetParamAsString(params.FilePath))
}

return e, nil
case event.ReleaseFile:
fileReleaseCount.Add(1)
Expand Down Expand Up @@ -190,6 +197,14 @@ func (f *fsProcessor) processEvent(e *event.Event) (*event.Event, error) {

if e.IsDeleteFile() {
delete(f.files, fileObject)
if fileinfo != nil {
signature.GetSignatures().RemoveSignature(fileinfo.Name)
}
}
if e.IsRenameFile() {
if fileinfo != nil {
signature.GetSignatures().RemoveSignature(fileinfo.Name)
}
}
if e.IsEnumDirectory() {
if fileinfo != nil {
Expand Down
19 changes: 18 additions & 1 deletion internal/etw/processors/module_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/rabbitstack/fibratus/pkg/event"
"github.com/rabbitstack/fibratus/pkg/event/params"
"github.com/rabbitstack/fibratus/pkg/ps"
"github.com/rabbitstack/fibratus/pkg/util/signature"
)

type moduleProcessor struct {
Expand All @@ -38,7 +39,6 @@ func (*moduleProcessor) Name() ProcessorType { return Module }

func (m *moduleProcessor) ProcessEvent(e *event.Event) (*event.Event, bool, error) {
if e.IsLoadModuleInternal() {
// state management
return e, false, m.psnap.AddModule(e)
}

Expand All @@ -52,6 +52,23 @@ func (m *moduleProcessor) ProcessEvent(e *event.Event) (*event.Event, bool, erro
}

if e.IsLoadModule() || e.IsModuleRundown() {
typ := signature.Type(e.Params.MustGetUint32(params.ModuleSignatureType))
lvl := signature.Level(e.Params.MustGetUint32(params.ModuleSignatureLevel))
// Code Integrity successfully validated the file's trust chain.
// The signature level WINDOWS and WINDOWS_TCB describes the trust
// level assigned after verification.
// A file can reach the WINDOWS signing level through either an embedded PE
// Authenticode signature or a catalog signature where the file hash lives
// in a trusted .cat file.
// Trusted signatures are automatically pushed to the store. On the contrary,
// signature verification is delegated to the async workers
key := e.SignatureKey()
if signature.IsTrusted(typ, lvl) {
signature.GetSignatures().PutSignature(key, typ, lvl)
} else {
signature.GetSignatures().DoRequestAsync(key)
}

return e, false, m.psnap.AddModule(e)
}

Expand Down
10 changes: 10 additions & 0 deletions pkg/event/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,16 @@ func (e *Event) GetFlagsAsSlice(name string) []string {
return strings.Split(e.GetParamAsString(name), "|")
}

// GetParamAsUint64 returns the uint64 value of the given parameter.
func (e *Event) GetParamAsUint64(name string) uint64 {
return e.Params.TryGetUint64(name)
}

// GetParamAsUint32 returns the uint32 value of the given parameter.
func (e *Event) GetParamAsUint32(name string) uint32 {
return e.Params.TryGetUint32(name)
}

// SequenceLink returns the sequence link values from event metadata.
func (e *Event) SequenceLinks() []any {
e.mmux.RLock()
Expand Down
16 changes: 16 additions & 0 deletions pkg/event/event_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/rabbitstack/fibratus/pkg/util/hashers"
"github.com/rabbitstack/fibratus/pkg/util/hostname"
"github.com/rabbitstack/fibratus/pkg/util/ntstatus"
"github.com/rabbitstack/fibratus/pkg/util/signature"
"golang.org/x/sys/windows"
)

Expand Down Expand Up @@ -219,6 +220,7 @@ func (e *Event) IsCloseFile() bool { return e.Type == CloseFile }
func (e *Event) IsCreateHandle() bool { return e.Type == CreateHandle }
func (e *Event) IsCloseHandle() bool { return e.Type == CloseHandle }
func (e *Event) IsDeleteFile() bool { return e.Type == DeleteFile }
func (e *Event) IsRenameFile() bool { return e.Type == RenameFile }
func (e *Event) IsEnumDirectory() bool { return e.Type == EnumDirectory }
func (e *Event) IsTerminateProcess() bool { return e.Type == TerminateProcess }
func (e *Event) IsTerminateThread() bool { return e.Type == TerminateThread }
Expand Down Expand Up @@ -286,6 +288,20 @@ func (e *Event) IsSurrogateProcess() bool {
return e.IsCreateProcess() && e.Params.MustGetUint32(params.ProcessParentID) != e.Params.MustGetUint32(params.ProcessRealParentID)
}

// SignatureKey derives the key into signature store.
func (e *Event) SignatureKey() signature.Key {
if e.IsLoadModule() || e.IsModuleRundown() {
return signature.MakeKey(e.GetParamAsString(params.ModulePath), e.GetParamAsUint64(params.ModuleSize), e.GetParamAsUint32(params.ModuleCheckSum), e.GetParamAsUint32(params.ModuleTimeDateStamp))
}

if e.PS != nil && e.PS.PE != nil {
pe := e.PS.PE
return signature.MakeKey(e.PS.Exe, uint64(pe.ImageSize), pe.ImageChecksum, pe.TimedateStamp)
}

return signature.Key{}
}

// RundownKey calculates the rundown event hash. The hash is
// used to determine if the rundown event was already processed.
func (e *Event) RundownKey() uint64 {
Expand Down
2 changes: 1 addition & 1 deletion pkg/event/param_decoder_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ func (d *ParamDecoder) DecodeModule(r *etw.EventRecord, e *Event) {
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.ModuleTimeDateStamp, params.Uint32, r.ReadUint32(24))
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)
Expand Down
2 changes: 1 addition & 1 deletion pkg/event/param_decoder_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ func TestDecodeModule(t *testing.T) {
e := &Event{Params: make(Params)}
paramDecoder.DecodeModule(r, e)

assert.Len(t, e.Params, 8)
assert.Len(t, e.Params, 9)
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))
Expand Down
2 changes: 2 additions & 0 deletions pkg/event/params/params_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ const (
ModuleSize = "module_size"
// ModuleCheckSum is the parameter name for module checksum.
ModuleCheckSum = "checksum"
// ModuleTimeDateStamp is the parametter name for module timedate stamp.
ModuleTimeDateStamp = "timedate_stamp"
// ModuleDefaultBase is the parameter name that represents module's base address.
ModuleDefaultBase = "default_address"
// ModulePath is the parameter name that denotes the file path and extension of the DLL/executable Module.
Expand Down
Loading
Loading