diff options
author | Bryan McNulty <bryanmcnulty@protonmail.com> | 2025-04-17 03:22:59 -0500 |
---|---|---|
committer | Bryan McNulty <bryanmcnulty@protonmail.com> | 2025-04-17 03:22:59 -0500 |
commit | fc2ed14f92dd82268ca94d3d08c3760aba534d3f (patch) | |
tree | f17c5ccb01dfbf2764bfa938ee4570a9fa1b38d3 /cmd | |
parent | 22e4fc56cca0a8c466bf09a6f529573063ce5cb6 (diff) | |
download | goexec-fc2ed14f92dd82268ca94d3d08c3760aba534d3f.tar.gz goexec-fc2ed14f92dd82268ca94d3d08c3760aba534d3f.zip |
Slim down cobra Run function (WMI & TSCH)
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/root.go | 184 | ||||
-rw-r--r-- | cmd/tsch.go | 208 | ||||
-rw-r--r-- | cmd/wmi.go | 224 |
3 files changed, 297 insertions, 319 deletions
diff --git a/cmd/root.go b/cmd/root.go index 0f8a17a..3d696aa 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,112 +1,112 @@ package cmd import ( - "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" - "os" + "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" + "os" ) var ( - 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", - 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 = log.Level(zerolog.InfoLevel).With().Timestamp().Logger() - if debug { - log = log.Level(zerolog.DebugLevel) - } - - 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, - DeleteOutputFile: true, // TEMP - } - } - }, - } + 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", + 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 = log.Level(zerolog.InfoLevel).With().Timestamp().Logger() + if debug { + log = log.Level(zerolog.DebugLevel) + } + + 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, + DeleteOutputFile: exec.Output.NoDelete, // TEMP + } + } + }, + } ) func init() { - // Cobra init - { - cobra.EnableCommandSorting = false + // Cobra init + { + cobra.EnableCommandSorting = false - rootCmd.InitDefaultVersionFlag() - rootCmd.InitDefaultHelpCmd() - rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "Enable debug logging") - rootCmd.PersistentFlags().BoolVar(&logJson, "log-json", false, "Log in JSON format") + rootCmd.InitDefaultVersionFlag() + rootCmd.InitDefaultHelpCmd() + rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "Enable debug logging") + rootCmd.PersistentFlags().BoolVar(&logJson, "log-json", false, "Log in JSON format") - dcomCmdInit() - rootCmd.AddCommand(dcomCmd) + dcomCmdInit() + rootCmd.AddCommand(dcomCmd) - wmiCmdInit() - rootCmd.AddCommand(wmiCmd) + wmiCmdInit() + rootCmd.AddCommand(wmiCmd) - scmrCmdInit() - rootCmd.AddCommand(scmrCmd) + scmrCmdInit() + rootCmd.AddCommand(scmrCmd) - tschCmdInit() - rootCmd.AddCommand(tschCmd) - } + tschCmdInit() + rootCmd.AddCommand(tschCmd) + } - // Auth init - { - gssapi.AddMechanism(ssp.SPNEGO) - gssapi.AddMechanism(ssp.NTLM) - gssapi.AddMechanism(ssp.KRB5) + // 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()) - } + authOpts = &adauth.Options{Debug: log.Debug().Msgf} + authOpts.RegisterFlags(rootCmd.PersistentFlags()) + } } func Execute() { - if err := rootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } - os.Exit(returnCode) + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } + os.Exit(returnCode) } diff --git a/cmd/tsch.go b/cmd/tsch.go index 9192b0a..328adcd 100644 --- a/cmd/tsch.go +++ b/cmd/tsch.go @@ -1,87 +1,87 @@ package cmd import ( - "context" - "github.com/FalconOpsLLC/goexec/internal/util" - "github.com/FalconOpsLLC/goexec/pkg/goexec" - tschexec "github.com/FalconOpsLLC/goexec/pkg/goexec/tsch" - "github.com/oiweiwei/go-msrpc/ssp/gssapi" - "github.com/spf13/cobra" - "time" + "context" + "github.com/FalconOpsLLC/goexec/internal/util" + "github.com/FalconOpsLLC/goexec/pkg/goexec" + tschexec "github.com/FalconOpsLLC/goexec/pkg/goexec/tsch" + "github.com/oiweiwei/go-msrpc/ssp/gssapi" + "github.com/spf13/cobra" + "time" ) func tschCmdInit() { - registerRpcFlags(tschCmd) + registerRpcFlags(tschCmd) - tschDemandCmdInit() - tschCmd.AddCommand(tschDemandCmd) + tschDemandCmdInit() + tschCmd.AddCommand(tschDemandCmd) - tschCreateCmdInit() - tschCmd.AddCommand(tschCreateCmd) + tschCreateCmdInit() + tschCmd.AddCommand(tschCreateCmd) } func argsTschTaskIdentifiers(name, path string) error { - switch { - case path != "": - return tschexec.ValidateTaskPath(path) - case name != "": - return tschexec.ValidateTaskName(name) - default: - } - return nil + switch { + case path != "": + return tschexec.ValidateTaskPath(path) + case name != "": + return tschexec.ValidateTaskName(name) + default: + } + return nil } func argsTschDemand(_ *cobra.Command, _ []string) error { - return argsTschTaskIdentifiers(tschDemand.TaskName, tschDemand.TaskPath) + return argsTschTaskIdentifiers(tschDemand.TaskName, tschDemand.TaskPath) } func argsTschCreate(_ *cobra.Command, _ []string) error { - return argsTschTaskIdentifiers(tschCreate.TaskName, tschCreate.TaskPath) + return argsTschTaskIdentifiers(tschCreate.TaskName, tschCreate.TaskPath) } func tschDemandCmdInit() { - tschDemandCmd.Flags().StringVarP(&tschDemand.TaskName, "name", "t", "", "Name of task to register") - tschDemandCmd.Flags().StringVarP(&tschDemand.TaskPath, "path", "P", "", "Path of task to register") - tschDemandCmd.Flags().Uint32Var(&tschDemand.SessionId, "session", 0, "Hijack existing session given the session ID") - tschDemandCmd.Flags().BoolVar(&tschDemand.NoDelete, "no-delete", false, "Don't delete task after execution") - tschDemandCmd.Flags().StringVar(&tschDemand.UserSid, "sid", "S-1-5-18", "User SID to impersonate") + tschDemandCmd.Flags().StringVarP(&tschDemand.TaskName, "name", "t", "", "Name of task to register") + tschDemandCmd.Flags().StringVarP(&tschDemand.TaskPath, "path", "P", "", "Path of task to register") + tschDemandCmd.Flags().Uint32Var(&tschDemand.SessionId, "session", 0, "Hijack existing session given the session ID") + tschDemandCmd.Flags().BoolVar(&tschDemand.NoDelete, "no-delete", false, "Don't delete task after execution") + tschDemandCmd.Flags().StringVar(&tschDemand.UserSid, "sid", "S-1-5-18", "User SID to impersonate") - registerProcessExecutionArgs(tschDemandCmd) - registerExecutionOutputArgs(tschDemandCmd) + registerProcessExecutionArgs(tschDemandCmd) + registerExecutionOutputArgs(tschDemandCmd) - tschDemandCmd.MarkFlagsMutuallyExclusive("name", "path") + tschDemandCmd.MarkFlagsMutuallyExclusive("name", "path") } func tschCreateCmdInit() { - tschCreateCmd.Flags().StringVarP(&tschCreate.TaskName, "name", "t", "", "Name of task to register") - tschCreateCmd.Flags().StringVarP(&tschCreate.TaskPath, "path", "P", "", "Path of task to register") - tschCreateCmd.Flags().DurationVar(&tschCreate.StopDelay, "delay-stop", 5*time.Second, "Delay between task execution and termination. This will not stop the process spawned by the task") - tschCreateCmd.Flags().DurationVar(&tschCreate.StartDelay, "start-delay", 5*time.Second, "Delay between task registration and execution") - tschCreateCmd.Flags().DurationVar(&tschCreate.DeleteDelay, "delete-delay", 0*time.Second, "Delay between task termination and deletion") - tschCreateCmd.Flags().BoolVar(&tschCreate.NoDelete, "no-delete", false, "Don't delete task after execution") - tschCreateCmd.Flags().BoolVar(&tschCreate.CallDelete, "call-delete", false, "Directly call SchRpcDelete to delete task") - tschCreateCmd.Flags().StringVar(&tschCreate.UserSid, "sid", "S-1-5-18", "User SID to impersonate") - - registerProcessExecutionArgs(tschCreateCmd) - registerExecutionOutputArgs(tschCreateCmd) - - tschCreateCmd.MarkFlagsMutuallyExclusive("name", "path") + tschCreateCmd.Flags().StringVarP(&tschCreate.TaskName, "name", "t", "", "Name of task to register") + tschCreateCmd.Flags().StringVarP(&tschCreate.TaskPath, "path", "P", "", "Path of task to register") + tschCreateCmd.Flags().DurationVar(&tschCreate.StopDelay, "delay-stop", 5*time.Second, "Delay between task execution and termination. This will not stop the process spawned by the task") + tschCreateCmd.Flags().DurationVar(&tschCreate.StartDelay, "start-delay", 5*time.Second, "Delay between task registration and execution") + tschCreateCmd.Flags().DurationVar(&tschCreate.DeleteDelay, "delete-delay", 0*time.Second, "Delay between task termination and deletion") + tschCreateCmd.Flags().BoolVar(&tschCreate.NoDelete, "no-delete", false, "Don't delete task after execution") + tschCreateCmd.Flags().BoolVar(&tschCreate.CallDelete, "call-delete", false, "Directly call SchRpcDelete to delete task") + tschCreateCmd.Flags().StringVar(&tschCreate.UserSid, "sid", "S-1-5-18", "User SID to impersonate") + + registerProcessExecutionArgs(tschCreateCmd) + registerExecutionOutputArgs(tschCreateCmd) + + tschCreateCmd.MarkFlagsMutuallyExclusive("name", "path") } var ( - tschDemand tschexec.TschDemand - tschCreate tschexec.TschCreate - - tschCmd = &cobra.Command{ - Use: "tsch", - Short: "Establish execution via Windows Task Scheduler (MS-TSCH)", - Args: cobra.NoArgs, - } - - tschDemandCmd = &cobra.Command{ - Use: "demand [target]", - Short: "Register a remote scheduled task and demand immediate start", - Long: `Description: + tschDemand tschexec.TschDemand + tschCreate tschexec.TschCreate + + tschCmd = &cobra.Command{ + Use: "tsch", + Short: "Establish execution via Windows Task Scheduler (MS-TSCH)", + Args: cobra.NoArgs, + } + + tschDemandCmd = &cobra.Command{ + Use: "demand [target]", + Short: "Register a remote scheduled task and demand immediate start", + Long: `Description: Similar to the create method, the demand method will call SchRpcRegisterTask, But rather than setting a defined time when the task will start, it will additionally call SchRpcRun to forcefully start the task. @@ -90,33 +90,31 @@ References: SchRpcRegisterTask - https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tsch/849c131a-64e4-46ef-b015-9d4c599c5167 SchRpcRun - https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tsch/77f2250d-500a-40ee-be18-c82f7079c4f0 `, - Args: args( - argsRpcClient("cifs"), - argsOutput("smb"), - argsTschDemand, - ), - - Run: func(cmd *cobra.Command, args []string) { - var err error - - tschDemand.Client = &rpcClient - tschDemand.IO = exec - - if tschDemand.TaskName == "" && tschDemand.TaskPath == "" { - tschDemand.TaskPath = `\` + util.RandomString() - } - - ctx := log.WithContext(gssapi.NewSecurityContext(context.TODO())) - - if err = goexec.ExecuteCleanMethod(ctx, &tschDemand, &exec); err != nil { - log.Fatal().Err(err).Msg("Operation failed") - } - }, - } - tschCreateCmd = &cobra.Command{ - Use: "create [target]", - Short: "Create a remote scheduled task with an automatic start time", - Long: `Description: + Args: args( + argsRpcClient("cifs"), + argsOutput("smb"), + argsTschDemand, + ), + + Run: func(cmd *cobra.Command, args []string) { + tschDemand.Client = &rpcClient + tschDemand.IO = exec + + if tschDemand.TaskName == "" && tschDemand.TaskPath == "" { + tschDemand.TaskPath = `\` + util.RandomString() + } + + ctx := log.WithContext(gssapi.NewSecurityContext(context.TODO())) + + if err := goexec.ExecuteCleanMethod(ctx, &tschDemand, &exec); err != nil { + log.Fatal().Err(err).Msg("Operation failed") + } + }, + } + tschCreateCmd = &cobra.Command{ + Use: "create [target]", + Short: "Create a remote scheduled task with an automatic start time", + Long: `Description: The create method calls SchRpcRegisterTask to register a scheduled task with an automatic start time.This method avoids directly calling SchRpcRun, and can even avoid calling SchRpcDelete by populating the DeleteExpiredTaskAfter @@ -128,27 +126,25 @@ References: SchRpcDelete - https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tsch/360bb9b1-dd2a-4b36-83ee-21f12cb97cff DeleteExpiredTaskAfter - https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tsch/6bfde6fe-440e-4ddd-b4d6-c8fc0bc06fae `, - Args: args( - argsRpcClient("cifs"), - argsOutput("smb"), - argsTschCreate, - ), - - Run: func(cmd *cobra.Command, args []string) { - var err error - - tschCreate.Tsch.Client = &rpcClient - tschCreate.IO = exec - - if tschCreate.TaskName == "" && tschDemand.TaskPath == "" { - tschCreate.TaskPath = `\` + util.RandomString() - } - - ctx := log.WithContext(gssapi.NewSecurityContext(context.TODO())) - - if err = goexec.ExecuteCleanMethod(ctx, &tschCreate, &exec); err != nil { - log.Fatal().Err(err).Msg("Operation failed") - } - }, - } + Args: args( + argsRpcClient("cifs"), + argsOutput("smb"), + argsTschCreate, + ), + + Run: func(cmd *cobra.Command, args []string) { + tschCreate.Tsch.Client = &rpcClient + tschCreate.IO = exec + + if tschCreate.TaskName == "" && tschDemand.TaskPath == "" { + tschCreate.TaskPath = `\` + util.RandomString() + } + + ctx := log.WithContext(gssapi.NewSecurityContext(context.TODO())) + + if err := goexec.ExecuteCleanMethod(ctx, &tschCreate, &exec); err != nil { + log.Fatal().Err(err).Msg("Operation failed") + } + }, + } ) @@ -1,119 +1,117 @@ package cmd import ( - "context" - "encoding/json" - "fmt" - "github.com/FalconOpsLLC/goexec/pkg/goexec" - wmiexec "github.com/FalconOpsLLC/goexec/pkg/goexec/wmi" - "github.com/oiweiwei/go-msrpc/ssp/gssapi" - "github.com/spf13/cobra" - "io" - "os" + "context" + "encoding/json" + "fmt" + "github.com/FalconOpsLLC/goexec/pkg/goexec" + wmiexec "github.com/FalconOpsLLC/goexec/pkg/goexec/wmi" + "github.com/oiweiwei/go-msrpc/ssp/gssapi" + "github.com/spf13/cobra" ) func wmiCmdInit() { - registerRpcFlags(wmiCmd) + registerRpcFlags(wmiCmd) - wmiCallCmdInit() - wmiCmd.AddCommand(wmiCallCmd) + wmiCallCmdInit() + wmiCmd.AddCommand(wmiCallCmd) - wmiProcCmdInit() - wmiCmd.AddCommand(wmiProcCmd) + wmiProcCmdInit() + wmiCmd.AddCommand(wmiProcCmd) } func wmiCallArgs(_ *cobra.Command, _ []string) error { - return json.Unmarshal([]byte(wmiArguments), &wmiCall.Args) + return json.Unmarshal([]byte(wmiArguments), &wmiCall.Args) } func wmiCallCmdInit() { - wmiCallCmd.Flags().StringVarP(&wmiCall.Resource, "namespace", "n", "//./root/cimv2", "WMI namespace") - wmiCallCmd.Flags().StringVarP(&wmiCall.Class, "class", "C", "", `WMI class to instantiate (i.e. "Win32_Process")`) - wmiCallCmd.Flags().StringVarP(&wmiCall.Method, "method", "m", "", `WMI Method to call (i.e. "Create")`) - wmiCallCmd.Flags().StringVarP(&wmiArguments, "args", "A", "{}", `WMI Method argument(s) in JSON dictionary format (i.e. {"CommandLine":"calc.exe"})`) - - if err := wmiCallCmd.MarkFlagRequired("class"); err != nil { - panic(err) - } - if err := wmiCallCmd.MarkFlagRequired("method"); err != nil { - panic(err) - } + wmiCallCmd.Flags().StringVarP(&wmiCall.Resource, "namespace", "n", "//./root/cimv2", "WMI namespace") + wmiCallCmd.Flags().StringVarP(&wmiCall.Class, "class", "C", "", `WMI class to instantiate (i.e. "Win32_Process")`) + wmiCallCmd.Flags().StringVarP(&wmiCall.Method, "method", "m", "", `WMI Method to call (i.e. "Create")`) + wmiCallCmd.Flags().StringVarP(&wmiArguments, "args", "A", "{}", `WMI Method argument(s) in JSON dictionary format (i.e. {"CommandLine":"calc.exe"})`) + + if err := wmiCallCmd.MarkFlagRequired("class"); err != nil { + panic(err) + } + if err := wmiCallCmd.MarkFlagRequired("method"); err != nil { + panic(err) + } } func wmiProcCmdInit() { - wmiProcCmd.Flags().StringVarP(&wmiProc.Resource, "namespace", "n", "//./root/cimv2", "WMI namespace") - wmiProcCmd.Flags().StringVarP(&wmiProc.WorkingDirectory, "directory", "d", `C:\`, "Working directory") + wmiProcCmd.Flags().StringVarP(&wmiProc.Resource, "namespace", "n", "//./root/cimv2", "WMI namespace") + wmiProcCmd.Flags().StringVarP(&wmiProc.WorkingDirectory, "directory", "d", `C:\`, "Working directory") - registerProcessExecutionArgs(wmiProcCmd) - registerExecutionOutputArgs(wmiProcCmd) + registerProcessExecutionArgs(wmiProcCmd) + registerExecutionOutputArgs(wmiProcCmd) } var ( - wmiCall = wmiexec.WmiCall{} - wmiProc = wmiexec.WmiProc{} + wmiCall = wmiexec.WmiCall{} + wmiProc = wmiexec.WmiProc{} - wmiArguments string + wmiArguments string - wmiCmd = &cobra.Command{ - Use: "wmi", - Short: "Establish execution via wmi", - Args: cobra.NoArgs, - } + wmiCmd = &cobra.Command{ + Use: "wmi", + Short: "Establish execution via wmi", + Args: cobra.NoArgs, + } - wmiCallCmd = &cobra.Command{ - Use: "call", - Short: "Execute specified WMI method", - Long: `Description: + wmiCallCmd = &cobra.Command{ + Use: "call", + Short: "Execute specified WMI method", + Long: `Description: The call method creates an instance of the specified WMI class (-c), then calls the provided method (-m) with the provided arguments (-A). References: https://learn.microsoft.com/en-us/windows/win32/wmisdk/wmi-classes `, - Args: args(argsRpcClient("host"), wmiCallArgs), - - Run: func(cmd *cobra.Command, args []string) { - var err error - - ctx := gssapi.NewSecurityContext(context.Background()) - - ctx = log.With(). - Str("module", "wmi"). - Str("method", "call"). - Logger(). - WithContext(ctx) - - 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 = wmiCall.Init(ctx); err != nil { - log.Error().Err(err).Msg("Module initialization failed") - returnCode = 2 - return - } - - out, err := wmiCall.Call(ctx) - if err != nil { - log.Error().Err(err).Msg("Call failed") - returnCode = 4 - return - } - fmt.Println(string(out)) - }, - } - - wmiProcCmd = &cobra.Command{ - Use: "proc", - Short: "Start a Windows process", - Long: `Description: + Args: args(argsRpcClient("host"), wmiCallArgs), + + Run: func(cmd *cobra.Command, args []string) { + var err error + + ctx := gssapi.NewSecurityContext(context.Background()) + + ctx = log.With(). + Str("module", "wmi"). + Str("method", "call"). + Logger(). + WithContext(ctx) + + 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 = wmiCall.Init(ctx); err != nil { + log.Error().Err(err).Msg("Module initialization failed") + returnCode = 2 + return + } + + out, err := wmiCall.Call(ctx) + if err != nil { + log.Error().Err(err).Msg("Call failed") + returnCode = 4 + return + } + fmt.Println(string(out)) + }, + } + + wmiProcCmd = &cobra.Command{ + Use: "proc", + Short: "Start a Windows process", + Long: `Description: The proc method creates an instance of the Win32_Process WMI class, then calls the Win32_Process.Create method with the provided command (-c), and optional working directory (-d). @@ -121,39 +119,23 @@ References: References: https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/create-method-in-class-win32-process `, - Args: args(argsOutput("smb"), argsRpcClient("host")), - - Run: func(cmd *cobra.Command, args []string) { - var err error - - wmiProc.Client = &rpcClient - wmiProc.IO = exec - - ctx := log.WithContext(gssapi.NewSecurityContext(context.TODO())) - - var writer io.WriteCloser - - if outputPath == "-" { - writer = os.Stdout - - } else if outputPath != "" { - - if writer, err = os.OpenFile(outputPath, os.O_WRONLY|os.O_CREATE, 0644); err != nil { - log.Fatal().Err(err).Msg("Failed to open output file") - } - defer writer.Close() - } - - if err = goexec.ExecuteCleanMethod(ctx, &wmiProc, &exec); err != nil { - log.Fatal().Err(err).Msg("Operation failed") - } - - if outputPath != "" { - if err = wmiProc.IO.GetOutput(ctx); err != nil { - log.Error().Err(err).Msg("Failed to get process execution output") - returnCode = 4 - } - } - }, - } + Args: args( + argsOutput("smb"), + argsRpcClient("host"), + ), + + Run: func(cmd *cobra.Command, args []string) { + wmiProc.Client = &rpcClient + wmiProc.IO = exec + + ctx := log.With(). + Str("module", "wmi"). + Str("method", "proc"). + Logger().WithContext(gssapi.NewSecurityContext(context.TODO())) + + if err := goexec.ExecuteCleanMethod(ctx, &wmiProc, &exec); err != nil { + log.Fatal().Err(err).Msg("Operation failed") + } + }, + } ) |