aboutsummaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorBryan McNulty <bryanmcnulty@protonmail.com>2025-04-26 05:18:48 -0500
committerBryan McNulty <bryanmcnulty@protonmail.com>2025-04-26 05:18:48 -0500
commit7770ce5c15dff99c1100f9fe6e41c502a94cd713 (patch)
tree3aef1a4d027cecece4fc833af0777357334929e3 /cmd
parent00205e02bd1768254e5ee2519cf7027cbcab5ee6 (diff)
downloadgoexec-7770ce5c15dff99c1100f9fe6e41c502a94cd713.tar.gz
goexec-7770ce5c15dff99c1100f9fe6e41c502a94cd713.zip
Fixed some more linter issues
Diffstat (limited to 'cmd')
-rw-r--r--cmd/args.go3
-rw-r--r--cmd/root.go18
-rw-r--r--cmd/tsch.go386
3 files changed, 205 insertions, 202 deletions
diff --git a/cmd/args.go b/cmd/args.go
index 9568395..40b9701 100644
--- a/cmd/args.go
+++ b/cmd/args.go
@@ -29,10 +29,13 @@ func registerNetworkFlags(fs *pflag.FlagSet) {
//cmd.MarkFlagsMutuallyExclusive("no-epm", "epm-filter")
}
+// FUTURE: automatically stage & execute file
+/*
func registerStageFlags(fs *pflag.FlagSet) {
fs.StringVarP(&stageFilePath, "stage", "E", "", "File to stage and execute")
//fs.StringVarP(&stageArgs ...)
}
+*/
func registerExecutionFlags(fs *pflag.FlagSet) {
fs.StringVarP(&exec.Input.Executable, "exec", "e", "", "Remote Windows executable to invoke")
diff --git a/cmd/root.go b/cmd/root.go
index 12f3e19..a66fa62 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -60,9 +60,9 @@ var (
toClose []io.Closer
// === IO ===
- stageFilePath string
- outputMethod string
- outputPath string
+ //stageFilePath string // FUTURE
+ outputMethod string
+ outputPath string
// ==========
// === Logging ===
@@ -196,6 +196,12 @@ Authors: FalconOps LLC (@FalconOpsLLC),
pprof.StopCPUProfile()
}
+ if exec.Input != nil && exec.Input.StageFile != nil {
+ if err := exec.Input.StageFile.Close(); err != nil {
+ log.Warn().Err(err).Msg("Failed to close stage file")
+ }
+ }
+
for _, c := range toClose {
if c != nil {
if err := c.Close(); err != nil {
@@ -203,12 +209,6 @@ Authors: FalconOps LLC (@FalconOpsLLC),
}
}
}
-
- if exec.Input != nil && exec.Input.StageFile != nil {
- if err := exec.Input.StageFile.Close(); err != nil {
- // ...
- }
- }
},
}
)
diff --git a/cmd/tsch.go b/cmd/tsch.go
index ec3504f..f58caf6 100644
--- a/cmd/tsch.go
+++ b/cmd/tsch.go
@@ -1,233 +1,233 @@
package cmd
import (
- "context"
- "fmt"
- "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"
+ "fmt"
+ "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() {
- cmdFlags[tschCmd] = []*flagSet{
- defaultAuthFlags,
- defaultLogFlags,
- defaultNetRpcFlags,
- }
- tschDemandCmdInit()
- tschCreateCmdInit()
- tschChangeCmdInit()
-
- tschCmd.PersistentFlags().AddFlagSet(defaultAuthFlags.Flags)
- tschCmd.PersistentFlags().AddFlagSet(defaultLogFlags.Flags)
- tschCmd.PersistentFlags().AddFlagSet(defaultNetRpcFlags.Flags)
- tschCmd.AddCommand(tschDemandCmd, tschCreateCmd, tschChangeCmd)
+ cmdFlags[tschCmd] = []*flagSet{
+ defaultAuthFlags,
+ defaultLogFlags,
+ defaultNetRpcFlags,
+ }
+ tschDemandCmdInit()
+ tschCreateCmdInit()
+ tschChangeCmdInit()
+
+ tschCmd.PersistentFlags().AddFlagSet(defaultAuthFlags.Flags)
+ tschCmd.PersistentFlags().AddFlagSet(defaultLogFlags.Flags)
+ tschCmd.PersistentFlags().AddFlagSet(defaultNetRpcFlags.Flags)
+ tschCmd.AddCommand(tschDemandCmd, tschCreateCmd, tschChangeCmd)
}
func tschDemandCmdInit() {
- tschDemandFlags := newFlagSet("Task Scheduler")
+ tschDemandFlags := newFlagSet("Task Scheduler")
- tschDemandFlags.Flags.StringVarP(&tschTask, "task", "t", "", "Name or path of the new task")
- tschDemandFlags.Flags.Uint32Var(&tschDemand.SessionId, "session", 0, "Hijack existing session given the session `ID`")
- tschDemandFlags.Flags.StringVar(&tschDemand.UserSid, "sid", "S-1-5-18", "User `SID` to impersonate")
- tschDemandFlags.Flags.BoolVar(&tschDemand.NoDelete, "no-delete", false, "Don't delete task after execution")
+ tschDemandFlags.Flags.StringVarP(&tschTask, "task", "t", "", "Name or path of the new task")
+ tschDemandFlags.Flags.Uint32Var(&tschDemand.SessionId, "session", 0, "Hijack existing session given the session `ID`")
+ tschDemandFlags.Flags.StringVar(&tschDemand.UserSid, "sid", "S-1-5-18", "User `SID` to impersonate")
+ tschDemandFlags.Flags.BoolVar(&tschDemand.NoDelete, "no-delete", false, "Don't delete task after execution")
- tschDemandExecFlags := newFlagSet("Execution")
+ tschDemandExecFlags := newFlagSet("Execution")
- registerExecutionFlags(tschDemandExecFlags.Flags)
- registerExecutionOutputFlags(tschDemandExecFlags.Flags)
+ registerExecutionFlags(tschDemandExecFlags.Flags)
+ registerExecutionOutputFlags(tschDemandExecFlags.Flags)
- cmdFlags[tschDemandCmd] = []*flagSet{
- tschDemandFlags,
- tschDemandExecFlags,
- defaultAuthFlags,
- defaultLogFlags,
- defaultNetRpcFlags,
- }
+ cmdFlags[tschDemandCmd] = []*flagSet{
+ tschDemandFlags,
+ tschDemandExecFlags,
+ defaultAuthFlags,
+ defaultLogFlags,
+ defaultNetRpcFlags,
+ }
- tschDemandCmd.Flags().AddFlagSet(tschDemandFlags.Flags)
- tschDemandCmd.Flags().AddFlagSet(tschDemandExecFlags.Flags)
- tschDemandCmd.MarkFlagsOneRequired("exec", "command")
+ tschDemandCmd.Flags().AddFlagSet(tschDemandFlags.Flags)
+ tschDemandCmd.Flags().AddFlagSet(tschDemandExecFlags.Flags)
+ tschDemandCmd.MarkFlagsOneRequired("exec", "command")
}
func tschCreateCmdInit() {
- tschCreateFlags := newFlagSet("Task Scheduler")
-
- tschCreateFlags.Flags.StringVarP(&tschTask, "task", "t", "", "Name or path of the new task")
- tschCreateFlags.Flags.DurationVar(&tschCreate.StopDelay, "delay-stop", 5*time.Second, "Delay between task execution and termination. This won't stop the spawned process")
- tschCreateFlags.Flags.DurationVar(&tschCreate.StartDelay, "start-delay", 5*time.Second, "Delay between task registration and execution")
- //tschCreateFlags.Flags.DurationVar(&tschCreate.DeleteDelay, "delete-delay", 0*time.Second, "Delay between task termination and deletion")
- tschCreateFlags.Flags.BoolVar(&tschCreate.NoDelete, "no-delete", false, "Don't delete task after execution")
- tschCreateFlags.Flags.BoolVar(&tschCreate.CallDelete, "call-delete", false, "Directly call SchRpcDelete to delete task")
- tschCreateFlags.Flags.StringVar(&tschCreate.UserSid, "sid", "S-1-5-18", "User `SID` to impersonate")
-
- tschCreateExecFlags := newFlagSet("Execution")
-
- registerExecutionFlags(tschCreateExecFlags.Flags)
- registerExecutionOutputFlags(tschCreateExecFlags.Flags)
-
- cmdFlags[tschCreateCmd] = []*flagSet{
- tschCreateFlags,
- tschCreateExecFlags,
- defaultAuthFlags,
- defaultLogFlags,
- defaultNetRpcFlags,
- }
-
- tschCreateCmd.Flags().AddFlagSet(tschCreateFlags.Flags)
- tschCreateCmd.Flags().AddFlagSet(tschCreateExecFlags.Flags)
- tschCreateCmd.MarkFlagsOneRequired("exec", "command")
+ tschCreateFlags := newFlagSet("Task Scheduler")
+
+ tschCreateFlags.Flags.StringVarP(&tschTask, "task", "t", "", "Name or path of the new task")
+ tschCreateFlags.Flags.DurationVar(&tschCreate.StopDelay, "delay-stop", 5*time.Second, "Delay between task execution and termination. This won't stop the spawned process")
+ tschCreateFlags.Flags.DurationVar(&tschCreate.StartDelay, "start-delay", 5*time.Second, "Delay between task registration and execution")
+ //tschCreateFlags.Flags.DurationVar(&tschCreate.DeleteDelay, "delete-delay", 0*time.Second, "Delay between task termination and deletion")
+ tschCreateFlags.Flags.BoolVar(&tschCreate.NoDelete, "no-delete", false, "Don't delete task after execution")
+ tschCreateFlags.Flags.BoolVar(&tschCreate.CallDelete, "call-delete", false, "Directly call SchRpcDelete to delete task")
+ tschCreateFlags.Flags.StringVar(&tschCreate.UserSid, "sid", "S-1-5-18", "User `SID` to impersonate")
+
+ tschCreateExecFlags := newFlagSet("Execution")
+
+ registerExecutionFlags(tschCreateExecFlags.Flags)
+ registerExecutionOutputFlags(tschCreateExecFlags.Flags)
+
+ cmdFlags[tschCreateCmd] = []*flagSet{
+ tschCreateFlags,
+ tschCreateExecFlags,
+ defaultAuthFlags,
+ defaultLogFlags,
+ defaultNetRpcFlags,
+ }
+
+ tschCreateCmd.Flags().AddFlagSet(tschCreateFlags.Flags)
+ tschCreateCmd.Flags().AddFlagSet(tschCreateExecFlags.Flags)
+ tschCreateCmd.MarkFlagsOneRequired("exec", "command")
}
func tschChangeCmdInit() {
- tschChangeFlags := newFlagSet("Task Scheduler")
-
- tschChangeFlags.Flags.StringVarP(&tschChange.TaskPath, "task", "t", "", "Path to existing task")
- tschChangeFlags.Flags.BoolVar(&tschChange.NoStart, "no-start", false, "Don't start the task")
- tschChangeFlags.Flags.BoolVar(&tschChange.NoRevert, "no-revert", false, "Don't restore the original task definition")
-
- tschChangeExecFlags := newFlagSet("Execution")
-
- registerExecutionFlags(tschChangeExecFlags.Flags)
- registerExecutionOutputFlags(tschChangeExecFlags.Flags)
-
- cmdFlags[tschChangeCmd] = []*flagSet{
- tschChangeFlags,
- tschChangeExecFlags,
- defaultAuthFlags,
- defaultLogFlags,
- defaultNetRpcFlags,
- }
-
- tschChangeCmd.Flags().AddFlagSet(tschChangeFlags.Flags)
- tschChangeCmd.Flags().AddFlagSet(tschChangeExecFlags.Flags)
-
- // Constraints
- {
- if err := tschChangeCmd.MarkFlagRequired("task"); err != nil {
- panic(err)
- }
- tschChangeCmd.MarkFlagsOneRequired("exec", "command")
- }
+ tschChangeFlags := newFlagSet("Task Scheduler")
+
+ tschChangeFlags.Flags.StringVarP(&tschChange.TaskPath, "task", "t", "", "Path to existing task")
+ tschChangeFlags.Flags.BoolVar(&tschChange.NoStart, "no-start", false, "Don't start the task")
+ tschChangeFlags.Flags.BoolVar(&tschChange.NoRevert, "no-revert", false, "Don't restore the original task definition")
+
+ tschChangeExecFlags := newFlagSet("Execution")
+
+ registerExecutionFlags(tschChangeExecFlags.Flags)
+ registerExecutionOutputFlags(tschChangeExecFlags.Flags)
+
+ cmdFlags[tschChangeCmd] = []*flagSet{
+ tschChangeFlags,
+ tschChangeExecFlags,
+ defaultAuthFlags,
+ defaultLogFlags,
+ defaultNetRpcFlags,
+ }
+
+ tschChangeCmd.Flags().AddFlagSet(tschChangeFlags.Flags)
+ tschChangeCmd.Flags().AddFlagSet(tschChangeExecFlags.Flags)
+
+ // Constraints
+ {
+ if err := tschChangeCmd.MarkFlagRequired("task"); err != nil {
+ panic(err)
+ }
+ tschChangeCmd.MarkFlagsOneRequired("exec", "command")
+ }
}
func argsTask(*cobra.Command, []string) error {
- switch {
- case tschTask == "":
- tschTask = `\` + util.RandomString()
- case tschexec.ValidateTaskPath(tschTask) == nil:
- case tschexec.ValidateTaskName(tschTask) == nil:
- tschTask = `\` + tschTask
- default:
- return fmt.Errorf("invalid task Label or path: %q", tschTask)
- }
- return nil
+ switch {
+ case tschTask == "":
+ tschTask = `\` + util.RandomString()
+ case tschexec.ValidateTaskPath(tschTask) == nil:
+ case tschexec.ValidateTaskName(tschTask) == nil:
+ tschTask = `\` + tschTask
+ default:
+ return fmt.Errorf("invalid task Label or path: %q", tschTask)
+ }
+ return nil
}
var (
- tschDemand tschexec.TschDemand
- tschCreate tschexec.TschCreate
- tschChange tschexec.TschChange
+ tschDemand tschexec.TschDemand
+ tschCreate tschexec.TschCreate
+ tschChange tschexec.TschChange
- tschTask string
+ tschTask string
- tschCmd = &cobra.Command{
- Use: "tsch",
- Short: "Execute with Windows Task Scheduler (MS-TSCH)",
- Long: `Description:
+ tschCmd = &cobra.Command{
+ Use: "tsch",
+ Short: "Execute with Windows Task Scheduler (MS-TSCH)",
+ Long: `Description:
The tsch module makes use of the Windows Task Scheduler service (MS-TSCH) to
spawn processes on the remote target.`,
- GroupID: "module",
- Args: cobra.NoArgs,
- }
-
- tschDemandCmd = &cobra.Command{
- Use: "demand [target]",
- Short: "Register a remote scheduled task and demand immediate start",
- Long: `Description:
+ GroupID: "module",
+ 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.`,
- Args: args(
- argsRpcClient("cifs"),
- argsOutput("smb"),
- argsTask,
- ),
-
- Run: func(*cobra.Command, []string) {
- tschDemand.IO = exec
- tschDemand.Client = &rpcClient
- tschDemand.TaskPath = tschTask
-
- ctx := log.With().
- Str("module", "tsch").
- Str("method", "demand").
- Logger().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"),
+ argsTask,
+ ),
+
+ Run: func(*cobra.Command, []string) {
+ tschDemand.IO = exec
+ tschDemand.Client = &rpcClient
+ tschDemand.TaskPath = tschTask
+
+ ctx := log.With().
+ Str("module", "tsch").
+ Str("method", "demand").
+ Logger().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
Setting.`,
- Args: args(
- argsRpcClient("cifs"),
- argsOutput("smb"),
- argsTask,
- ),
-
- Run: func(*cobra.Command, []string) {
- tschCreate.Tsch.Client = &rpcClient
- tschCreate.IO = exec
- tschCreate.TaskPath = tschTask
-
- ctx := log.With().
- Str("module", "tsch").
- Str("method", "create").
- Logger().WithContext(gssapi.NewSecurityContext(context.TODO()))
-
- if err := goexec.ExecuteCleanMethod(ctx, &tschCreate, &exec); err != nil {
- log.Fatal().Err(err).Msg("Operation failed")
- }
- },
- }
- tschChangeCmd = &cobra.Command{
- Use: "change [target]",
- Short: "Modify an existing task to spawn an arbitrary process",
- Long: `Description:
+ Args: args(
+ argsRpcClient("cifs"),
+ argsOutput("smb"),
+ argsTask,
+ ),
+
+ Run: func(*cobra.Command, []string) {
+ tschCreate.Client = &rpcClient
+ tschCreate.IO = exec
+ tschCreate.TaskPath = tschTask
+
+ ctx := log.With().
+ Str("module", "tsch").
+ Str("method", "create").
+ Logger().WithContext(gssapi.NewSecurityContext(context.TODO()))
+
+ if err := goexec.ExecuteCleanMethod(ctx, &tschCreate, &exec); err != nil {
+ log.Fatal().Err(err).Msg("Operation failed")
+ }
+ },
+ }
+ tschChangeCmd = &cobra.Command{
+ Use: "change [target]",
+ Short: "Modify an existing task to spawn an arbitrary process",
+ Long: `Description:
The change method calls SchRpcRetrieveTask to fetch the definition of an existing
task (-t), then modifies the task definition to spawn a process`,
- Args: args(
- argsRpcClient("cifs"),
- argsOutput("smb"),
-
- func(*cobra.Command, []string) error {
- return tschexec.ValidateTaskPath(tschChange.TaskPath)
- },
- ),
-
- Run: func(*cobra.Command, []string) {
- tschChange.Tsch.Client = &rpcClient
- tschChange.IO = exec
-
- ctx := log.With().
- Str("module", "tsch").
- Str("method", "change").
- Logger().WithContext(gssapi.NewSecurityContext(context.TODO()))
-
- if err := goexec.ExecuteCleanMethod(ctx, &tschChange, &exec); err != nil {
- log.Fatal().Err(err).Msg("Operation failed")
- }
- },
- }
+ Args: args(
+ argsRpcClient("cifs"),
+ argsOutput("smb"),
+
+ func(*cobra.Command, []string) error {
+ return tschexec.ValidateTaskPath(tschChange.TaskPath)
+ },
+ ),
+
+ Run: func(*cobra.Command, []string) {
+ tschChange.Client = &rpcClient
+ tschChange.IO = exec
+
+ ctx := log.With().
+ Str("module", "tsch").
+ Str("method", "change").
+ Logger().WithContext(gssapi.NewSecurityContext(context.TODO()))
+
+ if err := goexec.ExecuteCleanMethod(ctx, &tschChange, &exec); err != nil {
+ log.Fatal().Err(err).Msg("Operation failed")
+ }
+ },
+ }
)