aboutsummaryrefslogtreecommitdiff
path: root/cmd/scmr.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/scmr.go')
-rw-r--r--cmd/scmr.go243
1 files changed, 125 insertions, 118 deletions
diff --git a/cmd/scmr.go b/cmd/scmr.go
index 11e1379..08e23d7 100644
--- a/cmd/scmr.go
+++ b/cmd/scmr.go
@@ -1,14 +1,12 @@
package cmd
import (
- "github.com/FalconOpsLLC/goexec/internal/exec"
+ "context"
"github.com/FalconOpsLLC/goexec/internal/util"
- "github.com/FalconOpsLLC/goexec/internal/windows"
- "github.com/RedTeamPentesting/adauth"
- "github.com/oiweiwei/go-msrpc/dcerpc"
+ "github.com/oiweiwei/go-msrpc/ssp/gssapi"
"github.com/spf13/cobra"
- scmrexec "github.com/FalconOpsLLC/goexec/internal/exec/scmr"
+ scmrexec "github.com/FalconOpsLLC/goexec/pkg/goexec/scmr"
)
func scmrCmdInit() {
@@ -22,53 +20,55 @@ func scmrCmdInit() {
}
func scmrCreateCmdInit() {
- scmrCreateCmd.Flags().StringVarP(&scmrDisplayName, "display-name", "n", "", "Display name of service to create")
- 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")
- scmrCreateCmd.Flags().BoolVar(&scmrNoStart, "no-start", false, "Don't start service")
- scmrCreateCmd.Flags().StringVarP(&executablePath, "executable-path", "f", "", "Full path to a remote Windows executable file")
- scmrCreateCmd.Flags().StringVarP(&executableArgs, "args", "a", "", "Arguments to pass to the executable")
- scmrCreateCmd.Flags().BoolVarP(&scmrOutput, "output", "O", false, "Fetch program output")
+ scmrCreateCmd.Flags().StringVarP(&scmrCreate.DisplayName, "display-name", "n", "", "Display name of service to create")
+ scmrCreateCmd.Flags().StringVarP(&scmrCreate.ServiceName, "service-name", "s", "", "Name of service to create")
+ scmrCreateCmd.Flags().BoolVar(&scmrCreate.NoDelete, "no-delete", false, "Don't delete service after execution")
+ scmrCreateCmd.Flags().BoolVar(&scmrCreate.NoStart, "no-start", false, "Don't start service")
+
+ scmrCreateCmd.Flags().StringVarP(&exec.Input.ExecutablePath, "executable-path", "f", "", "Full path to a remote Windows executable")
+ scmrCreateCmd.Flags().StringVarP(&exec.Input.Arguments, "args", "a", "", "Arguments to pass to the executable")
+
+ scmrCreateCmd.MarkFlagsMutuallyExclusive("no-delete", "no-start")
+
if err := scmrCreateCmd.MarkFlagRequired("executable-path"); err != nil {
panic(err)
}
}
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")
- scmrChangeCmd.Flags().StringVarP(&executablePath, "executable-path", "f", "", "Full path to remote Windows executable")
- scmrChangeCmd.Flags().StringVarP(&executableArgs, "args", "a", "", "Arguments to pass to executable")
+ scmrChangeCmd.Flags().BoolVar(&scmrChange.NoStart, "no-start", false, "Don't start service")
+ scmrChangeCmd.Flags().StringVarP(&scmrChange.ServiceName, "service-name", "s", "", "Name of service to modify")
+
+ scmrChangeCmd.Flags().StringVarP(&exec.Input.ExecutablePath, "executable-path", "f", "", "Full path to remote Windows executable")
+ scmrChangeCmd.Flags().StringVarP(&exec.Input.Arguments, "args", "a", "", "Arguments to pass to executable")
+
if err := scmrChangeCmd.MarkFlagRequired("service-name"); err != nil {
panic(err)
}
+ if err := scmrCreateCmd.MarkFlagRequired("executable-path"); err != nil {
+ panic(err)
+ }
}
func scmrDeleteCmdInit() {
- scmrDeleteCmd.Flags().StringArrayVarP(&scmrServiceNames, "service-name", "s", scmrServiceNames, "Name of service(s) to delete")
+ scmrDeleteCmd.Flags().StringVarP(&scmrDelete.ServiceName, "service-name", "s", scmrDelete.ServiceName, "Name of service to delete")
+
if err := scmrDeleteCmd.MarkFlagRequired("service-name"); err != nil {
panic(err)
}
}
var (
- // scmr arguments
- scmrServiceName string
- scmrServiceNames []string
- scmrDisplayName string
- scmrNoDelete bool
- scmrNoStart bool
- scmrOutput bool
-
- creds *adauth.Credential
- target *adauth.Target
+ scmrCreate scmrexec.ScmrCreate
+ scmrChange scmrexec.ScmrChange
+ scmrDelete scmrexec.ScmrDelete
scmrCmd = &cobra.Command{
Use: "scmr",
Short: "Establish execution via SCMR",
Args: cobra.NoArgs,
}
+
scmrCreateCmd = &cobra.Command{
Use: "create [target]",
Short: "Create & run a new Windows service to gain execution",
@@ -79,138 +79,145 @@ var (
References:
https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-scmr/6a8ca926-9477-4dd4-b766-692fab07227e
`,
- Args: needs(needsTarget("host"), needsRpcTarget("host")),
+ Args: argsRpcClient("cifs"),
+
Run: func(cmd *cobra.Command, args []string) {
+ var err error
+
+ ctx := gssapi.NewSecurityContext(context.Background())
- if scmrServiceName == "" {
- log.Warn().Msg("No service name was specified, using random string")
- scmrServiceName = util.RandomString()
+ ctx = log.With().
+ Str("module", "scmr").
+ Str("method", "create").
+ Logger().
+ WithContext(ctx)
+
+ if scmrCreate.ServiceName == "" {
+ log.Warn().Msg("No service name was provided. Using a random string")
+ scmrCreate.ServiceName = util.RandomString()
}
- if scmrNoDelete {
+
+ if scmrCreate.NoDelete {
log.Warn().Msg("Service will not be deleted after execution")
}
- if scmrDisplayName == "" {
+
+ if scmrCreate.DisplayName == "" {
log.Debug().Msg("No display name specified, using service name as display name")
- scmrDisplayName = scmrServiceName
+ scmrCreate.DisplayName = scmrCreate.ServiceName
}
- executor := scmrexec.Module{}
- cleanCfg := &exec.CleanupConfig{
- CleanupMethod: scmrexec.CleanupMethodDelete,
- CleanupMethodConfig: scmrexec.CleanupMethodDeleteConfig{},
- }
- connCfg := &exec.ConnectionConfig{
- ConnectionMethod: exec.ConnectionMethodDCE,
- ConnectionMethodConfig: dceConfig,
- }
- execCfg := &exec.ExecutionConfig{
- ExecutablePath: executablePath,
- ExecutableArgs: executableArgs,
- ReturnOutput: scmrOutput,
- ExecutionMethod: scmrexec.MethodCreate,
-
- ExecutionMethodConfig: scmrexec.MethodCreateConfig{
- NoDelete: scmrNoDelete,
- ServiceName: util.RandomStringIfBlank(scmrServiceName),
- DisplayName: scmrDisplayName,
- ServiceType: windows.SERVICE_WIN32_OWN_PROCESS,
- StartType: windows.SERVICE_DEMAND_START,
- },
- }
- ctx = log.With().
- Str("module", "scmr").
- Str("method", "create").
- Logger().WithContext(ctx)
-
- if err := executor.Connect(ctx, creds, target, connCfg); err != nil {
+ if err = rpcClient.Connect(ctx); 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")
- }
- }()
+
+ defer func() {
+ closeErr := rpcClient.Close(ctx)
+ if closeErr != nil {
+ log.Error().Err(closeErr).Msg("Failed to close connection")
+ }
+ }()
+
+ defer func() {
+ cleanErr := scmrCreate.Clean(ctx)
+ if cleanErr != nil {
+ log.Warn().Err(cleanErr).Msg("Clean operation failed")
+ }
+ }()
+
+ if err = scmrCreate.Init(ctx, &rpcClient); err != nil {
+ log.Error().Err(err).Msg("Module initialization failed")
+ returnCode = 2
+ return
}
- if err := executor.Exec(ctx, execCfg); err != nil {
+
+ if err = scmrCreate.Execute(ctx, exec.Input); err != nil {
log.Error().Err(err).Msg("Execution failed")
+ returnCode = 4
}
},
}
+
scmrChangeCmd = &cobra.Command{
Use: "change [target]",
Short: "Change an existing Windows service to gain execution",
- Args: needs(needsTarget("host"), needsRpcTarget("host")),
+ Args: argsRpcClient("cifs"),
Run: func(cmd *cobra.Command, args []string) {
+ var err error
+
+ ctx := gssapi.NewSecurityContext(context.Background())
- executor := scmrexec.Module{}
- cleanCfg := &exec.CleanupConfig{
- CleanupMethod: scmrexec.CleanupMethodRevert,
- CleanupMethodConfig: scmrexec.CleanupMethodRevertConfig{},
- }
- connCfg := &exec.ConnectionConfig{
- ConnectionMethod: exec.ConnectionMethodDCE,
- ConnectionMethodConfig: dceConfig,
- }
- execCfg := &exec.ExecutionConfig{
- ExecutablePath: executablePath,
- ExecutableArgs: executableArgs,
- ExecutionMethod: scmrexec.MethodChange,
-
- ExecutionMethodConfig: scmrexec.MethodChangeConfig{
- NoStart: scmrNoStart,
- ServiceName: scmrServiceName,
- },
- }
ctx = log.With().
Str("module", "scmr").
Str("method", "change").
- Logger().WithContext(ctx)
+ Logger().
+ WithContext(ctx)
- if err := executor.Connect(ctx, creds, target, connCfg); err != nil {
+ if err = rpcClient.Connect(ctx); 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")
- }
- }()
+
+ defer func() {
+ closeErr := rpcClient.Close(ctx)
+ if closeErr != nil {
+ log.Error().Err(closeErr).Msg("Failed to close connection")
+ }
+ }()
+
+ defer func() {
+ cleanErr := scmrChange.Clean(ctx)
+ if cleanErr != nil {
+ log.Warn().Err(cleanErr).Msg("Clean operation failed")
+ }
+ }()
+
+ if err = scmrChange.Init(ctx, &rpcClient); err != nil {
+ log.Error().Err(err).Msg("Module initialization failed")
+ returnCode = 2
+ return
}
- if err := executor.Exec(ctx, execCfg); err != nil {
+
+ if err = scmrChange.Execute(ctx, exec.Input); err != nil {
log.Error().Err(err).Msg("Execution failed")
+ returnCode = 4
}
},
}
scmrDeleteCmd = &cobra.Command{
Use: "delete [target]",
Short: "Delete an existing Windows service",
- Long: `Description:
-TODO
-`,
- Args: needs(needsTarget("host"), needsRpcTarget("host")),
+ Long: `TODO`,
+
+ Args: argsRpcClient("cifs"),
Run: func(cmd *cobra.Command, args []string) {
- dceConfig.DceOptions = append(dceConfig.DceOptions, dcerpc.WithInsecure())
+ var err error
+
+ ctx := gssapi.NewSecurityContext(context.Background())
- executor := scmrexec.Module{}
- cleanCfg := &exec.CleanupConfig{
- CleanupMethod: scmrexec.CleanupMethodDelete,
- CleanupMethodConfig: scmrexec.CleanupMethodDeleteConfig{ServiceNames: scmrServiceNames},
- }
- connCfg := &exec.ConnectionConfig{
- ConnectionMethod: exec.ConnectionMethodDCE,
- ConnectionMethodConfig: dceConfig,
- }
ctx = log.With().
Str("module", "scmr").
Str("method", "delete").
- Logger().WithContext(ctx)
+ Logger().
+ WithContext(ctx)
- if err := executor.Connect(ctx, creds, target, connCfg); err != nil {
+ if err = rpcClient.Connect(ctx); err != nil {
log.Fatal().Err(err).Msg("Connection failed")
+ }
+
+ defer func() {
+ closeErr := rpcClient.Close(ctx)
+ if closeErr != nil {
+ log.Error().Err(closeErr).Msg("Failed to close connection")
+ }
+ }()
+
+ if err = scmrDelete.Init(ctx, &rpcClient); err != nil {
+ log.Error().Err(err).Msg("Module initialization failed")
+ returnCode = 2
+ }
- } else if err = executor.Cleanup(ctx, cleanCfg); err != nil {
- log.Fatal().Err(err).Msg("Delete failed")
+ if err = scmrDelete.Clean(ctx); err != nil {
+ log.Warn().Err(err).Msg("Clean failed")
+ returnCode = 4
}
},
}