diff options
author | Bryan McNulty <bryanmcnulty@protonmail.com> | 2025-03-09 12:26:05 -0500 |
---|---|---|
committer | Bryan McNulty <bryanmcnulty@protonmail.com> | 2025-03-09 12:26:05 -0500 |
commit | c6460b19bd834875b00f199390e6121d5bdfba7e (patch) | |
tree | 11cf6c9c3ddbdf694547cea50c2375d2b6d0df7c /cmd/scmr.go | |
parent | 8099a1d45007ba86f353647bf2a3f09d0cfc73a7 (diff) | |
download | goexec-c6460b19bd834875b00f199390e6121d5bdfba7e.tar.gz goexec-c6460b19bd834875b00f199390e6121d5bdfba7e.zip |
massively improved SCMR module + new DCE client
Diffstat (limited to 'cmd/scmr.go')
-rw-r--r-- | cmd/scmr.go | 106 |
1 files changed, 75 insertions, 31 deletions
diff --git a/cmd/scmr.go b/cmd/scmr.go index f2f0d51..7772fc4 100644 --- a/cmd/scmr.go +++ b/cmd/scmr.go @@ -1,8 +1,8 @@ package cmd import ( - "fmt" "github.com/FalconOpsLLC/goexec/internal/exec" + "github.com/FalconOpsLLC/goexec/internal/util" "github.com/FalconOpsLLC/goexec/internal/windows" "github.com/RedTeamPentesting/adauth" "github.com/spf13/cobra" @@ -14,11 +14,11 @@ func scmrCmdInit() { registerRpcFlags(scmrCmd) scmrCmd.PersistentFlags().StringVarP(&executablePath, "executable-path", "f", "", "Full path to remote Windows executable") scmrCmd.PersistentFlags().StringVarP(&executableArgs, "args", "a", "", "Arguments to pass to executable") - scmrCmd.PersistentFlags().StringVarP(&scmrName, "service-name", "s", "", "Name of service to create or modify") - - scmrCmd.MarkPersistentFlagRequired("executable-path") - scmrCmd.MarkPersistentFlagRequired("service-name") + scmrCmd.PersistentFlags().StringVarP(&scmrServiceName, "service-name", "s", "", "Name of service to create or modify") + if err := scmrCmd.MarkPersistentFlagRequired("executable-path"); err != nil { + panic(err) + } scmrCmd.AddCommand(scmrChangeCmd) scmrCreateCmdInit() scmrCmd.AddCommand(scmrCreateCmd) @@ -28,30 +28,24 @@ func scmrCmdInit() { func scmrChangeCmdInit() { scmrChangeCmd.Flags().StringVarP(&scmrDisplayName, "display-name", "n", "", "Display name of service to create") scmrChangeCmd.Flags().BoolVar(&scmrNoStart, "no-start", false, "Don't start service") + scmrChangeCmd.Flags().StringVarP(&scmrServiceName, "service-name", "s", "", "Name of service to modify") + if err := scmrChangeCmd.MarkFlagRequired("service-name"); err != nil { + panic(err) + } } func scmrCreateCmdInit() { + scmrCreateCmd.Flags().StringVarP(&scmrServiceName, "service-name", "s", "", "Name of service to create") scmrCreateCmd.Flags().BoolVar(&scmrNoDelete, "no-delete", false, "Don't delete service after execution") } var ( // scmr arguments - scmrName string + scmrServiceName string scmrDisplayName string scmrNoDelete bool scmrNoStart bool - scmrArgs = func(cmd *cobra.Command, args []string) (err error) { - if len(args) != 1 { - return fmt.Errorf("expected exactly 1 positional argument, got %d", len(args)) - } - if creds, target, err = authOpts.WithTarget(ctx, "cifs", args[0]); err != nil { - return fmt.Errorf("failed to parse target: %w", err) - } - log.Debug().Str("target", args[0]).Msg("Resolved target") - return nil - } - creds *adauth.Credential target *adauth.Target @@ -63,16 +57,29 @@ var ( scmrCreateCmd = &cobra.Command{ Use: "create [target]", Short: "Create & run a new Windows service to gain execution", - Args: scmrArgs, - RunE: func(cmd *cobra.Command, args []string) (err error) { + Args: needsRpcTarget("cifs"), + Run: func(cmd *cobra.Command, args []string) { + + if scmrServiceName == "" { + log.Warn().Msg("No service name was specified, using random string") + scmrServiceName = util.RandomString() + } if scmrNoDelete { log.Warn().Msg("Service will not be deleted after execution") } if scmrDisplayName == "" { - scmrDisplayName = scmrName - log.Warn().Msg("No display name specified, using service name as display name") + log.Debug().Msg("No display name specified, using service name as display name") + scmrDisplayName = scmrServiceName } + executor := scmrexec.Module{} + cleanCfg := &exec.CleanupConfig{ + CleanupMethod: scmrexec.CleanupMethodDelete, + } + connCfg := &exec.ConnectionConfig{ + ConnectionMethod: exec.ConnectionMethodDCE, + ConnectionMethodConfig: dceConfig, + } execCfg := &exec.ExecutionConfig{ ExecutablePath: executablePath, ExecutableArgs: executableArgs, @@ -80,36 +87,73 @@ var ( ExecutionMethodConfig: scmrexec.MethodCreateConfig{ NoDelete: scmrNoDelete, - ServiceName: scmrName, + ServiceName: util.RandomStringIfBlank(scmrServiceName), DisplayName: scmrDisplayName, ServiceType: windows.SERVICE_WIN32_OWN_PROCESS, StartType: windows.SERVICE_DEMAND_START, }, } - if err := executor.Exec(log.WithContext(ctx), creds, target, execCfg); err != nil { - log.Fatal().Err(err).Msg("SCMR execution failed") + ctx = log.With(). + Str("module", "scmr"). + Str("method", "create"). + Logger().WithContext(ctx) + + if err := executor.Connect(ctx, creds, target, connCfg); err != nil { + log.Fatal().Err(err).Msg("Connection failed") + } + if !scmrNoDelete { + defer func() { + if err := executor.Cleanup(ctx, cleanCfg); err != nil { + log.Error().Err(err).Msg("Cleanup failed") + } + }() + } + if err := executor.Exec(ctx, execCfg); err != nil { + log.Error().Err(err).Msg("Execution failed") } - return nil }, } scmrChangeCmd = &cobra.Command{ Use: "change [target]", Short: "Change an existing Windows service to gain execution", - Args: scmrArgs, + Args: needsRpcTarget("cifs"), Run: func(cmd *cobra.Command, args []string) { + executor := scmrexec.Module{} + cleanCfg := &exec.CleanupConfig{ + CleanupMethod: scmrexec.CleanupMethodRevert, + } + connCfg := &exec.ConnectionConfig{ + ConnectionMethod: exec.ConnectionMethodDCE, + ConnectionMethodConfig: dceConfig, + } execCfg := &exec.ExecutionConfig{ ExecutablePath: executablePath, ExecutableArgs: executableArgs, - ExecutionMethod: scmrexec.MethodModify, + ExecutionMethod: scmrexec.MethodChange, - ExecutionMethodConfig: scmrexec.MethodModifyConfig{ + ExecutionMethodConfig: scmrexec.MethodChangeConfig{ NoStart: scmrNoStart, - ServiceName: scmrName, + ServiceName: scmrServiceName, }, } - if err := executor.Exec(log.WithContext(ctx), creds, target, execCfg); err != nil { - log.Fatal().Err(err).Msg("SCMR execution failed") + log = log.With(). + Str("module", "scmr"). + Str("method", "change"). + Logger() + + if err := executor.Connect(log.WithContext(ctx), creds, target, connCfg); err != nil { + log.Fatal().Err(err).Msg("Connection failed") + } + if !scmrNoDelete { + defer func() { + if err := executor.Cleanup(log.WithContext(ctx), cleanCfg); err != nil { + log.Error().Err(err).Msg("Cleanup failed") + } + }() + } + if err := executor.Exec(log.WithContext(ctx), execCfg); err != nil { + log.Error().Err(err).Msg("Execution failed") } }, } |