diff options
author | Bryan McNulty <bryanmcnulty@protonmail.com> | 2025-03-08 06:07:29 -0600 |
---|---|---|
committer | Bryan McNulty <bryanmcnulty@protonmail.com> | 2025-03-08 06:07:29 -0600 |
commit | 7574b7370be083ff563fa8ad6d01d5ac776d7e4d (patch) | |
tree | 78aeb5d671e35aee8780fd92b2511cad00efd67d /internal/exec/tsch/tsch.go | |
parent | d8eca7209d000609fea08d2973a402a41a4cf921 (diff) | |
download | goexec-7574b7370be083ff563fa8ad6d01d5ac776d7e4d.tar.gz goexec-7574b7370be083ff563fa8ad6d01d5ac776d7e4d.zip |
Add a bunch of DCE related options to TSCH module
Diffstat (limited to 'internal/exec/tsch/tsch.go')
-rw-r--r-- | internal/exec/tsch/tsch.go | 183 |
1 files changed, 112 insertions, 71 deletions
diff --git a/internal/exec/tsch/tsch.go b/internal/exec/tsch/tsch.go index bc3ed0b..f2476f1 100644 --- a/internal/exec/tsch/tsch.go +++ b/internal/exec/tsch/tsch.go @@ -1,102 +1,143 @@ package tschexec import ( - "encoding/xml" + "context" + "encoding/xml" + "fmt" + "github.com/oiweiwei/go-msrpc/msrpc/tsch/itaskschedulerservice/v1" + "github.com/rs/zerolog" +) + +const ( + TaskXMLDurationFormat = "2006-01-02T15:04:05.9999999Z" + TaskXMLHeader = `<?xml version="1.0" encoding="UTF-16"?>` ) // https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tsch/0d6383e4-de92-43e7-b0bb-a60cfa36379f +type triggers struct { + XMLName xml.Name `xml:"Triggers"` + TimeTriggers []taskTimeTrigger `xml:"TimeTrigger,omitempty"` +} + type taskTimeTrigger struct { - XMLName xml.Name `xml:"TimeTrigger"` - StartBoundary string `xml:"StartBoundary,omitempty"` // Derived from time.Time - EndBoundary string `xml:"EndBoundary,omitempty"` // Derived from time.Time; must be > StartBoundary - Enabled bool `xml:"Enabled"` + XMLName xml.Name `xml:"TimeTrigger"` + StartBoundary string `xml:"StartBoundary,omitempty"` // Derived from time.Time + EndBoundary string `xml:"EndBoundary,omitempty"` // Derived from time.Time; must be > StartBoundary + Enabled bool `xml:"Enabled"` } type idleSettings struct { - StopOnIdleEnd bool `xml:"StopOnIdleEnd"` - RestartOnIdle bool `xml:"RestartOnIdle"` + XMLName xml.Name `xml:"IdleSettings"` + StopOnIdleEnd bool `xml:"StopOnIdleEnd"` + RestartOnIdle bool `xml:"RestartOnIdle"` } type settings struct { - XMLName xml.Name `xml:"Settings"` - Enabled bool `xml:"Enabled"` - Hidden bool `xml:"Hidden"` - DisallowStartIfOnBatteries bool `xml:"DisallowStartIfOnBatteries"` - StopIfGoingOnBatteries bool `xml:"StopIfGoingOnBatteries"` - AllowHardTerminate bool `xml:"AllowHardTerminate"` - RunOnlyIfNetworkAvailable bool `xml:"RunOnlyIfNetworkAvailable"` - AllowStartOnDemand bool `xml:"AllowStartOnDemand"` - WakeToRun bool `xml:"WakeToRun"` - RunOnlyIfIdle bool `xml:"RunOnlyIfIdle"` - StartWhenAvailable bool `xml:"StartWhenAvailable"` - Priority int `xml:"Priority,omitempty"` // 1 to 10 inclusive - MultipleInstancesPolicy string `xml:"MultipleInstancesPolicy,omitempty"` - ExecutionTimeLimit string `xml:"ExecutionTimeLimit,omitempty"` - DeleteExpiredTaskAfter string `xml:"DeleteExpiredTaskAfter,omitempty"` // Derived from time.Duration - IdleSettings idleSettings `xml:"IdleSettings,omitempty"` + XMLName xml.Name `xml:"Settings"` + Enabled bool `xml:"Enabled"` + Hidden bool `xml:"Hidden"` + DisallowStartIfOnBatteries bool `xml:"DisallowStartIfOnBatteries"` + StopIfGoingOnBatteries bool `xml:"StopIfGoingOnBatteries"` + AllowHardTerminate bool `xml:"AllowHardTerminate"` + RunOnlyIfNetworkAvailable bool `xml:"RunOnlyIfNetworkAvailable"` + AllowStartOnDemand bool `xml:"AllowStartOnDemand"` + WakeToRun bool `xml:"WakeToRun"` + RunOnlyIfIdle bool `xml:"RunOnlyIfIdle"` + StartWhenAvailable bool `xml:"StartWhenAvailable"` + Priority int `xml:"Priority,omitempty"` // 1 to 10 inclusive + MultipleInstancesPolicy string `xml:"MultipleInstancesPolicy,omitempty"` + ExecutionTimeLimit string `xml:"ExecutionTimeLimit,omitempty"` + DeleteExpiredTaskAfter string `xml:"DeleteExpiredTaskAfter,omitempty"` // Derived from time.Duration + IdleSettings idleSettings `xml:"IdleSettings,omitempty"` } type actionExec struct { - XMLName xml.Name `xml:"Exec"` - Command string `xml:"Command"` - Arguments string `xml:"Arguments"` + XMLName xml.Name `xml:"Exec"` + Command string `xml:"Command"` + Arguments string `xml:"Arguments"` } type actions struct { - XMLName xml.Name `xml:"Actions"` - Context string `xml:"Context,attr"` - Exec []actionExec `xml:"Exec,omitempty"` + XMLName xml.Name `xml:"Actions"` + Context string `xml:"Context,attr"` + Exec []actionExec `xml:"Exec,omitempty"` } type principals struct { - XMLName xml.Name `xml:"Principals"` - Principals []principal `xml:"Principal"` + XMLName xml.Name `xml:"Principals"` + Principals []principal `xml:"Principal,omitempty"` } type principal struct { - XMLName xml.Name `xml:"Principal"` - ID string `xml:"id,attr"` - UserID string `xml:"UserId"` - RunLevel string `xml:"RunLevel"` + XMLName xml.Name `xml:"Principal"` + ID string `xml:"id,attr"` + UserID string `xml:"UserId"` + RunLevel string `xml:"RunLevel"` } type task struct { - XMLName xml.Name `xml:"Task"` - TaskVersion string `xml:"version,attr"` - TaskNamespace string `xml:"xmlns,attr"` - TimeTriggers []taskTimeTrigger `xml:"Triggers>TimeTrigger,omitempty"` - Actions actions `xml:"Actions"` - Principals principals `xml:"Principals"` - Settings settings `xml:"Settings"` + XMLName xml.Name `xml:"Task"` + TaskVersion string `xml:"version,attr"` + TaskNamespace string `xml:"xmlns,attr"` + //TimeTriggers []taskTimeTrigger `xml:"Triggers>TimeTrigger,omitempty"` // TODO: triggers type + Triggers triggers `xml:"Triggers"` + Actions actions `xml:"Actions"` + Principals principals `xml:"Principals"` + Settings settings `xml:"Settings"` } -var ( - defaultSettings = settings{ - MultipleInstancesPolicy: "IgnoreNew", - DisallowStartIfOnBatteries: false, - StopIfGoingOnBatteries: false, - AllowHardTerminate: true, - RunOnlyIfNetworkAvailable: false, - IdleSettings: idleSettings{ - StopOnIdleEnd: true, - RestartOnIdle: false, - }, - AllowStartOnDemand: true, - Enabled: true, - Hidden: true, - RunOnlyIfIdle: false, - WakeToRun: false, - Priority: 7, // 7 is a pretty standard value for scheduled tasks - StartWhenAvailable: true, - } - defaultPrincipals = principals{ - Principals: []principal{ - { - ID: "SYSTEM", - UserID: "S-1-5-18", - RunLevel: "HighestAvailable", - }, - }, - } -) +// registerTask serializes and submits the provided task structure +func (mod *Module) registerTask(ctx context.Context, taskDef task, taskPath string) (path string, err error) { + + var taskXml string + + log := zerolog.Ctx(ctx).With(). + Str("module", "tsch"). + Str("func", "createTask").Logger() + + // 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(taskDef) + 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") + } + + // Submit task + { + response, err := mod.tsch.RegisterTask(ctx, &itaskschedulerservice.RegisterTaskRequest{ + Path: taskPath, + XML: taskXml, + Flags: 0, // TODO + LogonType: 0, // TASK_LOGON_NONE + 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().Str("path", taskPath).Msg("Task created successfully") + path = response.ActualPath + } + return +} + +func (mod *Module) deleteTask(ctx context.Context, taskPath string) (err error) { + + log := zerolog.Ctx(ctx).With(). + Str("module", "tsch"). + Str("path", taskPath). + Str("func", "deleteTask").Logger() + + if _, err = mod.tsch.Delete(ctx, &itaskschedulerservice.DeleteRequest{Path: taskPath}); err != nil { + log.Error().Err(err).Msg("Failed to delete task") + return fmt.Errorf("delete task: %w", err) + } + log.Info().Msg("Task deleted successfully") + return +} |