diff options
Diffstat (limited to 'cmd/tsch.go')
-rw-r--r-- | cmd/tsch.go | 208 |
1 files changed, 102 insertions, 106 deletions
diff --git a/cmd/tsch.go b/cmd/tsch.go index 9192b0a..328adcd 100644 --- a/cmd/tsch.go +++ b/cmd/tsch.go @@ -1,87 +1,87 @@ package cmd import ( - "context" - "github.com/FalconOpsLLC/goexec/internal/util" - "github.com/FalconOpsLLC/goexec/pkg/goexec" - tschexec "github.com/FalconOpsLLC/goexec/pkg/goexec/tsch" - "github.com/oiweiwei/go-msrpc/ssp/gssapi" - "github.com/spf13/cobra" - "time" + "context" + "github.com/FalconOpsLLC/goexec/internal/util" + "github.com/FalconOpsLLC/goexec/pkg/goexec" + tschexec "github.com/FalconOpsLLC/goexec/pkg/goexec/tsch" + "github.com/oiweiwei/go-msrpc/ssp/gssapi" + "github.com/spf13/cobra" + "time" ) func tschCmdInit() { - registerRpcFlags(tschCmd) + registerRpcFlags(tschCmd) - tschDemandCmdInit() - tschCmd.AddCommand(tschDemandCmd) + tschDemandCmdInit() + tschCmd.AddCommand(tschDemandCmd) - tschCreateCmdInit() - tschCmd.AddCommand(tschCreateCmd) + tschCreateCmdInit() + tschCmd.AddCommand(tschCreateCmd) } func argsTschTaskIdentifiers(name, path string) error { - switch { - case path != "": - return tschexec.ValidateTaskPath(path) - case name != "": - return tschexec.ValidateTaskName(name) - default: - } - return nil + switch { + case path != "": + return tschexec.ValidateTaskPath(path) + case name != "": + return tschexec.ValidateTaskName(name) + default: + } + return nil } func argsTschDemand(_ *cobra.Command, _ []string) error { - return argsTschTaskIdentifiers(tschDemand.TaskName, tschDemand.TaskPath) + return argsTschTaskIdentifiers(tschDemand.TaskName, tschDemand.TaskPath) } func argsTschCreate(_ *cobra.Command, _ []string) error { - return argsTschTaskIdentifiers(tschCreate.TaskName, tschCreate.TaskPath) + return argsTschTaskIdentifiers(tschCreate.TaskName, tschCreate.TaskPath) } func tschDemandCmdInit() { - tschDemandCmd.Flags().StringVarP(&tschDemand.TaskName, "name", "t", "", "Name of task to register") - tschDemandCmd.Flags().StringVarP(&tschDemand.TaskPath, "path", "P", "", "Path of task to register") - tschDemandCmd.Flags().Uint32Var(&tschDemand.SessionId, "session", 0, "Hijack existing session given the session ID") - tschDemandCmd.Flags().BoolVar(&tschDemand.NoDelete, "no-delete", false, "Don't delete task after execution") - tschDemandCmd.Flags().StringVar(&tschDemand.UserSid, "sid", "S-1-5-18", "User SID to impersonate") + tschDemandCmd.Flags().StringVarP(&tschDemand.TaskName, "name", "t", "", "Name of task to register") + tschDemandCmd.Flags().StringVarP(&tschDemand.TaskPath, "path", "P", "", "Path of task to register") + tschDemandCmd.Flags().Uint32Var(&tschDemand.SessionId, "session", 0, "Hijack existing session given the session ID") + tschDemandCmd.Flags().BoolVar(&tschDemand.NoDelete, "no-delete", false, "Don't delete task after execution") + tschDemandCmd.Flags().StringVar(&tschDemand.UserSid, "sid", "S-1-5-18", "User SID to impersonate") - registerProcessExecutionArgs(tschDemandCmd) - registerExecutionOutputArgs(tschDemandCmd) + registerProcessExecutionArgs(tschDemandCmd) + registerExecutionOutputArgs(tschDemandCmd) - tschDemandCmd.MarkFlagsMutuallyExclusive("name", "path") + tschDemandCmd.MarkFlagsMutuallyExclusive("name", "path") } func tschCreateCmdInit() { - tschCreateCmd.Flags().StringVarP(&tschCreate.TaskName, "name", "t", "", "Name of task to register") - tschCreateCmd.Flags().StringVarP(&tschCreate.TaskPath, "path", "P", "", "Path of task to register") - tschCreateCmd.Flags().DurationVar(&tschCreate.StopDelay, "delay-stop", 5*time.Second, "Delay between task execution and termination. This will not stop the process spawned by the task") - tschCreateCmd.Flags().DurationVar(&tschCreate.StartDelay, "start-delay", 5*time.Second, "Delay between task registration and execution") - tschCreateCmd.Flags().DurationVar(&tschCreate.DeleteDelay, "delete-delay", 0*time.Second, "Delay between task termination and deletion") - tschCreateCmd.Flags().BoolVar(&tschCreate.NoDelete, "no-delete", false, "Don't delete task after execution") - tschCreateCmd.Flags().BoolVar(&tschCreate.CallDelete, "call-delete", false, "Directly call SchRpcDelete to delete task") - tschCreateCmd.Flags().StringVar(&tschCreate.UserSid, "sid", "S-1-5-18", "User SID to impersonate") - - registerProcessExecutionArgs(tschCreateCmd) - registerExecutionOutputArgs(tschCreateCmd) - - tschCreateCmd.MarkFlagsMutuallyExclusive("name", "path") + tschCreateCmd.Flags().StringVarP(&tschCreate.TaskName, "name", "t", "", "Name of task to register") + tschCreateCmd.Flags().StringVarP(&tschCreate.TaskPath, "path", "P", "", "Path of task to register") + tschCreateCmd.Flags().DurationVar(&tschCreate.StopDelay, "delay-stop", 5*time.Second, "Delay between task execution and termination. This will not stop the process spawned by the task") + tschCreateCmd.Flags().DurationVar(&tschCreate.StartDelay, "start-delay", 5*time.Second, "Delay between task registration and execution") + tschCreateCmd.Flags().DurationVar(&tschCreate.DeleteDelay, "delete-delay", 0*time.Second, "Delay between task termination and deletion") + tschCreateCmd.Flags().BoolVar(&tschCreate.NoDelete, "no-delete", false, "Don't delete task after execution") + tschCreateCmd.Flags().BoolVar(&tschCreate.CallDelete, "call-delete", false, "Directly call SchRpcDelete to delete task") + tschCreateCmd.Flags().StringVar(&tschCreate.UserSid, "sid", "S-1-5-18", "User SID to impersonate") + + registerProcessExecutionArgs(tschCreateCmd) + registerExecutionOutputArgs(tschCreateCmd) + + tschCreateCmd.MarkFlagsMutuallyExclusive("name", "path") } var ( - tschDemand tschexec.TschDemand - tschCreate tschexec.TschCreate - - tschCmd = &cobra.Command{ - Use: "tsch", - Short: "Establish execution via Windows Task Scheduler (MS-TSCH)", - Args: cobra.NoArgs, - } - - tschDemandCmd = &cobra.Command{ - Use: "demand [target]", - Short: "Register a remote scheduled task and demand immediate start", - Long: `Description: + tschDemand tschexec.TschDemand + tschCreate tschexec.TschCreate + + tschCmd = &cobra.Command{ + Use: "tsch", + Short: "Establish execution via Windows Task Scheduler (MS-TSCH)", + Args: cobra.NoArgs, + } + + tschDemandCmd = &cobra.Command{ + Use: "demand [target]", + Short: "Register a remote scheduled task and demand immediate start", + Long: `Description: Similar to the create method, the demand method will call SchRpcRegisterTask, But rather than setting a defined time when the task will start, it will additionally call SchRpcRun to forcefully start the task. @@ -90,33 +90,31 @@ References: SchRpcRegisterTask - https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tsch/849c131a-64e4-46ef-b015-9d4c599c5167 SchRpcRun - https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tsch/77f2250d-500a-40ee-be18-c82f7079c4f0 `, - Args: args( - argsRpcClient("cifs"), - argsOutput("smb"), - argsTschDemand, - ), - - Run: func(cmd *cobra.Command, args []string) { - var err error - - tschDemand.Client = &rpcClient - tschDemand.IO = exec - - if tschDemand.TaskName == "" && tschDemand.TaskPath == "" { - tschDemand.TaskPath = `\` + util.RandomString() - } - - ctx := log.WithContext(gssapi.NewSecurityContext(context.TODO())) - - if err = goexec.ExecuteCleanMethod(ctx, &tschDemand, &exec); err != nil { - log.Fatal().Err(err).Msg("Operation failed") - } - }, - } - tschCreateCmd = &cobra.Command{ - Use: "create [target]", - Short: "Create a remote scheduled task with an automatic start time", - Long: `Description: + Args: args( + argsRpcClient("cifs"), + argsOutput("smb"), + argsTschDemand, + ), + + Run: func(cmd *cobra.Command, args []string) { + tschDemand.Client = &rpcClient + tschDemand.IO = exec + + if tschDemand.TaskName == "" && tschDemand.TaskPath == "" { + tschDemand.TaskPath = `\` + util.RandomString() + } + + ctx := log.WithContext(gssapi.NewSecurityContext(context.TODO())) + + if err := goexec.ExecuteCleanMethod(ctx, &tschDemand, &exec); err != nil { + log.Fatal().Err(err).Msg("Operation failed") + } + }, + } + tschCreateCmd = &cobra.Command{ + Use: "create [target]", + Short: "Create a remote scheduled task with an automatic start time", + Long: `Description: The create method calls SchRpcRegisterTask to register a scheduled task with an automatic start time.This method avoids directly calling SchRpcRun, and can even avoid calling SchRpcDelete by populating the DeleteExpiredTaskAfter @@ -128,27 +126,25 @@ References: SchRpcDelete - https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tsch/360bb9b1-dd2a-4b36-83ee-21f12cb97cff DeleteExpiredTaskAfter - https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tsch/6bfde6fe-440e-4ddd-b4d6-c8fc0bc06fae `, - Args: args( - argsRpcClient("cifs"), - argsOutput("smb"), - argsTschCreate, - ), - - Run: func(cmd *cobra.Command, args []string) { - var err error - - tschCreate.Tsch.Client = &rpcClient - tschCreate.IO = exec - - if tschCreate.TaskName == "" && tschDemand.TaskPath == "" { - tschCreate.TaskPath = `\` + util.RandomString() - } - - ctx := log.WithContext(gssapi.NewSecurityContext(context.TODO())) - - if err = goexec.ExecuteCleanMethod(ctx, &tschCreate, &exec); err != nil { - log.Fatal().Err(err).Msg("Operation failed") - } - }, - } + Args: args( + argsRpcClient("cifs"), + argsOutput("smb"), + argsTschCreate, + ), + + Run: func(cmd *cobra.Command, args []string) { + tschCreate.Tsch.Client = &rpcClient + tschCreate.IO = exec + + if tschCreate.TaskName == "" && tschDemand.TaskPath == "" { + tschCreate.TaskPath = `\` + util.RandomString() + } + + ctx := log.WithContext(gssapi.NewSecurityContext(context.TODO())) + + if err := goexec.ExecuteCleanMethod(ctx, &tschCreate, &exec); err != nil { + log.Fatal().Err(err).Msg("Operation failed") + } + }, + } ) |