From c7769ec00578d6e25ffb50f5fb28ae7923e196a8 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 3 Mar 2026 16:40:38 +0000 Subject: [PATCH] feat: wire --upload flags to all 12 execution method commands DCOM (6 commands): - dcom mmc, shellwindows, shellbrowserwindow, htafile, excel macro, visualstudio dte TSCH (3 commands): - tsch demand, create, change WMI (1 command): - wmi proc SCMR (2 commands): - scmr create, change For each command: - Register upload flags (--upload, --upload-dest, --no-delete-upload) - Add argsUpload('smb') to Args chain for SMB client setup - Update MarkFlagsOneRequired to accept 'upload' as alternative to exec/command Co-authored-by: Carter --- cmd/dcom.go | 249 +++++++++++++++++++++++++++------------------------- cmd/scmr.go | 125 +++++++++++++------------- cmd/tsch.go | 92 ++++++++++--------- cmd/wmi.go | 22 ++--- 4 files changed, 253 insertions(+), 235 deletions(-) diff --git a/cmd/dcom.go b/cmd/dcom.go index 79fbd67..bcd289b 100644 --- a/cmd/dcom.go +++ b/cmd/dcom.go @@ -61,127 +61,133 @@ func dcomVisualStudioCmdInit() { } func dcomMmcCmdInit() { - dcomMmcExecFlags := newFlagSet("Execution") - registerExecutionFlags(dcomMmcExecFlags.Flags) - registerExecutionOutputFlags(dcomMmcExecFlags.Flags) - dcomMmcExecFlags.Flags.StringVar(&dcomMmc.WorkingDirectory, "directory", `C:\`, "Working `directory`") - dcomMmcExecFlags.Flags.StringVar(&dcomMmc.WindowState, "window", "Minimized", "Window state") + dcomMmcExecFlags := newFlagSet("Execution") + registerExecutionFlags(dcomMmcExecFlags.Flags) + registerExecutionOutputFlags(dcomMmcExecFlags.Flags) + registerExecutionUploadFlags(dcomMmcExecFlags.Flags) + dcomMmcExecFlags.Flags.StringVar(&dcomMmc.WorkingDirectory, "directory", `C:\`, "Working `directory`") + dcomMmcExecFlags.Flags.StringVar(&dcomMmc.WindowState, "window", "Minimized", "Window state") - cmdFlags[dcomMmcCmd] = []*flagSet{ - dcomMmcExecFlags, - defaultAuthFlags, - defaultLogFlags, - defaultNetRpcFlags, - } - dcomMmcCmd.Flags().AddFlagSet(dcomMmcExecFlags.Flags) + cmdFlags[dcomMmcCmd] = []*flagSet{ + dcomMmcExecFlags, + defaultAuthFlags, + defaultLogFlags, + defaultNetRpcFlags, + } + dcomMmcCmd.Flags().AddFlagSet(dcomMmcExecFlags.Flags) - // Constraints - dcomMmcCmd.MarkFlagsOneRequired("command", "exec") + // Constraints + dcomMmcCmd.MarkFlagsOneRequired("command", "exec", "upload") } func dcomShellWindowsCmdInit() { - dcomShellWindowsExecFlags := newFlagSet("Execution") - registerExecutionFlags(dcomShellWindowsExecFlags.Flags) - registerExecutionOutputFlags(dcomShellWindowsExecFlags.Flags) - dcomShellWindowsExecFlags.Flags.StringVar(&dcomShellWindows.WorkingDirectory, "directory", `C:\`, "Working directory `path`") - dcomShellWindowsExecFlags.Flags.StringVar(&dcomShellWindows.WindowState, "app-window", "0", "Application window state `ID`") + dcomShellWindowsExecFlags := newFlagSet("Execution") + registerExecutionFlags(dcomShellWindowsExecFlags.Flags) + registerExecutionOutputFlags(dcomShellWindowsExecFlags.Flags) + registerExecutionUploadFlags(dcomShellWindowsExecFlags.Flags) + dcomShellWindowsExecFlags.Flags.StringVar(&dcomShellWindows.WorkingDirectory, "directory", `C:\`, "Working directory `path`") + dcomShellWindowsExecFlags.Flags.StringVar(&dcomShellWindows.WindowState, "app-window", "0", "Application window state `ID`") - cmdFlags[dcomShellWindowsCmd] = []*flagSet{ - dcomShellWindowsExecFlags, - defaultAuthFlags, - defaultLogFlags, - defaultNetRpcFlags, - } - dcomShellWindowsCmd.Flags().AddFlagSet(dcomShellWindowsExecFlags.Flags) + cmdFlags[dcomShellWindowsCmd] = []*flagSet{ + dcomShellWindowsExecFlags, + defaultAuthFlags, + defaultLogFlags, + defaultNetRpcFlags, + } + dcomShellWindowsCmd.Flags().AddFlagSet(dcomShellWindowsExecFlags.Flags) - // Constraints - dcomShellWindowsCmd.MarkFlagsOneRequired("command", "exec") + // Constraints + dcomShellWindowsCmd.MarkFlagsOneRequired("command", "exec", "upload") } func dcomShellBrowserWindowCmdInit() { - dcomShellBrowserWindowExecFlags := newFlagSet("Execution") - registerExecutionFlags(dcomShellBrowserWindowExecFlags.Flags) - registerExecutionOutputFlags(dcomShellBrowserWindowExecFlags.Flags) - dcomShellBrowserWindowExecFlags.Flags.StringVar(&dcomShellBrowserWindow.WorkingDirectory, "directory", `C:\`, "Working directory `path`") - dcomShellBrowserWindowExecFlags.Flags.StringVar(&dcomShellBrowserWindow.WindowState, "app-window", "0", "Application window state `ID`") + dcomShellBrowserWindowExecFlags := newFlagSet("Execution") + registerExecutionFlags(dcomShellBrowserWindowExecFlags.Flags) + registerExecutionOutputFlags(dcomShellBrowserWindowExecFlags.Flags) + registerExecutionUploadFlags(dcomShellBrowserWindowExecFlags.Flags) + dcomShellBrowserWindowExecFlags.Flags.StringVar(&dcomShellBrowserWindow.WorkingDirectory, "directory", `C:\`, "Working directory `path`") + dcomShellBrowserWindowExecFlags.Flags.StringVar(&dcomShellBrowserWindow.WindowState, "app-window", "0", "Application window state `ID`") - cmdFlags[dcomShellBrowserWindowCmd] = []*flagSet{ - dcomShellBrowserWindowExecFlags, - defaultAuthFlags, - defaultLogFlags, - defaultNetRpcFlags, - } - dcomShellBrowserWindowCmd.Flags().AddFlagSet(dcomShellBrowserWindowExecFlags.Flags) + cmdFlags[dcomShellBrowserWindowCmd] = []*flagSet{ + dcomShellBrowserWindowExecFlags, + defaultAuthFlags, + defaultLogFlags, + defaultNetRpcFlags, + } + dcomShellBrowserWindowCmd.Flags().AddFlagSet(dcomShellBrowserWindowExecFlags.Flags) - // Constraints - dcomShellBrowserWindowCmd.MarkFlagsOneRequired("command", "exec") + // Constraints + dcomShellBrowserWindowCmd.MarkFlagsOneRequired("command", "exec", "upload") } func dcomHtafileCmdInit() { - dcomHtafileExecFlags := newFlagSet("Execution") - dcomHtafileExecFlags.Flags.StringVarP(&dcomHtafile.Url, "url", "U", "", "Load custom `URL`") - dcomHtafileExecFlags.Flags.StringVar(&dcomHtafile.Javascript, "js", "", "Execute JavaScript one-liner") - dcomHtafileExecFlags.Flags.StringVar(&dcomHtafile.Vbscript, "vbs", "", "Execute VBScript one-liner") - registerExecutionFlags(dcomHtafileExecFlags.Flags) - registerExecutionOutputFlags(dcomHtafileExecFlags.Flags) + dcomHtafileExecFlags := newFlagSet("Execution") + dcomHtafileExecFlags.Flags.StringVarP(&dcomHtafile.Url, "url", "U", "", "Load custom `URL`") + dcomHtafileExecFlags.Flags.StringVar(&dcomHtafile.Javascript, "js", "", "Execute JavaScript one-liner") + dcomHtafileExecFlags.Flags.StringVar(&dcomHtafile.Vbscript, "vbs", "", "Execute VBScript one-liner") + registerExecutionFlags(dcomHtafileExecFlags.Flags) + registerExecutionOutputFlags(dcomHtafileExecFlags.Flags) + registerExecutionUploadFlags(dcomHtafileExecFlags.Flags) - cmdFlags[dcomHtafileCmd] = []*flagSet{ - dcomHtafileExecFlags, - defaultAuthFlags, - defaultLogFlags, - defaultNetRpcFlags, - } - dcomHtafileCmd.Flags().AddFlagSet(dcomHtafileExecFlags.Flags) + cmdFlags[dcomHtafileCmd] = []*flagSet{ + dcomHtafileExecFlags, + defaultAuthFlags, + defaultLogFlags, + defaultNetRpcFlags, + } + dcomHtafileCmd.Flags().AddFlagSet(dcomHtafileExecFlags.Flags) - // Constraints - dcomHtafileCmd.MarkFlagsOneRequired("command", "exec", "url", "js", "vbs") + // Constraints + dcomHtafileCmd.MarkFlagsOneRequired("command", "exec", "url", "js", "vbs", "upload") } func dcomExcelMacroCmdInit() { - dcomExcelMacroExecFlags := newFlagSet("Execution") - dcomExcelMacroExecFlags.Flags.StringArrayVarP(&dcomExcelMacro.Macros, "macro", "M", nil, "XLM macro `code`") - dcomExcelMacroExecFlags.Flags.StringVar(&dcomExcelMacro.MacroFile, "macro-file", "", "XLM macro `file`") - registerExecutionFlags(dcomExcelMacroExecFlags.Flags) - registerExecutionOutputFlags(dcomExcelMacroExecFlags.Flags) + dcomExcelMacroExecFlags := newFlagSet("Execution") + dcomExcelMacroExecFlags.Flags.StringArrayVarP(&dcomExcelMacro.Macros, "macro", "M", nil, "XLM macro `code`") + dcomExcelMacroExecFlags.Flags.StringVar(&dcomExcelMacro.MacroFile, "macro-file", "", "XLM macro `file`") + registerExecutionFlags(dcomExcelMacroExecFlags.Flags) + registerExecutionOutputFlags(dcomExcelMacroExecFlags.Flags) + registerExecutionUploadFlags(dcomExcelMacroExecFlags.Flags) - cmdFlags[dcomExcelMacroCmd] = []*flagSet{ - dcomExcelMacroExecFlags, - defaultAuthFlags, - defaultLogFlags, - defaultNetRpcFlags, - } - dcomExcelMacroCmd.Flags().AddFlagSet(dcomExcelMacroExecFlags.Flags) + cmdFlags[dcomExcelMacroCmd] = []*flagSet{ + dcomExcelMacroExecFlags, + defaultAuthFlags, + defaultLogFlags, + defaultNetRpcFlags, + } + dcomExcelMacroCmd.Flags().AddFlagSet(dcomExcelMacroExecFlags.Flags) - // Constraints - dcomExcelMacroCmd.MarkFlagsOneRequired("command", "exec", "macro", "macro-file") - dcomExcelMacroCmd.MarkFlagsMutuallyExclusive("command", "exec", "macro", "macro-file") - dcomExcelMacroCmd.MarkFlagsMutuallyExclusive("macro", "macro-file", "out") + // Constraints + dcomExcelMacroCmd.MarkFlagsOneRequired("command", "exec", "macro", "macro-file", "upload") + dcomExcelMacroCmd.MarkFlagsMutuallyExclusive("command", "exec", "macro", "macro-file") + dcomExcelMacroCmd.MarkFlagsMutuallyExclusive("macro", "macro-file", "out") } func dcomVisualStudioDteCmdInit() { - dcomVisualStudioDteVsFlags := newFlagSet("Visual Studio") - dcomVisualStudioDteVsFlags.Flags.BoolVar(&dcomVisualStudioDte.Is2019, "vs-2019", false, "Target Visual Studio 2019") - dcomVisualStudioDteVsFlags.Flags.StringVar(&dcomVisualStudioDte.CommandName, "vs-command", "", "Visual Studio DTE command to execute") - dcomVisualStudioDteVsFlags.Flags.StringVar(&dcomVisualStudioDte.CommandArgs, "vs-args", "", "Visual Studio DTE command arguments") + dcomVisualStudioDteVsFlags := newFlagSet("Visual Studio") + dcomVisualStudioDteVsFlags.Flags.BoolVar(&dcomVisualStudioDte.Is2019, "vs-2019", false, "Target Visual Studio 2019") + dcomVisualStudioDteVsFlags.Flags.StringVar(&dcomVisualStudioDte.CommandName, "vs-command", "", "Visual Studio DTE command to execute") + dcomVisualStudioDteVsFlags.Flags.StringVar(&dcomVisualStudioDte.CommandArgs, "vs-args", "", "Visual Studio DTE command arguments") - dcomVisualStudioDteExecFlags := newFlagSet("Execution") - registerExecutionFlags(dcomVisualStudioDteExecFlags.Flags) - registerExecutionOutputFlags(dcomVisualStudioDteExecFlags.Flags) + dcomVisualStudioDteExecFlags := newFlagSet("Execution") + registerExecutionFlags(dcomVisualStudioDteExecFlags.Flags) + registerExecutionOutputFlags(dcomVisualStudioDteExecFlags.Flags) + registerExecutionUploadFlags(dcomVisualStudioDteExecFlags.Flags) - cmdFlags[dcomVisualStudioDteCmd] = []*flagSet{ - dcomVisualStudioDteVsFlags, - dcomVisualStudioDteExecFlags, - defaultAuthFlags, - defaultLogFlags, - defaultNetRpcFlags, - } - dcomVisualStudioDteCmd.Flags().AddFlagSet(dcomVisualStudioDteVsFlags.Flags) - dcomVisualStudioDteCmd.Flags().AddFlagSet(dcomVisualStudioDteExecFlags.Flags) + cmdFlags[dcomVisualStudioDteCmd] = []*flagSet{ + dcomVisualStudioDteVsFlags, + dcomVisualStudioDteExecFlags, + defaultAuthFlags, + defaultLogFlags, + defaultNetRpcFlags, + } + dcomVisualStudioDteCmd.Flags().AddFlagSet(dcomVisualStudioDteVsFlags.Flags) + dcomVisualStudioDteCmd.Flags().AddFlagSet(dcomVisualStudioDteExecFlags.Flags) - // Constraints - dcomVisualStudioDteCmd.MarkFlagsOneRequired("command", "exec", "vs-command") - dcomVisualStudioDteCmd.MarkFlagsMutuallyExclusive("command", "exec", "vs-command") - dcomVisualStudioDteCmd.MarkFlagsMutuallyExclusive("vs-command", "out") + // Constraints + dcomVisualStudioDteCmd.MarkFlagsOneRequired("command", "exec", "vs-command", "upload") + dcomVisualStudioDteCmd.MarkFlagsMutuallyExclusive("command", "exec", "vs-command") + dcomVisualStudioDteCmd.MarkFlagsMutuallyExclusive("vs-command", "out") } func dcomExcelXllCmdInit() { @@ -240,12 +246,13 @@ var ( Long: `Description: The mmc method uses the exposed MMC20.Application object to call Document.ActiveView.ShellExec, and ultimately spawn a process on the remote host.`, - Args: args(argsRpcClient("cifs", ""), - argsOutput("smb"), - argsAcceptValues("window", &dcomMmc.WindowState, "Minimized", "Maximized", "Restored"), - ), - Run: func(cmd *cobra.Command, args []string) { - dcomMmc.Client = &rpcClient + Args: args(argsRpcClient("cifs", ""), + argsOutput("smb"), + argsUpload("smb"), + argsAcceptValues("window", &dcomMmc.WindowState, "Minimized", "Maximized", "Restored"), + ), + Run: func(cmd *cobra.Command, args []string) { + dcomMmc.Client = &rpcClient ctx := log.With().Str("module", dcomexec.ModuleName).Str("method", dcomexec.MethodMmc). Logger().WithContext(gssapi.NewSecurityContext(context.Background())) @@ -261,12 +268,13 @@ var ( Long: `Description: The shellwindows method uses the exposed ShellWindows DCOM object on older Windows installations to call Item().Document.Application.ShellExecute, and spawn the provided process.`, - Args: args(argsRpcClient("host", ""), - argsOutput("smb"), - argsAcceptValues("app-window", &dcomShellWindows.WindowState, "0", "1", "2", "3", "4", "5", "7", "10"), - ), - Run: func(cmd *cobra.Command, args []string) { - dcomShellWindows.Client = &rpcClient + Args: args(argsRpcClient("host", ""), + argsOutput("smb"), + argsUpload("smb"), + argsAcceptValues("app-window", &dcomShellWindows.WindowState, "0", "1", "2", "3", "4", "5", "7", "10"), + ), + Run: func(cmd *cobra.Command, args []string) { + dcomShellWindows.Client = &rpcClient ctx := log.With().Str("module", dcomexec.ModuleName).Str("method", dcomexec.MethodShellWindows). Logger().WithContext(gssapi.NewSecurityContext(context.Background())) @@ -282,12 +290,13 @@ var ( Long: `Description: The shellbrowserwindow method uses the exposed ShellBrowserWindow DCOM object on older Windows installations to call Document.Application.ShellExecute, and spawn the provided process.`, - Args: args(argsRpcClient("host", ""), - argsOutput("smb"), - argsAcceptValues("app-window", &dcomShellBrowserWindow.WindowState, "0", "1", "2", "3", "4", "5", "7", "10"), - ), - Run: func(cmd *cobra.Command, args []string) { - dcomShellBrowserWindow.Client = &rpcClient + Args: args(argsRpcClient("host", ""), + argsOutput("smb"), + argsUpload("smb"), + argsAcceptValues("app-window", &dcomShellBrowserWindow.WindowState, "0", "1", "2", "3", "4", "5", "7", "10"), + ), + Run: func(cmd *cobra.Command, args []string) { + dcomShellBrowserWindow.Client = &rpcClient ctx := log.With().Str("module", dcomexec.ModuleName).Str("method", dcomexec.MethodShellBrowserWindow). Logger().WithContext(gssapi.NewSecurityContext(context.Background())) @@ -303,9 +312,9 @@ var ( Long: `Description: The htafile method uses the exposed "HTML Application" DCOM object to load a remote HTA application or execute inline. This is made possible by the Load method of the IPersistMoniker interface.`, - Args: args(argsRpcClient("host", ""), argsOutput("smb")), - RunE: func(cmd *cobra.Command, args []string) error { - dcomHtafile.Client = &rpcClient + Args: args(argsRpcClient("host", ""), argsOutput("smb"), argsUpload("smb")), + RunE: func(cmd *cobra.Command, args []string) error { + dcomHtafile.Client = &rpcClient dcomHtafile.Url = dcomexec.HtafileGetUrl(dcomHtafile.Url, dcomHtafile.Javascript, dcomHtafile.Vbscript, &exec) if url := strings.ToLower(dcomHtafile.Url); (strings.HasPrefix(url, "javascript:") || strings.HasPrefix(url, "vbscript:")) && len(url) > 508 { @@ -327,9 +336,9 @@ var ( Long: `Description: The macro method uses the exposed Excel.Application DCOM object to call ExecuteExcel4Macro, thus executing XLM macros at will. This method requires that the remote host has Microsoft Excel installed.`, - Args: args(argsRpcClient("host", ""), argsOutput("smb"), - func(*cobra.Command, []string) error { - if dcomExcelMacro.MacroFile != "" { + Args: args(argsRpcClient("host", ""), argsOutput("smb"), argsUpload("smb"), + func(*cobra.Command, []string) error { + if dcomExcelMacro.MacroFile != "" { f, err := os.Open(dcomExcelMacro.MacroFile) if err != nil { return fmt.Errorf("open macro file: %w", err) @@ -380,9 +389,9 @@ var ( Long: `Description: The dte method uses the exposed VisualStudio.DTE object to spawn a process via the ExecuteCommand method. This method requires that the remote host has Microsoft Visual Studio installed.`, - Args: args(argsRpcClient("host", ""), argsOutput("smb")), - Run: func(*cobra.Command, []string) { - dcomVisualStudioDte.Client = &rpcClient + Args: args(argsRpcClient("host", ""), argsOutput("smb"), argsUpload("smb")), + Run: func(*cobra.Command, []string) { + dcomVisualStudioDte.Client = &rpcClient ctx := log.With().Str("module", dcomexec.ModuleName).Str("method", dcomexec.MethodVisualStudioDTE). Logger().WithContext(gssapi.NewSecurityContext(context.Background())) diff --git a/cmd/scmr.go b/cmd/scmr.go index 0b45287..354768b 100644 --- a/cmd/scmr.go +++ b/cmd/scmr.go @@ -28,76 +28,73 @@ func scmrCmdInit() { } func scmrCreateCmdInit() { - scmrCreateFlags := newFlagSet("Service") + 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") + 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") + scmrCreateExecFlags := newFlagSet("Execution") - // TODO: SCMR output - //registerExecutionOutputFlags(scmrCreateExecFlags.Flags) + // TODO: SCMR output + //registerExecutionOutputFlags(scmrCreateExecFlags.Flags) + registerExecutionUploadFlags(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") + 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) + scmrCreateCmd.Flags().AddFlagSet(scmrCreateFlags.Flags) + scmrCreateCmd.Flags().AddFlagSet(scmrCreateExecFlags.Flags) - cmdFlags[scmrCreateCmd] = []*flagSet{ - scmrCreateExecFlags, - scmrCreateFlags, - defaultAuthFlags, - defaultLogFlags, - defaultNetRpcFlags, - } + 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) - } - } + // Constraints + { + //scmrCreateCmd.MarkFlagsMutuallyExclusive("no-delete", "no-start") + scmrCreateCmd.MarkFlagsOneRequired("executable-path", "upload") + } } func scmrChangeCmdInit() { - scmrChangeFlags := newFlagSet("Service Control") + 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") + 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 := 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") + 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) + // TODO: SCMR output + //registerExecutionOutputFlags(scmrChangeExecFlags.Flags) + registerExecutionUploadFlags(scmrChangeExecFlags.Flags) - cmdFlags[scmrChangeCmd] = []*flagSet{ - scmrChangeFlags, - scmrChangeExecFlags, - defaultAuthFlags, - defaultLogFlags, - defaultNetRpcFlags, - } + cmdFlags[scmrChangeCmd] = []*flagSet{ + scmrChangeFlags, + scmrChangeExecFlags, + defaultAuthFlags, + defaultLogFlags, + defaultNetRpcFlags, + } - scmrChangeCmd.Flags().AddFlagSet(scmrChangeFlags.Flags) - scmrChangeCmd.Flags().AddFlagSet(scmrChangeExecFlags.Flags) + 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) - } - } + // Constraints + { + if err := scmrChangeCmd.MarkFlagRequired("service-name"); err != nil { + panic(err) + } + scmrChangeCmd.MarkFlagsOneRequired("executable-path", "upload") + } } func scmrDeleteCmdInit() { @@ -139,13 +136,14 @@ var ( 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`, - Args: args( - argsRpcClient("cifs", "ncacn_np:[svcctl]"), - argsSmbClient(), - ), + Args: args( + argsRpcClient("cifs", "ncacn_np:[svcctl]"), + argsSmbClient(), + argsUpload("smb"), + ), - Run: func(cmd *cobra.Command, args []string) { - scmrCreate.Client = &rpcClient + Run: func(cmd *cobra.Command, args []string) { + scmrCreate.Client = &rpcClient scmrCreate.IO = exec log = log.With(). @@ -184,10 +182,13 @@ var ( 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", "ncacn_np:[svcctl]"), + Args: args( + argsRpcClient("cifs", "ncacn_np:[svcctl]"), + argsUpload("smb"), + ), - Run: func(cmd *cobra.Command, args []string) { - scmrChange.Client = &rpcClient + Run: func(cmd *cobra.Command, args []string) { + scmrChange.Client = &rpcClient scmrChange.IO = exec ctx := log.With(). diff --git a/cmd/tsch.go b/cmd/tsch.go index a9b0d71..8803ca3 100644 --- a/cmd/tsch.go +++ b/cmd/tsch.go @@ -36,12 +36,13 @@ func tschDemandCmdInit() { tschDemandFlags.Flags.StringVar(&tschDemand.UserSid, "sid", "S-1-5-18", "User `SID` to impersonate") tschDemandFlags.Flags.BoolVar(&tschDemand.NoDelete, "no-delete", false, "Don't delete task after execution") - tschDemandExecFlags := newFlagSet("Execution") + tschDemandExecFlags := newFlagSet("Execution") - registerExecutionFlags(tschDemandExecFlags.Flags) - registerExecutionOutputFlags(tschDemandExecFlags.Flags) + registerExecutionFlags(tschDemandExecFlags.Flags) + registerExecutionOutputFlags(tschDemandExecFlags.Flags) + registerExecutionUploadFlags(tschDemandExecFlags.Flags) - cmdFlags[tschDemandCmd] = []*flagSet{ + cmdFlags[tschDemandCmd] = []*flagSet{ tschDemandFlags, tschDemandExecFlags, defaultAuthFlags, @@ -49,9 +50,9 @@ func tschDemandCmdInit() { defaultNetRpcFlags, } - tschDemandCmd.Flags().AddFlagSet(tschDemandFlags.Flags) - tschDemandCmd.Flags().AddFlagSet(tschDemandExecFlags.Flags) - tschDemandCmd.MarkFlagsOneRequired("exec", "command") + tschDemandCmd.Flags().AddFlagSet(tschDemandFlags.Flags) + tschDemandCmd.Flags().AddFlagSet(tschDemandExecFlags.Flags) + tschDemandCmd.MarkFlagsOneRequired("exec", "command", "upload") } func tschCreateCmdInit() { @@ -65,12 +66,13 @@ func tschCreateCmdInit() { tschCreateFlags.Flags.BoolVar(&tschCreate.CallDelete, "call-delete", false, "Directly call SchRpcDelete to delete task") tschCreateFlags.Flags.StringVar(&tschCreate.UserSid, "sid", "S-1-5-18", "User `SID` to impersonate") - tschCreateExecFlags := newFlagSet("Execution") + tschCreateExecFlags := newFlagSet("Execution") - registerExecutionFlags(tschCreateExecFlags.Flags) - registerExecutionOutputFlags(tschCreateExecFlags.Flags) + registerExecutionFlags(tschCreateExecFlags.Flags) + registerExecutionOutputFlags(tschCreateExecFlags.Flags) + registerExecutionUploadFlags(tschCreateExecFlags.Flags) - cmdFlags[tschCreateCmd] = []*flagSet{ + cmdFlags[tschCreateCmd] = []*flagSet{ tschCreateFlags, tschCreateExecFlags, defaultAuthFlags, @@ -78,9 +80,9 @@ func tschCreateCmdInit() { defaultNetRpcFlags, } - tschCreateCmd.Flags().AddFlagSet(tschCreateFlags.Flags) - tschCreateCmd.Flags().AddFlagSet(tschCreateExecFlags.Flags) - tschCreateCmd.MarkFlagsOneRequired("exec", "command") + tschCreateCmd.Flags().AddFlagSet(tschCreateFlags.Flags) + tschCreateCmd.Flags().AddFlagSet(tschCreateExecFlags.Flags) + tschCreateCmd.MarkFlagsOneRequired("exec", "command", "upload") } func tschChangeCmdInit() { @@ -90,12 +92,13 @@ func tschChangeCmdInit() { tschChangeFlags.Flags.BoolVar(&tschChange.NoStart, "no-start", false, "Don't start the task") tschChangeFlags.Flags.BoolVar(&tschChange.NoRevert, "no-revert", false, "Don't restore the original task definition") - tschChangeExecFlags := newFlagSet("Execution") + tschChangeExecFlags := newFlagSet("Execution") - registerExecutionFlags(tschChangeExecFlags.Flags) - registerExecutionOutputFlags(tschChangeExecFlags.Flags) + registerExecutionFlags(tschChangeExecFlags.Flags) + registerExecutionOutputFlags(tschChangeExecFlags.Flags) + registerExecutionUploadFlags(tschChangeExecFlags.Flags) - cmdFlags[tschChangeCmd] = []*flagSet{ + cmdFlags[tschChangeCmd] = []*flagSet{ tschChangeFlags, tschChangeExecFlags, defaultAuthFlags, @@ -108,10 +111,10 @@ func tschChangeCmdInit() { // Constraints { - if err := tschChangeCmd.MarkFlagRequired("task"); err != nil { - panic(err) - } - tschChangeCmd.MarkFlagsOneRequired("exec", "command") + if err := tschChangeCmd.MarkFlagRequired("task"); err != nil { + panic(err) + } + tschChangeCmd.MarkFlagsOneRequired("exec", "command", "upload") } } @@ -152,14 +155,15 @@ var ( 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.`, - Args: args( - argsRpcClient("cifs", "ncacn_np:[atsvc]"), - argsOutput("smb"), - argsTask, - ), + Args: args( + argsRpcClient("cifs", "ncacn_np:[atsvc]"), + argsOutput("smb"), + argsUpload("smb"), + argsTask, + ), - Run: func(*cobra.Command, []string) { - tschDemand.Client = &rpcClient + Run: func(*cobra.Command, []string) { + tschDemand.Client = &rpcClient tschDemand.TaskPath = tschTask ctx := log.With(). @@ -180,14 +184,15 @@ var ( with an automatic start time.This method avoids directly calling SchRpcRun, and can even avoid calling SchRpcDelete by populating the DeleteExpiredTaskAfter Setting.`, - Args: args( - argsRpcClient("cifs", "ncacn_np:[atsvc]"), - argsOutput("smb"), - argsTask, - ), + Args: args( + argsRpcClient("cifs", "ncacn_np:[atsvc]"), + argsOutput("smb"), + argsUpload("smb"), + argsTask, + ), - Run: func(*cobra.Command, []string) { - tschCreate.Client = &rpcClient + Run: func(*cobra.Command, []string) { + tschCreate.Client = &rpcClient tschCreate.TaskPath = tschTask ctx := log.With(). @@ -206,14 +211,15 @@ var ( Long: `Description: The change method calls SchRpcRetrieveTask to fetch the definition of an existing task (-t), then modifies the task definition to spawn a process`, - Args: args( - argsRpcClient("cifs", "ncacn_np:[atsvc]"), - argsOutput("smb"), + Args: args( + argsRpcClient("cifs", "ncacn_np:[atsvc]"), + argsOutput("smb"), + argsUpload("smb"), - func(*cobra.Command, []string) error { - return tschexec.ValidateTaskPath(tschChange.TaskPath) - }, - ), + func(*cobra.Command, []string) error { + return tschexec.ValidateTaskPath(tschChange.TaskPath) + }, + ), Run: func(*cobra.Command, []string) { tschChange.Client = &rpcClient diff --git a/cmd/wmi.go b/cmd/wmi.go index e63feba..009fac2 100644 --- a/cmd/wmi.go +++ b/cmd/wmi.go @@ -50,12 +50,13 @@ func wmiCallCmdInit() { } func wmiProcCmdInit() { - wmiProcExecFlags := newFlagSet("Execution") + wmiProcExecFlags := newFlagSet("Execution") - registerExecutionFlags(wmiProcExecFlags.Flags) - registerExecutionOutputFlags(wmiProcExecFlags.Flags) + registerExecutionFlags(wmiProcExecFlags.Flags) + registerExecutionOutputFlags(wmiProcExecFlags.Flags) + registerExecutionUploadFlags(wmiProcExecFlags.Flags) - wmiProcExecFlags.Flags.StringVarP(&wmiProc.WorkingDirectory, "directory", "d", `C:\`, "Working directory") + wmiProcExecFlags.Flags.StringVarP(&wmiProc.WorkingDirectory, "directory", "d", `C:\`, "Working directory") cmdFlags[wmiProcCmd] = []*flagSet{ wmiProcExecFlags, @@ -117,13 +118,14 @@ var ( 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).`, - Args: args( - argsRpcClient("cifs", ""), - argsOutput("smb"), - ), + Args: args( + argsRpcClient("cifs", ""), + argsOutput("smb"), + argsUpload("smb"), + ), - Run: func(cmd *cobra.Command, args []string) { - wmiProc.Client = &rpcClient + Run: func(cmd *cobra.Command, args []string) { + wmiProc.Client = &rpcClient wmiProc.IO = exec wmiProc.Resource = "//./root/cimv2"