diff options
Diffstat (limited to 'cmd/tsch.go')
-rw-r--r-- | cmd/tsch.go | 282 |
1 files changed, 168 insertions, 114 deletions
diff --git a/cmd/tsch.go b/cmd/tsch.go index 05c55cf..8011cf2 100644 --- a/cmd/tsch.go +++ b/cmd/tsch.go @@ -1,70 +1,78 @@ package cmd import ( - "github.com/FalconOpsLLC/goexec/internal/exec" - "github.com/FalconOpsLLC/goexec/internal/exec/tsch" - "github.com/spf13/cobra" - "time" + "github.com/FalconOpsLLC/goexec/internal/client/dce" + "github.com/FalconOpsLLC/goexec/internal/exec" + "github.com/FalconOpsLLC/goexec/internal/exec/tsch" + "github.com/spf13/cobra" + "time" ) func tschCmdInit() { - tschDeleteCmdInit() - tschCmd.AddCommand(tschDeleteCmd) + registerRpcFlags(tschCmd) - tschRegisterCmdInit() - tschCmd.AddCommand(tschRegisterCmd) - - tschDemandCmdInit() - tschCmd.AddCommand(tschDemandCmd) + tschDeleteCmdInit() + tschCmd.AddCommand(tschDeleteCmd) + tschRegisterCmdInit() + tschCmd.AddCommand(tschRegisterCmd) + tschDemandCmdInit() + tschCmd.AddCommand(tschDemandCmd) } func tschDeleteCmdInit() { - tschDeleteCmd.Flags().StringVarP(&tschTaskPath, "path", "t", "", "Scheduled task path") - tschDeleteCmd.MarkFlagRequired("path") + tschDeleteCmd.Flags().StringVarP(&tschTaskPath, "path", "t", "", "Scheduled task path") + if err := tschDeleteCmd.MarkFlagRequired("path"); err != nil { + panic(err) + } } func tschDemandCmdInit() { - tschDemandCmd.Flags().StringVarP(&executable, "executable", "e", "", "Remote Windows executable to invoke") - tschDemandCmd.Flags().StringVarP(&executableArgs, "args", "a", "", "Arguments to pass to executable") - tschDemandCmd.Flags().StringVarP(&tschName, "name", "n", "", "Target task name") - tschDemandCmd.Flags().BoolVar(&tschNoDelete, "no-delete", false, "Don't delete task after execution") - tschDemandCmd.MarkFlagRequired("executable") + tschDemandCmd.Flags().StringVarP(&executable, "executable", "e", "", "Remote Windows executable to invoke") + tschDemandCmd.Flags().StringVarP(&executableArgs, "args", "a", "", "Arguments to pass to executable") + tschDemandCmd.Flags().StringVarP(&tschName, "name", "n", "", "Target task name") + tschDemandCmd.Flags().BoolVar(&tschNoDelete, "no-delete", false, "Don't delete task after execution") + if err := tschDemandCmd.MarkFlagRequired("executable"); err != nil { + panic(err) + } } func tschRegisterCmdInit() { - tschRegisterCmd.Flags().StringVarP(&executable, "executable", "e", "", "Remote Windows executable to invoke") - tschRegisterCmd.Flags().StringVarP(&executableArgs, "args", "a", "", "Arguments to pass to executable") - tschRegisterCmd.Flags().StringVarP(&tschName, "name", "n", "", "Target task name") - tschRegisterCmd.Flags().DurationVar(&tschStopDelay, "delay-stop", time.Duration(5*time.Second), "Delay between task execution and termination. This will not stop the process spawned by the task") - tschRegisterCmd.Flags().DurationVarP(&tschDelay, "delay-start", "d", time.Duration(5*time.Second), "Delay between task registration and execution") - tschRegisterCmd.Flags().DurationVarP(&tschDeleteDelay, "delay-delete", "D", time.Duration(0*time.Second), "Delay between task termination and deletion") - tschRegisterCmd.Flags().BoolVar(&tschNoDelete, "no-delete", false, "Don't delete task after execution") - tschRegisterCmd.Flags().BoolVar(&tschCallDelete, "call-delete", false, "Directly call SchRpcDelete to delete task") - - tschRegisterCmd.MarkFlagsMutuallyExclusive("no-delete", "delay-delete") - tschRegisterCmd.MarkFlagsMutuallyExclusive("no-delete", "call-delete") - tschRegisterCmd.MarkFlagsMutuallyExclusive("delay-delete", "call-delete") - tschRegisterCmd.MarkFlagRequired("executable") + tschRegisterCmd.Flags().StringVarP(&executable, "executable", "e", "", "Remote Windows executable to invoke") + tschRegisterCmd.Flags().StringVarP(&executableArgs, "args", "a", "", "Arguments to pass to executable") + tschRegisterCmd.Flags().StringVarP(&tschName, "name", "n", "", "Target task name") + tschRegisterCmd.Flags().DurationVar(&tschStopDelay, "delay-stop", time.Duration(5*time.Second), "Delay between task execution and termination. This will not stop the process spawned by the task") + tschRegisterCmd.Flags().DurationVarP(&tschDelay, "delay-start", "d", time.Duration(5*time.Second), "Delay between task registration and execution") + tschRegisterCmd.Flags().DurationVarP(&tschDeleteDelay, "delay-delete", "D", time.Duration(0*time.Second), "Delay between task termination and deletion") + tschRegisterCmd.Flags().BoolVar(&tschNoDelete, "no-delete", false, "Don't delete task after execution") + tschRegisterCmd.Flags().BoolVar(&tschCallDelete, "call-delete", false, "Directly call SchRpcDelete to delete task") + + tschRegisterCmd.MarkFlagsMutuallyExclusive("no-delete", "delay-delete") + tschRegisterCmd.MarkFlagsMutuallyExclusive("no-delete", "call-delete") + tschRegisterCmd.MarkFlagsMutuallyExclusive("delay-delete", "call-delete") + + if err := tschRegisterCmd.MarkFlagRequired("executable"); err != nil { + panic(err) + } } var ( - tschNoDelete bool - tschCallDelete bool - tschDeleteDelay time.Duration - tschStopDelay time.Duration - tschDelay time.Duration - tschName string - tschTaskPath string - - tschCmd = &cobra.Command{ - Use: "tsch", - Short: "Establish execution via TSCH (ITaskSchedulerService)", - Args: cobra.NoArgs, - } - tschRegisterCmd = &cobra.Command{ - Use: "register [target]", - Short: "Register a remote scheduled task with an automatic start time", - Long: `Description: + tschNoDelete bool + tschCallDelete bool + tschDeleteDelay time.Duration + tschStopDelay time.Duration + tschDelay time.Duration + tschName string + tschTaskPath string + + tschCmd = &cobra.Command{ + Use: "tsch", + Short: "Establish execution via TSCH (ITaskSchedulerService)", + Args: cobra.NoArgs, + } + tschRegisterCmd = &cobra.Command{ + Use: "register [target]", + Short: "Register a remote scheduled task with an automatic start time", + Long: `Description: The register 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 @@ -76,35 +84,51 @@ 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: needsTarget, - Run: func(cmd *cobra.Command, args []string) { - if tschNoDelete { - log.Warn().Msg("Task will not be deleted after execution") - } - module := tschexec.Module{} - execCfg := &exec.ExecutionConfig{ - ExecutableName: executable, - ExecutableArgs: executableArgs, - ExecutionMethod: tschexec.MethodRegister, - - ExecutionMethodConfig: tschexec.MethodRegisterConfig{ - NoDelete: tschNoDelete, - CallDelete: tschCallDelete, - StartDelay: tschDelay, - StopDelay: tschStopDelay, - DeleteDelay: tschDeleteDelay, - TaskName: tschName, - }, - } - if err := module.Exec(log.WithContext(ctx), creds, target, execCfg); err != nil { - log.Fatal().Err(err).Msg("TSCH execution failed") - } - }, - } - tschDemandCmd = &cobra.Command{ - Use: "demand [target]", - Short: "Register a remote scheduled task and demand immediate start", - Long: `Description: + Args: needsRpcTarget("cifs"), + Run: func(cmd *cobra.Command, args []string) { + + log = log.With(). + Str("module", "tsch"). + Str("method", "register"). + Logger() + if tschNoDelete { + log.Warn().Msg("Task will not be deleted after execution") + } + + module := tschexec.Module{} + connCfg := &exec.ConnectionConfig{ + ConnectionMethod: exec.ConnectionMethodDCE, + ConnectionMethodConfig: dce.ConnectionMethodDCEConfig{ + Endpoint: dceStringBinding, + Options: dceOptions, + EpmAuto: argDceEpmAuto, + }, + } + execCfg := &exec.ExecutionConfig{ + ExecutableName: executable, + ExecutableArgs: executableArgs, + ExecutionMethod: tschexec.MethodRegister, + + ExecutionMethodConfig: tschexec.MethodRegisterConfig{ + NoDelete: tschNoDelete, + CallDelete: tschCallDelete, + StartDelay: tschDelay, + StopDelay: tschStopDelay, + DeleteDelay: tschDeleteDelay, + TaskPath: tschTaskPath, + }, + } + if err := module.Connect(log.WithContext(ctx), creds, target, connCfg); err != nil { + log.Fatal().Err(err).Msg("Connection failed") + } else if err = module.Exec(log.WithContext(ctx), execCfg); err != nil { + log.Fatal().Err(err).Msg("Execution failed") + } + }, + } + tschDemandCmd = &cobra.Command{ + Use: "demand [target]", + Short: "Register a remote scheduled task and demand immediate start", + Long: `Description: Similar to the register 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. @@ -113,46 +137,76 @@ 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: needsTarget, - Run: func(cmd *cobra.Command, args []string) { - if tschNoDelete { - log.Warn().Msg("Task will not be deleted after execution") - } - module := tschexec.Module{} - execCfg := &exec.ExecutionConfig{ - ExecutableName: executable, - ExecutableArgs: executableArgs, - ExecutionMethod: tschexec.MethodDemand, - - ExecutionMethodConfig: tschexec.MethodDemandConfig{ - NoDelete: tschNoDelete, - TaskName: tschName, - }, - } - if err := module.Exec(log.WithContext(ctx), creds, target, execCfg); err != nil { - log.Fatal().Err(err).Msg("TSCH execution failed") - } - }, - } - tschDeleteCmd = &cobra.Command{ - Use: "delete [target]", - Short: "Manually delete a scheduled task", - Long: `Description: + Args: needsTarget("cifs"), + Run: func(cmd *cobra.Command, args []string) { + + log = log.With(). + Str("module", "tsch"). + Str("method", "register"). + Logger() + if tschNoDelete { + log.Warn().Msg("Task will not be deleted after execution") + } + module := tschexec.Module{} + connCfg := &exec.ConnectionConfig{ + ConnectionMethod: exec.ConnectionMethodDCE, + ConnectionMethodConfig: dce.ConnectionMethodDCEConfig{ + Endpoint: dceStringBinding, + Options: dceOptions, + EpmAuto: argDceEpmAuto, + }, + } + execCfg := &exec.ExecutionConfig{ + ExecutableName: executable, + ExecutableArgs: executableArgs, + ExecutionMethod: tschexec.MethodDemand, + + ExecutionMethodConfig: tschexec.MethodDemandConfig{ + NoDelete: tschNoDelete, + TaskName: tschName, + }, + } + if err := module.Connect(log.WithContext(ctx), creds, target, connCfg); err != nil { + log.Fatal().Err(err).Msg("Connection failed") + } else if err = module.Exec(log.WithContext(ctx), execCfg); err != nil { + log.Fatal().Err(err).Msg("Execution failed") + } + }, + } + tschDeleteCmd = &cobra.Command{ + Use: "delete [target]", + Short: "Manually delete a scheduled task", + Long: `Description: The delete method manually deletes a scheduled task by calling SchRpcDelete References: SchRpcDelete - https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tsch/360bb9b1-dd2a-4b36-83ee-21f12cb97cff `, - Args: needsTarget, - Run: func(cmd *cobra.Command, args []string) { - module := tschexec.Module{} - cleanCfg := &exec.CleanupConfig{ - CleanupMethod: tschexec.MethodDelete, - CleanupMethodConfig: tschexec.MethodDeleteConfig{TaskPath: tschTaskPath}, - } - if err := module.Cleanup(log.WithContext(ctx), creds, target, cleanCfg); err != nil { - log.Fatal().Err(err).Msg("TSCH cleanup failed") - } - }, - } + Args: needsTarget("cifs"), + Run: func(cmd *cobra.Command, args []string) { + log = log.With(). + Str("module", "tsch"). + Str("method", "delete"). + Logger() + + module := tschexec.Module{} + connCfg := &exec.ConnectionConfig{ + ConnectionMethod: exec.ConnectionMethodDCE, + ConnectionMethodConfig: dce.ConnectionMethodDCEConfig{ + Endpoint: dceStringBinding, + Options: dceOptions, + EpmAuto: argDceEpmAuto, + }, + } + cleanCfg := &exec.CleanupConfig{ + CleanupMethod: tschexec.MethodDelete, + CleanupMethodConfig: tschexec.MethodDeleteConfig{TaskPath: tschTaskPath}, + } + if err := module.Connect(log.WithContext(ctx), creds, target, connCfg); err != nil { + log.Fatal().Err(err).Msg("Connection failed") + } else if err := module.Cleanup(log.WithContext(ctx), cleanCfg); err != nil { + log.Fatal().Err(err).Msg("Cleanup failed") + } + }, + } ) |