diff options
Diffstat (limited to 'cmd/scmr.go')
-rw-r--r-- | cmd/scmr.go | 391 |
1 files changed, 198 insertions, 193 deletions
diff --git a/cmd/scmr.go b/cmd/scmr.go index 4edcf22..23d9272 100644 --- a/cmd/scmr.go +++ b/cmd/scmr.go @@ -1,217 +1,222 @@ package cmd import ( - "context" - "github.com/FalconOpsLLC/goexec/internal/util" - "github.com/FalconOpsLLC/goexec/pkg/goexec" - "github.com/oiweiwei/go-msrpc/ssp/gssapi" - "github.com/spf13/cobra" + "context" + "github.com/FalconOpsLLC/goexec/internal/util" + "github.com/FalconOpsLLC/goexec/pkg/goexec" + "github.com/oiweiwei/go-msrpc/ssp/gssapi" + "github.com/spf13/cobra" - scmrexec "github.com/FalconOpsLLC/goexec/pkg/goexec/scmr" + scmrexec "github.com/FalconOpsLLC/goexec/pkg/goexec/scmr" ) func scmrCmdInit() { - cmdFlags[scmrCmd] = []*flagSet{ - defaultAuthFlags, - defaultLogFlags, - defaultNetRpcFlags, - } - scmrCreateCmdInit() - scmrChangeCmdInit() - scmrDeleteCmdInit() - - scmrCmd.PersistentFlags().AddFlagSet(defaultAuthFlags.Flags) - scmrCmd.PersistentFlags().AddFlagSet(defaultLogFlags.Flags) - scmrCmd.PersistentFlags().AddFlagSet(defaultNetRpcFlags.Flags) - scmrCmd.AddCommand(scmrCreateCmd, scmrChangeCmd, scmrDeleteCmd) + cmdFlags[scmrCmd] = []*flagSet{ + defaultAuthFlags, + defaultLogFlags, + defaultNetRpcFlags, + } + scmrCreateCmdInit() + scmrChangeCmdInit() + scmrDeleteCmdInit() + + scmrCmd.PersistentFlags().AddFlagSet(defaultAuthFlags.Flags) + scmrCmd.PersistentFlags().AddFlagSet(defaultLogFlags.Flags) + scmrCmd.PersistentFlags().AddFlagSet(defaultNetRpcFlags.Flags) + scmrCmd.AddCommand(scmrCreateCmd, scmrChangeCmd, scmrDeleteCmd) } func scmrCreateCmdInit() { - scmrCreateFlags := newFlagSet("Service") - - scmrCreateFlags.Flags.StringVarP(&scmrCreate.DisplayName, "display-name", "n", "", "Display name of service to create") - scmrCreateFlags.Flags.StringVarP(&scmrCreate.ServiceName, "service", "s", "", "Name of service to create") - scmrCreateFlags.Flags.BoolVar(&scmrCreate.NoDelete, "no-delete", false, "Don't delete service after execution") - scmrCreateFlags.Flags.BoolVar(&scmrCreate.NoStart, "no-start", false, "Don't start service") - - scmrCreateExecFlags := newFlagSet("Execution") - - // TODO: SCMR output - //registerExecutionOutputFlags(scmrCreateExecFlags.Flags) - - scmrCreateExecFlags.Flags.StringVarP(&exec.Input.ExecutablePath, "executable-path", "f", "", "Full path to a remote Windows executable") - scmrCreateExecFlags.Flags.StringVarP(&exec.Input.Arguments, "args", "a", "", "Arguments to pass to the executable") - - scmrCreateCmd.Flags().AddFlagSet(scmrCreateFlags.Flags) - scmrCreateCmd.Flags().AddFlagSet(scmrCreateExecFlags.Flags) - - cmdFlags[scmrCreateCmd] = []*flagSet{ - scmrCreateExecFlags, - scmrCreateFlags, - defaultAuthFlags, - defaultLogFlags, - defaultNetRpcFlags, - } - - // Constraints - { - //scmrCreateCmd.MarkFlagsMutuallyExclusive("no-delete", "no-start") - if err := scmrCreateCmd.MarkFlagRequired("executable-path"); err != nil { - panic(err) - } - } + scmrCreateFlags := newFlagSet("Service") + + scmrCreateFlags.Flags.StringVarP(&scmrCreate.DisplayName, "display-name", "n", "", "Display name of service to create") + scmrCreateFlags.Flags.StringVarP(&scmrCreate.ServiceName, "service", "s", "", "Name of service to create") + scmrCreateFlags.Flags.BoolVar(&scmrCreate.NoDelete, "no-delete", false, "Don't delete service after execution") + scmrCreateFlags.Flags.BoolVar(&scmrCreate.NoStart, "no-start", false, "Don't start service") + + scmrCreateExecFlags := newFlagSet("Execution") + + // TODO: SCMR output + //registerExecutionOutputFlags(scmrCreateExecFlags.Flags) + + scmrCreateExecFlags.Flags.StringVarP(&exec.Input.ExecutablePath, "executable-path", "f", "", "Full path to a remote Windows executable") + scmrCreateExecFlags.Flags.StringVarP(&exec.Input.Arguments, "args", "a", "", "Arguments to pass to the executable") + + scmrCreateCmd.Flags().AddFlagSet(scmrCreateFlags.Flags) + scmrCreateCmd.Flags().AddFlagSet(scmrCreateExecFlags.Flags) + + cmdFlags[scmrCreateCmd] = []*flagSet{ + scmrCreateExecFlags, + scmrCreateFlags, + defaultAuthFlags, + defaultLogFlags, + defaultNetRpcFlags, + } + + // Constraints + { + //scmrCreateCmd.MarkFlagsMutuallyExclusive("no-delete", "no-start") + if err := scmrCreateCmd.MarkFlagRequired("executable-path"); err != nil { + panic(err) + } + } } func scmrChangeCmdInit() { - scmrChangeFlags := newFlagSet("Service Control") - - scmrChangeFlags.Flags.StringVarP(&scmrChange.ServiceName, "service-name", "s", "", "Name of service to modify") - scmrChangeFlags.Flags.BoolVar(&scmrChange.NoStart, "no-start", false, "Don't start service") - - scmrChangeExecFlags := newFlagSet("Execution") - - scmrChangeExecFlags.Flags.StringVarP(&exec.Input.ExecutablePath, "executable-path", "f", "", "Full path to remote Windows executable") - scmrChangeExecFlags.Flags.StringVarP(&exec.Input.Arguments, "args", "a", "", "Arguments to pass to executable") - - // TODO: SCMR output - //registerExecutionOutputFlags(scmrChangeExecFlags.Flags) - //registerStageFlags(scmrChangeExecFlags.Flags) - - cmdFlags[scmrChangeCmd] = []*flagSet{ - scmrChangeFlags, - scmrChangeExecFlags, - defaultAuthFlags, - defaultLogFlags, - defaultNetRpcFlags, - } - - scmrChangeCmd.Flags().AddFlagSet(scmrChangeFlags.Flags) - scmrChangeCmd.Flags().AddFlagSet(scmrChangeExecFlags.Flags) - - // Constraints - { - if err := scmrChangeCmd.MarkFlagRequired("service-name"); err != nil { - panic(err) - } - if err := scmrCreateCmd.MarkFlagRequired("executable-path"); err != nil { - panic(err) - } - } + scmrChangeFlags := newFlagSet("Service Control") + + scmrChangeFlags.Flags.StringVarP(&scmrChange.ServiceName, "service-name", "s", "", "Name of service to modify") + scmrChangeFlags.Flags.BoolVar(&scmrChange.NoStart, "no-start", false, "Don't start service") + + scmrChangeExecFlags := newFlagSet("Execution") + + scmrChangeExecFlags.Flags.StringVarP(&exec.Input.ExecutablePath, "executable-path", "f", "", "Full path to remote Windows executable") + scmrChangeExecFlags.Flags.StringVarP(&exec.Input.Arguments, "args", "a", "", "Arguments to pass to executable") + + // TODO: SCMR output + //registerExecutionOutputFlags(scmrChangeExecFlags.Flags) + //registerStageFlags(scmrChangeExecFlags.Flags) + + cmdFlags[scmrChangeCmd] = []*flagSet{ + scmrChangeFlags, + scmrChangeExecFlags, + defaultAuthFlags, + defaultLogFlags, + defaultNetRpcFlags, + } + + scmrChangeCmd.Flags().AddFlagSet(scmrChangeFlags.Flags) + scmrChangeCmd.Flags().AddFlagSet(scmrChangeExecFlags.Flags) + + // Constraints + { + if err := scmrChangeCmd.MarkFlagRequired("service-name"); err != nil { + panic(err) + } + if err := scmrCreateCmd.MarkFlagRequired("executable-path"); err != nil { + panic(err) + } + } } func scmrDeleteCmdInit() { - scmrDeleteFlags := newFlagSet("Service Control") - scmrDeleteFlags.Flags.StringVarP(&scmrDelete.ServiceName, "service-name", "s", scmrDelete.ServiceName, "Name of service to delete") + scmrDeleteFlags := newFlagSet("Service Control") + scmrDeleteFlags.Flags.StringVarP(&scmrDelete.ServiceName, "service-name", "s", scmrDelete.ServiceName, "Name of service to delete") - cmdFlags[scmrDeleteCmd] = []*flagSet{ - scmrDeleteFlags, - defaultAuthFlags, - defaultLogFlags, - defaultNetRpcFlags, - } + cmdFlags[scmrDeleteCmd] = []*flagSet{ + scmrDeleteFlags, + defaultAuthFlags, + defaultLogFlags, + defaultNetRpcFlags, + } - scmrDeleteCmd.Flags().AddFlagSet(scmrDeleteFlags.Flags) + scmrDeleteCmd.Flags().AddFlagSet(scmrDeleteFlags.Flags) - if err := scmrDeleteCmd.MarkFlagRequired("service-name"); err != nil { - panic(err) - } + if err := scmrDeleteCmd.MarkFlagRequired("service-name"); err != nil { + panic(err) + } } var ( - scmrCreate = scmrexec.ScmrCreate{} - scmrChange = scmrexec.ScmrChange{} - scmrDelete = scmrexec.ScmrDelete{} - - scmrCmd = &cobra.Command{ - Use: "scmr", - Short: "Execute with Service Control Manager Remote (MS-SCMR)", - GroupID: "module", - Args: cobra.NoArgs, - } - - scmrCreateCmd = &cobra.Command{ - Use: "create [target]", - Short: "Spawn a remote process by creating & running a Windows service", - Long: `Description: + scmrCreate = scmrexec.ScmrCreate{} + scmrChange = scmrexec.ScmrChange{} + scmrDelete = scmrexec.ScmrDelete{} + + scmrCmd = &cobra.Command{ + Use: "scmr", + Short: "Execute with Service Control Manager Remote (MS-SCMR)", + Long: `Description: + The SCMR module works a lot like Impacket's smbexec.py, but it provides additional RPC transports + to evade network monitoring or firewall rules, and some minor OPSEC improvements overall.`, + GroupID: "module", + Args: cobra.NoArgs, + } + + scmrCreateCmd = &cobra.Command{ + Use: "create [target]", + Short: "Spawn a remote process by creating & running a Windows service", + Long: `Description: The create method calls RCreateServiceW to create a new Windows service on the - remote target with the provided executable & arguments as the lpBinaryPathName - -References: - - https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-scmr/6a8ca926-9477-4dd4-b766-692fab07227e -`, - Args: args( - argsRpcClient("cifs"), - argsSmbClient(), - ), - - Run: func(cmd *cobra.Command, args []string) { - scmrCreate.Client = &rpcClient - scmrCreate.IO = exec - - log = log.With(). - Str("module", "scmr"). - Str("method", "create"). - Logger() - - // Warnings - { - if scmrCreate.ServiceName == "" { - log.Warn().Msg("No service name was provided. Using a random string") - scmrCreate.ServiceName = util.RandomString() - } - if scmrCreate.NoDelete { - log.Warn().Msg("Service will not be deleted after execution") - } - if scmrCreate.DisplayName == "" { - log.Debug().Msg("No display name specified, using service name as display name") - scmrCreate.DisplayName = scmrCreate.ServiceName - } - } - - ctx := log.WithContext(gssapi.NewSecurityContext(context.Background())) - - if err := goexec.ExecuteCleanMethod(ctx, &scmrCreate, &exec); err != nil { - log.Fatal().Err(err).Msg("Operation failed") - } - }, - } - - scmrChangeCmd = &cobra.Command{ - Use: "change [target]", - Short: "Change an existing Windows service to spawn an arbitrary process", - Args: argsRpcClient("cifs"), - - Run: func(cmd *cobra.Command, args []string) { - scmrChange.Client = &rpcClient - scmrChange.IO = exec - - ctx := log.With(). - Str("module", "scmr"). - Str("method", "change"). - Logger().WithContext(gssapi.NewSecurityContext(context.Background())) - - if err := goexec.ExecuteCleanMethod(ctx, &scmrChange, &exec); err != nil { - log.Fatal().Err(err).Msg("Operation failed") - } - }, - } - scmrDeleteCmd = &cobra.Command{ - Use: "delete [target]", - Short: "Delete an existing Windows service", - Long: `TODO`, - - Args: argsRpcClient("cifs"), - Run: func(cmd *cobra.Command, args []string) { - scmrDelete.Client = &rpcClient - - ctx := log.With(). - Str("module", "scmr"). - Str("method", "delete"). - Logger().WithContext(gssapi.NewSecurityContext(context.Background())) - - if err := goexec.ExecuteCleanAuxiliaryMethod(ctx, &scmrDelete); err != nil { - log.Fatal().Err(err).Msg("Operation failed") - } - }, - } + remote target with the provided executable & arguments as the lpBinaryPathName`, + Args: args( + argsRpcClient("cifs"), + argsSmbClient(), + ), + + Run: func(cmd *cobra.Command, args []string) { + scmrCreate.Client = &rpcClient + scmrCreate.IO = exec + + log = log.With(). + Str("module", "scmr"). + Str("method", "create"). + Logger() + + // Warnings + { + if scmrCreate.ServiceName == "" { + log.Warn().Msg("No service name was provided. Using a random string") + scmrCreate.ServiceName = util.RandomString() + } + if scmrCreate.NoDelete { + log.Warn().Msg("Service will not be deleted after execution") + } + if scmrCreate.DisplayName == "" { + log.Debug().Msg("No display name specified, using service name as display name") + scmrCreate.DisplayName = scmrCreate.ServiceName + } + } + + ctx := log.WithContext(gssapi.NewSecurityContext(context.Background())) + + if err := goexec.ExecuteCleanMethod(ctx, &scmrCreate, &exec); err != nil { + log.Fatal().Err(err).Msg("Operation failed") + } + }, + } + + scmrChangeCmd = &cobra.Command{ + Use: "change [target]", + Short: "Change an existing Windows service to spawn an arbitrary process", + Long: `Description: + The change method executes programs by modifying existing Windows services + using the RChangeServiceConfigW method rather than calling RCreateServiceW + like scmr create. The modified service is restored to its original state + after execution`, + Args: argsRpcClient("cifs"), + + Run: func(cmd *cobra.Command, args []string) { + scmrChange.Client = &rpcClient + scmrChange.IO = exec + + ctx := log.With(). + Str("module", "scmr"). + Str("method", "change"). + Logger().WithContext(gssapi.NewSecurityContext(context.Background())) + + if err := goexec.ExecuteCleanMethod(ctx, &scmrChange, &exec); err != nil { + log.Fatal().Err(err).Msg("Operation failed") + } + }, + } + scmrDeleteCmd = &cobra.Command{ + Use: "delete [target]", + Short: "Delete an existing Windows service", + Long: `Description: + The delete method will simply delete the provided service.`, + + Args: argsRpcClient("cifs"), + Run: func(cmd *cobra.Command, args []string) { + scmrDelete.Client = &rpcClient + + ctx := log.With(). + Str("module", "scmr"). + Str("method", "delete"). + Logger().WithContext(gssapi.NewSecurityContext(context.Background())) + + if err := goexec.ExecuteCleanAuxiliaryMethod(ctx, &scmrDelete); err != nil { + log.Fatal().Err(err).Msg("Operation failed") + } + }, + } ) |