aboutsummaryrefslogtreecommitdiff
path: root/cmd/scmr.go
blob: 477773d3d0280802c1f16f06faea9c0d6d1a3670 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package cmd

import (
	"errors"
	"fmt"
	"github.com/bryanmcnulty/adauth"
	"github.com/spf13/cobra"

	"github.com/FalconOpsLLC/goexec/pkg/exec"
	scmrexec "github.com/FalconOpsLLC/goexec/pkg/exec/scmr"
	"github.com/FalconOpsLLC/goexec/pkg/windows"
)

func scmrCmdInit() {
	scmrCmd.PersistentFlags().StringVarP(&executablePath, "executable-path", "e", "", "Full path to remote Windows executable")
	scmrCmd.PersistentFlags().StringVarP(&executableArgs, "args", "a", "", "Arguments to pass to executable")
	scmrCmd.PersistentFlags().StringVarP(&scmrName, "service", "s", "", "Name of service to create or modify")
	scmrCmd.PersistentFlags().StringVarP(&scmrDisplayName, "display-name", "n", "", "Service display name")

	scmrCmd.MarkPersistentFlagRequired("executable-path")
	scmrCmd.MarkPersistentFlagRequired("service")

	scmrCmd.AddCommand(scmrChangeCmd)
	scmrChangeCmdInit()
	scmrCmd.AddCommand(scmrCreateCmd)
	scmrCreateCmdInit()
}

func scmrChangeCmdInit() {
	scmrChangeCmd.Flags().BoolVar(&scmrNoStart, "no-start", false, "Don't start service")
}

func scmrCreateCmdInit() {
	scmrChangeCmd.Flags().StringVarP(&scmrDisplayName, "display-name", "n", "", "Display name of service to create")
	scmrCreateCmd.Flags().BoolVar(&scmrNoDelete, "no-delete", false, "Don't delete service after execution")
}

var (
	// scmr arguments
	scmrName        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

	scmrCmd = &cobra.Command{
		Use:   "scmr",
		Short: "Establish execution via SCMR",
		Args: func(cmd *cobra.Command, args []string) error {
			if len(args) != 1 {
				return errors.New(`command not set. Choose from (change, create)`)
			}
			return nil
		},
		Run: func(cmd *cobra.Command, args []string) {
			if err := cmd.Help(); err != nil {
				panic(err)
			}
		},
	}
	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) {
			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")
			}
			executor := scmrexec.Executor{}
			execCfg := &exec.ExecutionConfig{
				ExecutablePath:  executablePath,
				ExecutableArgs:  executableArgs,
				ExecutionMethod: scmrexec.MethodCreate,

				ExecutionMethodConfig: scmrexec.MethodCreateConfig{
					NoDelete:    scmrNoDelete,
					ServiceName: scmrName,
					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")
			}
			return nil
		},
	}
	scmrChangeCmd = &cobra.Command{
		Use:   "change [target]",
		Short: "Change an existing Windows service to gain execution",
		Args:  scmrArgs,
		Run: func(cmd *cobra.Command, args []string) {
			executor := scmrexec.Executor{}
			execCfg := &exec.ExecutionConfig{
				ExecutablePath:  executablePath,
				ExecutableArgs:  executableArgs,
				ExecutionMethod: scmrexec.MethodModify,

				ExecutionMethodConfig: scmrexec.MethodModifyConfig{
					NoStart:     scmrNoStart,
					ServiceName: scmrName,
				},
			}
			if err := executor.Exec(log.WithContext(ctx), creds, target, execCfg); err != nil {
				log.Fatal().Err(err).Msg("SCMR execution failed")
			}
		},
	}
)