diff options
Diffstat (limited to 'cmd/root.go')
-rw-r--r-- | cmd/root.go | 172 |
1 files changed, 78 insertions, 94 deletions
diff --git a/cmd/root.go b/cmd/root.go index cbc38c0..733bb75 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,122 +1,105 @@ package cmd import ( - "context" "fmt" + "github.com/FalconOpsLLC/goexec/internal/util" + "github.com/FalconOpsLLC/goexec/pkg/goexec" + "github.com/FalconOpsLLC/goexec/pkg/goexec/dce" + "github.com/FalconOpsLLC/goexec/pkg/goexec/smb" "github.com/RedTeamPentesting/adauth" + "github.com/oiweiwei/go-msrpc/ssp" + "github.com/oiweiwei/go-msrpc/ssp/gssapi" "github.com/rs/zerolog" "github.com/spf13/cobra" - "net/url" "os" - "regexp" - "strings" ) var ( - //logFile string - log zerolog.Logger - ctx context.Context - authOpts *adauth.Options - - hostname string - proxyStr string - proxyUrl *url.URL - - // Root flags - unsafe bool // not implemented - debug bool - - // Generic flags - command string - executable string - executablePath string - executableArgs string - workingDirectory string - windowState string + debug bool + logJson bool + returnCode int + outputMethod string + outputPath string + proxy string + + log zerolog.Logger + + rpcClient dce.Client + smbClient smb.Client + + exec = goexec.ExecutionIO{ + Input: new(goexec.ExecutionInput), + Output: new(goexec.ExecutionOutput), + } + + authOpts *adauth.Options + credential *adauth.Credential + target *adauth.Target rootCmd = &cobra.Command{ - Use: "goexec", - PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) { - // For modules that require a full executable path - if executablePath != "" && !regexp.MustCompile(`^([a-zA-Z]:)?\\`).MatchString(executablePath) { - return fmt.Errorf("executable path (-e) must be an absolute Windows path, i.e. C:\\Windows\\System32\\cmd.exe") - } - if command != "" { - p := strings.SplitN(command, " ", 2) - executable = p[0] - if len(p) > 1 { - executableArgs = p[1] - } + Use: "goexec", + Short: `Windows remote execution multitool`, + Long: `TODO`, + + PersistentPreRun: func(cmd *cobra.Command, args []string) { + + if logJson { + log = zerolog.New(os.Stderr) + } else { + log = zerolog.New(zerolog.ConsoleWriter{Out: os.Stderr}) } - log = zerolog.New(zerolog.ConsoleWriter{Out: os.Stderr}).Level(zerolog.InfoLevel).With().Timestamp().Logger() + + log = log.Level(zerolog.InfoLevel).With().Timestamp().Logger() if debug { log = log.Level(zerolog.DebugLevel) } - return + + if outputMethod == "smb" { + if exec.Output.RemotePath == "" { + exec.Output.RemotePath = util.RandomWindowsTempFile() + } + exec.Output.Provider = &smb.OutputFileFetcher{ + Client: &smbClient, + Share: `C$`, + File: exec.Output.RemotePath, + } + } }, } ) -func needs(reqs ...func(*cobra.Command, []string) error) (fn func(*cobra.Command, []string) error) { - return func(cmd *cobra.Command, args []string) (err error) { - for _, req := range reqs { - if err = req(cmd, args); err != nil { - return - } - } - return - } -} +func init() { + // Cobra init + { + cobra.EnableCommandSorting = false -func needsTarget(proto string) func(cmd *cobra.Command, args []string) error { + rootCmd.InitDefaultVersionFlag() + rootCmd.InitDefaultHelpCmd() + rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "Enable debug logging") + rootCmd.PersistentFlags().BoolVar(&logJson, "log-json", false, "Log in JSON format") - return func(cmd *cobra.Command, args []string) (err error) { - if proxyStr != "" { - if proxyUrl, err = url.Parse(proxyStr); err != nil { - return fmt.Errorf("failed to parse proxy URL %q: %w", proxyStr, err) - } - } - if len(args) != 1 { - return fmt.Errorf("command require exactly one positional argument: [target]") - } - if creds, target, err = authOpts.WithTarget(ctx, proto, args[0]); err != nil { - return fmt.Errorf("failed to parse target: %w", err) - } - if creds == nil { - return fmt.Errorf("no credentials supplied") - } - if target == nil { - return fmt.Errorf("no target supplied") - } - if hostname, err = target.Hostname(ctx); err != nil { - log.Debug().Err(err).Msg("Could not get target hostname") - } - return + dcomCmdInit() + rootCmd.AddCommand(dcomCmd) + + wmiCmdInit() + rootCmd.AddCommand(wmiCmd) + + scmrCmdInit() + rootCmd.AddCommand(scmrCmd) + + tschCmdInit() + rootCmd.AddCommand(tschCmd) } -} -func init() { - ctx = context.Background() - - cobra.EnableCommandSorting = false - - rootCmd.InitDefaultVersionFlag() - rootCmd.InitDefaultHelpCmd() - rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "Enable debug logging") - rootCmd.PersistentFlags().StringVarP(&proxyStr, "proxy", "x", "", "Proxy URL") - rootCmd.PersistentFlags().BoolVar(&unsafe, "unsafe", false, "[NOT IMPLEMENTED] Don't ask for permission to run unsafe actions") - - authOpts = &adauth.Options{Debug: log.Debug().Msgf} - authOpts.RegisterFlags(rootCmd.PersistentFlags()) - - scmrCmdInit() - rootCmd.AddCommand(scmrCmd) - tschCmdInit() - rootCmd.AddCommand(tschCmd) - wmiCmdInit() - rootCmd.AddCommand(wmiCmd) - dcomCmdInit() - rootCmd.AddCommand(dcomCmd) + // Auth init + { + gssapi.AddMechanism(ssp.SPNEGO) + gssapi.AddMechanism(ssp.NTLM) + gssapi.AddMechanism(ssp.KRB5) + + authOpts = &adauth.Options{Debug: log.Debug().Msgf} + authOpts.RegisterFlags(rootCmd.PersistentFlags()) + } } func Execute() { @@ -124,4 +107,5 @@ func Execute() { fmt.Println(err) os.Exit(1) } + os.Exit(returnCode) } |