diff options
author | Bryan McNulty <bryanmcnulty@protonmail.com> | 2025-04-17 11:26:57 -0500 |
---|---|---|
committer | Bryan McNulty <bryanmcnulty@protonmail.com> | 2025-04-17 11:26:57 -0500 |
commit | 7fa9b35e4ba0eb477dad9258b827766a65c28fef (patch) | |
tree | afb104d095a0fd68e3beabead7df23bfa0695541 /pkg | |
parent | 2d7920941b6a19757911c54181a971d3d35bde02 (diff) | |
download | goexec-7fa9b35e4ba0eb477dad9258b827766a65c28fef.tar.gz goexec-7fa9b35e4ba0eb477dad9258b827766a65c28fef.zip |
Fix `tsch create`
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/goexec/tsch/module.go | 250 |
1 files changed, 125 insertions, 125 deletions
diff --git a/pkg/goexec/tsch/module.go b/pkg/goexec/tsch/module.go index 74ded2f..dd569cf 100644 --- a/pkg/goexec/tsch/module.go +++ b/pkg/goexec/tsch/module.go @@ -1,162 +1,162 @@ package tschexec import ( - "context" - "encoding/xml" - "errors" - "fmt" - "github.com/FalconOpsLLC/goexec/pkg/goexec" - "github.com/FalconOpsLLC/goexec/pkg/goexec/dce" - "github.com/oiweiwei/go-msrpc/msrpc/tsch/itaskschedulerservice/v1" - "github.com/rs/zerolog" + "context" + "encoding/xml" + "errors" + "fmt" + "github.com/FalconOpsLLC/goexec/pkg/goexec" + "github.com/FalconOpsLLC/goexec/pkg/goexec/dce" + "github.com/oiweiwei/go-msrpc/msrpc/tsch/itaskschedulerservice/v1" + "github.com/rs/zerolog" ) const ( - ModuleName = "TSCH" + ModuleName = "TSCH" ) type Tsch struct { - goexec.Cleaner + goexec.Cleaner - Client *dce.Client - tsch itaskschedulerservice.TaskSchedulerServiceClient + Client *dce.Client + tsch itaskschedulerservice.TaskSchedulerServiceClient - TaskPath string - UserSid string - NotHidden bool + TaskPath string + UserSid string + NotHidden bool } type registerOptions struct { - AllowStartOnDemand bool - AllowHardTerminate bool - StartWhenAvailable bool - Hidden bool - DeleteAfter string + AllowStartOnDemand bool + AllowHardTerminate bool + StartWhenAvailable bool + Hidden bool + DeleteAfter string - triggers taskTriggers + triggers taskTriggers } func (m *Tsch) Connect(ctx context.Context) (err error) { - if err = m.Client.Connect(ctx); err == nil { - m.AddCleaner(m.Client.Close) - } - return + if err = m.Client.Connect(ctx); err == nil { + m.AddCleaner(m.Client.Close) + } + return } func (m *Tsch) Init(ctx context.Context) (err error) { - if m.Client.Dce() == nil { - return errors.New("DCE connection not initialized") - } + if m.Client.Dce() == nil { + return errors.New("DCE connection not initialized") + } - // Create ITaskSchedulerService Client - m.tsch, err = itaskschedulerservice.NewTaskSchedulerServiceClient(ctx, m.Client.Dce()) - return + // Create ITaskSchedulerService Client + m.tsch, err = itaskschedulerservice.NewTaskSchedulerServiceClient(ctx, m.Client.Dce()) + return } func (m *Tsch) registerTask(ctx context.Context, opts *registerOptions, in *goexec.ExecutionIO) (path string, err error) { - log := zerolog.Ctx(ctx).With(). - Str("task", m.TaskPath). - Logger() - - ctx = log.WithContext(ctx) - - principalId := "1" // This value can be anything - - settings := taskSettings{ - MultipleInstancesPolicy: "IgnoreNew", - IdleSettings: taskIdleSettings{ - StopOnIdleEnd: true, - RestartOnIdle: false, - }, - Enabled: true, - Priority: 7, // a pretty standard value for scheduled tasks - AllowHardTerminate: opts.AllowHardTerminate, - AllowStartOnDemand: opts.AllowStartOnDemand, - Hidden: opts.Hidden, - StartWhenAvailable: opts.StartWhenAvailable, - DeleteExpiredTaskAfter: opts.DeleteAfter, - } - - principals := taskPrincipals{ - Principals: []taskPrincipal{ - { - ID: principalId, - UserID: m.UserSid, - RunLevel: "HighestAvailable", - }, - }} - - cmdline := in.CommandLine() - - actions := taskActions{ - Context: principalId, - Exec: []taskActionExec{ - { - Command: cmdline[0], - Arguments: cmdline[1], - }, - }, - } - - def := task{ - TaskVersion: TaskXmlVersion, - TaskNamespace: TaskXmlNamespace, - Triggers: opts.triggers, - Actions: actions, - Principals: principals, - Settings: settings, - } - - // Generate task XML content. See https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tsch/0d6383e4-de92-43e7-b0bb-a60cfa36379f - - doc, err := xml.Marshal(def) - - if err != nil { - log.Error().Err(err).Msg("failed to marshal task XML") - return "", fmt.Errorf("marshal task: %w", err) - } - - taskXml := TaskXmlHeader + string(doc) - - log.Debug().Str("content", taskXml).Msg("Generated task XML") - - registerResponse, err := m.tsch.RegisterTask(ctx, &itaskschedulerservice.RegisterTaskRequest{ - Path: m.TaskPath, - XML: taskXml, - Flags: 0, // FEATURE: dynamic - SDDL: "", - LogonType: 0, // FEATURE: dynamic - CredsCount: 0, - Creds: nil, - }) - - if err != nil { - log.Error().Err(err).Msg("Failed to register task") - return "", fmt.Errorf("register task: %w", err) - } - log.Info().Msg("Scheduled task registered") - - return registerResponse.ActualPath, nil + log := zerolog.Ctx(ctx).With(). + Str("task", m.TaskPath). + Logger() + + ctx = log.WithContext(ctx) + + principalId := "1" // This value can be anything + + settings := taskSettings{ + MultipleInstancesPolicy: "IgnoreNew", + IdleSettings: taskIdleSettings{ + StopOnIdleEnd: true, + RestartOnIdle: false, + }, + Enabled: true, + Priority: 7, // a pretty standard value for scheduled tasks + AllowHardTerminate: opts.AllowHardTerminate, + AllowStartOnDemand: opts.AllowStartOnDemand, + Hidden: opts.Hidden, + StartWhenAvailable: opts.StartWhenAvailable, + DeleteExpiredTaskAfter: opts.DeleteAfter, + } + + principals := taskPrincipals{ + Principals: []taskPrincipal{ + { + ID: principalId, + UserID: m.UserSid, + RunLevel: "HighestAvailable", + }, + }} + + cmdline := in.CommandLine() + + actions := taskActions{ + Context: principalId, + Exec: []taskActionExec{ + { + Command: cmdline[0], + Arguments: cmdline[1], + }, + }, + } + + def := task{ + TaskVersion: TaskXmlVersion, + TaskNamespace: TaskXmlNamespace, + Triggers: opts.triggers, + Actions: actions, + Principals: principals, + Settings: settings, + } + + // Generate task XML content. See https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tsch/0d6383e4-de92-43e7-b0bb-a60cfa36379f + + doc, err := xml.Marshal(def) + + if err != nil { + log.Error().Err(err).Msg("failed to marshal task XML") + return "", fmt.Errorf("marshal task: %w", err) + } + + taskXml := TaskXmlHeader + string(doc) + + log.Debug().Str("content", taskXml).Msg("Generated task XML") + + registerResponse, err := m.tsch.RegisterTask(ctx, &itaskschedulerservice.RegisterTaskRequest{ + Path: m.TaskPath, + XML: taskXml, + Flags: 0, // FEATURE: dynamic + SDDL: "", + LogonType: 0, // FEATURE: dynamic + CredsCount: 0, + Creds: nil, + }) + + if err != nil { + log.Error().Err(err).Msg("Failed to register task") + return "", fmt.Errorf("register task: %w", err) + } + log.Info().Msg("Scheduled task registered") + + return registerResponse.ActualPath, nil } func (m *Tsch) deleteTask(ctx context.Context, taskPath string) (err error) { - log := zerolog.Ctx(ctx).With(). - Str("path", taskPath).Logger() + log := zerolog.Ctx(ctx).With(). + Str("path", taskPath).Logger() - _, err = m.tsch.Delete(ctx, &itaskschedulerservice.DeleteRequest{ - Path: taskPath, - }) + _, err = m.tsch.Delete(ctx, &itaskschedulerservice.DeleteRequest{ + Path: taskPath, + }) - if err != nil { - log.Error().Err(err).Msg("Failed to delete task") - return fmt.Errorf("delete task: %w", err) - } + if err != nil { + log.Error().Err(err).Msg("Failed to delete task") + return fmt.Errorf("delete task: %w", err) + } - log.Info().Msg("Task deleted") + log.Info().Msg("Task deleted") - return + return } |