aboutsummaryrefslogtreecommitdiff
path: root/cmd/wmi.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/wmi.go')
-rw-r--r--cmd/wmi.go240
1 files changed, 127 insertions, 113 deletions
diff --git a/cmd/wmi.go b/cmd/wmi.go
index df047a2..74996b7 100644
--- a/cmd/wmi.go
+++ b/cmd/wmi.go
@@ -1,108 +1,111 @@
package cmd
import (
- "encoding/json"
- "fmt"
- "github.com/FalconOpsLLC/goexec/internal/exec"
- wmiexec "github.com/FalconOpsLLC/goexec/internal/exec/wmi"
- "github.com/spf13/cobra"
- "regexp"
- "strings"
+ "encoding/json"
+ "fmt"
+ "github.com/FalconOpsLLC/goexec/internal/exec"
+ wmiexec "github.com/FalconOpsLLC/goexec/internal/exec/wmi"
+ "github.com/spf13/cobra"
)
func wmiCmdInit() {
- wmiCustomCmdInit()
- wmiCmd.AddCommand(wmiCustomCmd)
- wmiProcessCmdInit()
- wmiCmd.AddCommand(wmiProcessCmd)
+ registerRpcFlags(wmiCmd)
+ wmiCallCmdInit()
+ wmiCmd.AddCommand(wmiCallCmd)
+ wmiProcessCmdInit()
+ wmiCmd.AddCommand(wmiProcessCmd)
}
-func wmiCustomCmdInit() {
- wmiCustomCmd.Flags().StringVarP(&wmiArgMethod, "method", "m", "", `WMI Method to use in the format CLASS.METHOD (i.e. "Win32_Process.Create")`)
- wmiCustomCmd.Flags().StringVarP(&wmiArgMethodArgs, "args", "A", "{}", `WMI Method argument(s) in JSON dictionary format (i.e. {"CommandLine":"calc.exe"})`)
- if err := wmiCustomCmd.MarkFlagRequired("method"); err != nil {
- panic(err)
- }
+func wmiCallCmdInit() {
+ wmiCallCmd.Flags().StringVarP(&wmi.Method, "method", "m", "", `WMI Method to call (i.e. "Create")`)
+ wmiCallCmd.Flags().StringVarP(&wmi.Class, "class", "C", "", `WMI class to instantiate (i.e. "Win32_Process")`)
+ wmiCallCmd.Flags().StringVarP(&wmi.Args, "args", "A", "{}", `WMI Method argument(s) in JSON dictionary format (i.e. {"CommandLine":"calc.exe"})`)
+ if err := wmiCallCmd.MarkFlagRequired("method"); err != nil {
+ panic(err)
+ }
}
func wmiProcessCmdInit() {
- wmiProcessCmd.Flags().StringVarP(&command, "command", "c", "", "Process command line")
- wmiProcessCmd.Flags().StringVarP(&workingDirectory, "directory", "d", `C:\`, "Working directory")
- if err := wmiProcessCmd.MarkFlagRequired("command"); err != nil {
- panic(err)
- }
+ wmiProcessCmd.Flags().StringVarP(&command, "command", "c", "", "Process command line")
+ wmiProcessCmd.Flags().StringVarP(&workingDirectory, "directory", "d", `C:\`, "Working directory")
+ if err := wmiProcessCmd.MarkFlagRequired("command"); err != nil {
+ panic(err)
+ }
}
var (
- // for custom method
- wmiArgMethod string
- wmiArgMethodArgs string
-
- wmiClass string
- wmiMethod string
- wmiMethodArgsMap map[string]any
- methodRegex = regexp.MustCompile(`^\w+\.\w+$`)
-
- wmiCmd = &cobra.Command{
- Use: "wmi",
- Short: "Establish execution via WMI",
- Args: cobra.NoArgs,
- }
- wmiCustomCmd = &cobra.Command{
- Use: "custom",
- Short: "Execute specified WMI method",
- Long: `Description:
- The custom method creates an instance of the specified WMI class (-c),
+ wmi struct {
+ Namespace string // TODO
+ Class string
+ Method string
+ Args string
+ }
+ wmiMethodArgsMap map[string]any
+
+ 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:
+ 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: func(cmd *cobra.Command, args []string) (err error) {
- if err = needsTarget("cifs")(cmd, args); err == nil {
- if wmiArgMethod != "" && !methodRegex.MatchString(wmiArgMethod) {
- return fmt.Errorf("invalid CLASS.METHOD syntax: %s", wmiArgMethod)
- }
- if err = json.Unmarshal([]byte(wmiArgMethodArgs), &wmiMethodArgsMap); err != nil {
- err = fmt.Errorf("failed to parse JSON arguments: %w", err)
- }
- }
- return
- },
- Run: func(cmd *cobra.Command, args []string) {
- module := wmiexec.Module{}
-
- connCfg := &exec.ConnectionConfig{}
- cleanCfg := &exec.CleanupConfig{}
-
- parts := strings.SplitN(wmiArgMethod, ".", 2)
- wmiClass = parts[0]
- wmiMethod = parts[1]
-
- execCfg := &exec.ExecutionConfig{
- ExecutableName: executable,
- ExecutableArgs: executableArgs,
- ExecutionMethod: wmiexec.MethodCustom,
- ExecutionMethodConfig: wmiexec.MethodCustomConfig{
- Class: wmiClass,
- Method: wmiMethod,
- Arguments: wmiMethodArgsMap,
- },
- }
- if err := module.Connect(log.WithContext(ctx), creds, target, connCfg); err != nil {
- log.Fatal().Err(err).Msg("Connection failed")
- } else if err := module.Exec(log.WithContext(ctx), execCfg); err != nil {
- log.Fatal().Err(err).Msg("Execution failed")
- } else if err := module.Cleanup(log.WithContext(ctx), cleanCfg); err != nil {
- log.Error().Err(err).Msg("Cleanup failed")
- }
- },
- }
-
- wmiProcessCmd = &cobra.Command{
- Use: "proc",
- Short: "Start a Windows process",
- Long: `Description:
+ Args: needs(needsTarget("cifs"), needsRpcTarget("cifs"), func(cmd *cobra.Command, args []string) (err error) {
+ if err = json.Unmarshal([]byte(wmi.Args), &wmiMethodArgsMap); err != nil {
+ err = fmt.Errorf("parse JSON arguments: %w", err)
+ }
+ return
+ }),
+ Run: func(cmd *cobra.Command, args []string) {
+
+ executor := wmiexec.Module{}
+ cleanCfg := &exec.CleanupConfig{} // TODO
+ connCfg := &exec.ConnectionConfig{
+ ConnectionMethod: exec.ConnectionMethodDCE,
+ ConnectionMethodConfig: dceConfig,
+ }
+
+ execCfg := &exec.ExecutionConfig{
+ ExecutableName: executable,
+ ExecutableArgs: executableArgs,
+ ExecutionMethod: wmiexec.MethodCall,
+ ExecutionMethodConfig: wmiexec.MethodCallConfig{
+ Class: wmi.Class,
+ Method: wmi.Method,
+ Arguments: wmiMethodArgsMap,
+ },
+ }
+
+ ctx = log.With().
+ Str("module", "wmi").
+ Str("method", "proc").
+ Logger().WithContext(ctx)
+
+ if err := executor.Connect(ctx, creds, target, connCfg); err != nil {
+ log.Fatal().Err(err).Msg("Connection failed")
+ }
+ defer func() {
+ if err := executor.Cleanup(ctx, cleanCfg); err != nil {
+ log.Error().Err(err).Msg("Cleanup failed")
+ }
+ }()
+ if err := executor.Exec(ctx, execCfg); err != nil {
+ log.Error().Err(err).Msg("Execution failed")
+ }
+ },
+ }
+
+ wmiProcessCmd = &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).
@@ -110,31 +113,42 @@ References:
References:
https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/create-method-in-class-win32-process
`,
- Args: needsTarget("cifs"),
- Run: func(cmd *cobra.Command, args []string) {
- log = log.With().Str("module", "wmi").Logger()
-
- module := wmiexec.Module{}
- connCfg := &exec.ConnectionConfig{}
- cleanCfg := &exec.CleanupConfig{}
-
- execCfg := &exec.ExecutionConfig{
- ExecutableName: executable,
- ExecutableArgs: executableArgs,
- ExecutionMethod: wmiexec.MethodProcess,
-
- ExecutionMethodConfig: wmiexec.MethodProcessConfig{
- Command: command,
- WorkingDirectory: workingDirectory,
- },
- }
- if err := module.Connect(log.WithContext(ctx), creds, target, connCfg); err != nil {
- log.Fatal().Err(err).Msg("Connection failed")
- } else if err := module.Exec(log.WithContext(ctx), execCfg); err != nil {
- log.Fatal().Err(err).Msg("Execution failed")
- } else if err := module.Cleanup(log.WithContext(ctx), cleanCfg); err != nil {
- log.Error().Err(err).Msg("Cleanup failed")
- }
- },
- }
+ Args: needs(needsTarget("cifs"), needsRpcTarget("cifs")),
+ Run: func(cmd *cobra.Command, args []string) {
+
+ executor := wmiexec.Module{}
+ cleanCfg := &exec.CleanupConfig{} // TODO
+ connCfg := &exec.ConnectionConfig{
+ ConnectionMethod: exec.ConnectionMethodDCE,
+ ConnectionMethodConfig: dceConfig,
+ }
+ execCfg := &exec.ExecutionConfig{
+ ExecutableName: executable,
+ ExecutableArgs: executableArgs,
+ ExecutionMethod: wmiexec.MethodProcess,
+
+ ExecutionMethodConfig: wmiexec.MethodProcessConfig{
+ Command: command,
+ WorkingDirectory: workingDirectory,
+ },
+ }
+
+ ctx = log.With().
+ Str("module", "wmi").
+ Str("method", "proc").
+ Logger().WithContext(ctx)
+
+ if err := executor.Connect(ctx, creds, target, connCfg); err != nil {
+ log.Fatal().Err(err).Msg("Connection failed")
+ }
+ defer func() {
+ if err := executor.Cleanup(ctx, cleanCfg); err != nil {
+ log.Error().Err(err).Msg("Cleanup failed")
+ }
+ }()
+ if err := executor.Exec(ctx, execCfg); err != nil {
+ log.Error().Err(err).Msg("Execution failed")
+ }
+ },
+ }
)