aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryan McNulty <bryanmcnulty@protonmail.com>2025-04-26 05:12:13 -0500
committerBryan McNulty <bryanmcnulty@protonmail.com>2025-04-26 05:12:13 -0500
commit9d2a16e16d21bcfed1da89001b095776261d790b (patch)
tree1a48264072a8fcd0ad2ae78d96db53b7ff91d727
parente860eced799e64ebff56012a7655155d26b3a2a2 (diff)
downloadgoexec-9d2a16e16d21bcfed1da89001b095776261d790b.tar.gz
goexec-9d2a16e16d21bcfed1da89001b095776261d790b.zip
Fixed some linter issues
-rw-r--r--cmd/dcom.go110
-rw-r--r--cmd/root.go506
-rw-r--r--pkg/goexec/scmr/scmr.go8
-rw-r--r--pkg/goexec/tsch/task/action.go2
-rw-r--r--pkg/goexec/wmi/module.go236
5 files changed, 430 insertions, 432 deletions
diff --git a/cmd/dcom.go b/cmd/dcom.go
index 89fac18..1a8d031 100644
--- a/cmd/dcom.go
+++ b/cmd/dcom.go
@@ -1,80 +1,80 @@
package cmd
import (
- "context"
- "github.com/FalconOpsLLC/goexec/pkg/goexec"
- dcomexec "github.com/FalconOpsLLC/goexec/pkg/goexec/dcom"
- "github.com/oiweiwei/go-msrpc/ssp/gssapi"
- "github.com/spf13/cobra"
+ "context"
+ "github.com/FalconOpsLLC/goexec/pkg/goexec"
+ dcomexec "github.com/FalconOpsLLC/goexec/pkg/goexec/dcom"
+ "github.com/oiweiwei/go-msrpc/ssp/gssapi"
+ "github.com/spf13/cobra"
)
func dcomCmdInit() {
- cmdFlags[dcomCmd] = []*flagSet{
- defaultAuthFlags,
- defaultLogFlags,
- defaultNetRpcFlags,
- }
- dcomMmcCmdInit()
+ cmdFlags[dcomCmd] = []*flagSet{
+ defaultAuthFlags,
+ defaultLogFlags,
+ defaultNetRpcFlags,
+ }
+ dcomMmcCmdInit()
- dcomCmd.PersistentFlags().AddFlagSet(defaultAuthFlags.Flags)
- dcomCmd.PersistentFlags().AddFlagSet(defaultLogFlags.Flags)
- dcomCmd.PersistentFlags().AddFlagSet(defaultNetRpcFlags.Flags)
- dcomCmd.AddCommand(dcomMmcCmd)
+ dcomCmd.PersistentFlags().AddFlagSet(defaultAuthFlags.Flags)
+ dcomCmd.PersistentFlags().AddFlagSet(defaultLogFlags.Flags)
+ dcomCmd.PersistentFlags().AddFlagSet(defaultNetRpcFlags.Flags)
+ dcomCmd.AddCommand(dcomMmcCmd)
}
func dcomMmcCmdInit() {
- dcomMmcExecFlags := newFlagSet("Execution")
+ dcomMmcExecFlags := newFlagSet("Execution")
- registerExecutionFlags(dcomMmcExecFlags.Flags)
- registerExecutionOutputFlags(dcomMmcExecFlags.Flags)
+ 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.Flags.StringVar(&dcomMmc.WorkingDirectory, "directory", `C:\`, "Working `directory`")
+ dcomMmcExecFlags.Flags.StringVar(&dcomMmc.WindowState, "window", "Minimized", "Window state")
- cmdFlags[dcomMmcCmd] = []*flagSet{
- dcomMmcExecFlags,
- defaultAuthFlags,
- defaultLogFlags,
- defaultNetRpcFlags,
- }
+ cmdFlags[dcomMmcCmd] = []*flagSet{
+ dcomMmcExecFlags,
+ defaultAuthFlags,
+ defaultLogFlags,
+ defaultNetRpcFlags,
+ }
- dcomMmcCmd.Flags().AddFlagSet(dcomMmcExecFlags.Flags)
+ dcomMmcCmd.Flags().AddFlagSet(dcomMmcExecFlags.Flags)
}
var (
- dcomMmc dcomexec.DcomMmc
+ dcomMmc dcomexec.DcomMmc
- dcomCmd = &cobra.Command{
- Use: "dcom",
- Short: "Execute with Distributed Component Object Model (MS-DCOM)",
- Long: `Description:
+ dcomCmd = &cobra.Command{
+ Use: "dcom",
+ Short: "Execute with Distributed Component Object Model (MS-DCOM)",
+ Long: `Description:
The dcom module uses exposed Distributed Component Object Model (DCOM) objects to spawn processes.`,
- GroupID: "module",
- Args: cobra.NoArgs,
- }
+ GroupID: "module",
+ Args: cobra.NoArgs,
+ }
- dcomMmcCmd = &cobra.Command{
- Use: "mmc [target]",
- Short: "Execute with the DCOM MMC20.Application object",
- Long: `Description:
+ dcomMmcCmd = &cobra.Command{
+ Use: "mmc [target]",
+ Short: "Execute with the DCOM MMC20.Application object",
+ 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("host"),
- argsOutput("smb"),
- ),
- Run: func(cmd *cobra.Command, args []string) {
- dcomMmc.Dcom.Client = &rpcClient
- dcomMmc.IO = exec
+ Args: args(
+ argsRpcClient("host"),
+ argsOutput("smb"),
+ ),
+ Run: func(cmd *cobra.Command, args []string) {
+ dcomMmc.Client = &rpcClient
+ dcomMmc.IO = exec
- ctx := log.With().
- Str("module", "dcom").
- Str("method", "mmc").
- Logger().WithContext(gssapi.NewSecurityContext(context.Background()))
+ ctx := log.With().
+ Str("module", "dcom").
+ Str("method", "mmc").
+ Logger().WithContext(gssapi.NewSecurityContext(context.Background()))
- if err := goexec.ExecuteCleanMethod(ctx, &dcomMmc, &exec); err != nil {
- log.Fatal().Err(err).Msg("Operation failed")
- }
- },
- }
+ if err := goexec.ExecuteCleanMethod(ctx, &dcomMmc, &exec); err != nil {
+ log.Fatal().Err(err).Msg("Operation failed")
+ }
+ },
+ }
)
diff --git a/cmd/root.go b/cmd/root.go
index 96173a4..12f3e19 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -1,26 +1,26 @@
package cmd
import (
- "fmt"
- "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/google/uuid"
- "github.com/oiweiwei/go-msrpc/ssp"
- "github.com/oiweiwei/go-msrpc/ssp/gssapi"
- "github.com/rs/zerolog"
- "github.com/spf13/cobra"
- "github.com/spf13/pflag"
- "golang.org/x/term"
- "io"
- "os"
- "runtime/pprof"
+ "fmt"
+ "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/google/uuid"
+ "github.com/oiweiwei/go-msrpc/ssp"
+ "github.com/oiweiwei/go-msrpc/ssp/gssapi"
+ "github.com/rs/zerolog"
+ "github.com/spf13/cobra"
+ "github.com/spf13/pflag"
+ "golang.org/x/term"
+ "io"
+ "os"
+ "runtime/pprof"
)
type flagSet struct {
- Label string
- Flags *pflag.FlagSet
+ Label string
+ Flags *pflag.FlagSet
}
const helpTemplate = `Usage:{{if .Runnable}}
@@ -52,55 +52,55 @@ Use "{{.CommandPath}} [command] --help" for more information about a command.{{e
`
var (
- cmdFlags = make(map[*cobra.Command][]*flagSet)
-
- defaultAuthFlags, defaultLogFlags, defaultNetRpcFlags *flagSet
-
- returnCode int
- toClose []io.Closer
-
- // === IO ===
- stageFilePath string
- outputMethod string
- outputPath string
- // ==========
-
- // === Logging ===
- logJson bool // Log output in JSON lines
- logDebug bool // Output debug log messages
- logQuiet bool // Suppress logging output
- logOutput string // Log output file
- logLevel zerolog.Level = zerolog.InfoLevel
- logFile io.WriteCloser = os.Stderr
- log zerolog.Logger
- // ===============
-
- // === Network ===
- proxy string
- rpcClient dce.Client
- smbClient smb.Client
- // ===============
-
- // === Resource profiling ===
- cpuProfile string
- memProfile string
- cpuProfileFile io.WriteCloser
- memProfileFile io.WriteCloser
- // ==========================
-
- exec = goexec.ExecutionIO{
- Input: new(goexec.ExecutionInput),
- Output: new(goexec.ExecutionOutput),
- }
-
- adAuthOpts *adauth.Options
- credential *adauth.Credential
- target *adauth.Target
-
- rootCmd = &cobra.Command{
- Use: "goexec",
- Short: `goexec - Windows remote execution multitool`,
- Long: `
+ cmdFlags = make(map[*cobra.Command][]*flagSet)
+
+ defaultAuthFlags, defaultLogFlags, defaultNetRpcFlags *flagSet
+
+ returnCode int
+ toClose []io.Closer
+
+ // === IO ===
+ stageFilePath string
+ outputMethod string
+ outputPath string
+ // ==========
+
+ // === Logging ===
+ logJson bool // Log output in JSON lines
+ logDebug bool // Output debug log messages
+ logQuiet bool // Suppress logging output
+ logOutput string // Log output file
+ logLevel = zerolog.InfoLevel
+ logFile io.WriteCloser = os.Stderr
+ log zerolog.Logger
+ // ===============
+
+ // === Network ===
+ proxy string
+ rpcClient dce.Client
+ smbClient smb.Client
+ // ===============
+
+ // === Resource profiling ===
+ cpuProfile string
+ memProfile string
+ cpuProfileFile io.WriteCloser
+ memProfileFile io.WriteCloser
+ // ==========================
+
+ exec = goexec.ExecutionIO{
+ Input: new(goexec.ExecutionInput),
+ Output: new(goexec.ExecutionOutput),
+ }
+
+ adAuthOpts *adauth.Options
+ credential *adauth.Credential
+ target *adauth.Target
+
+ rootCmd = &cobra.Command{
+ Use: "goexec",
+ Short: `goexec - Windows remote execution multitool`,
+ Long: `
___ ___ ___ _ _ ___ ___
| . | . | -_|_'_| -_| _|
|_ |___|___|_,_|___|___|
@@ -113,200 +113,200 @@ Authors: FalconOps LLC (@FalconOpsLLC),
while providing an extremely flexible CLI and a strong focus on OPSEC.
`,
- PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) {
-
- // Parse logging options
- {
- if logOutput != "" {
- logFile, err = os.OpenFile(logOutput, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
- if err != nil {
- return
- }
- toClose = append(toClose, logFile)
- logJson = true
- }
- if logQuiet {
- logLevel = zerolog.ErrorLevel
- } else if logDebug {
- logLevel = zerolog.DebugLevel
- }
- if logJson {
- log = zerolog.New(logFile).With().Timestamp().Logger()
- } else {
- log = zerolog.New(zerolog.ConsoleWriter{Out: logFile}).With().Timestamp().Logger()
- }
- log = log.Level(logLevel)
- }
-
- // CPU / memory profiling
- {
- if cpuProfile != "" {
- if cpuProfileFile, err = os.OpenFile(cpuProfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644); err != nil {
- log.Error().Err(err).Msg("Failed to open CPU profile for writing")
- return
- }
- toClose = append(toClose, cpuProfileFile)
-
- if err = pprof.StartCPUProfile(cpuProfileFile); err != nil {
- log.Error().Err(err).Msg("Failed to start CPU profile")
- return
- }
- }
- if memProfile != "" {
- if memProfileFile, err = os.OpenFile(memProfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644); err != nil {
- log.Error().Err(err).Msg("Failed to open memory profile for writing")
- return
- }
- toClose = append(toClose, memProfileFile)
- }
- }
-
- if proxy != "" {
- rpcClient.Proxy = proxy
- smbClient.Proxy = proxy
- }
-
- if outputPath != "" {
- if outputMethod == "smb" {
- if exec.Output.RemotePath == "" {
- exec.Output.RemotePath = `C:\Windows\Temp\` + uuid.NewString()
- }
- exec.Output.Provider = &smb.OutputFileFetcher{
- Client: &smbClient,
- Share: `ADMIN$`, // TODO: dynamic
- SharePath: `C:\Windows`,
- File: exec.Output.RemotePath,
- DeleteOutputFile: !exec.Output.NoDelete,
- }
- }
- }
- return
- },
-
- PersistentPostRun: func(cmd *cobra.Command, args []string) {
-
- if memProfileFile != nil {
- if err := pprof.WriteHeapProfile(memProfileFile); err != nil {
- log.Error().Err(err).Msg("Failed to write memory profile")
- return
- }
- }
-
- if cpuProfileFile != nil {
- pprof.StopCPUProfile()
- }
-
- for _, c := range toClose {
- if c != nil {
- if err := c.Close(); err != nil {
- log.Warn().Err(err).Msg("Failed to close stream")
- }
- }
- }
-
- if exec.Input != nil && exec.Input.StageFile != nil {
- if err := exec.Input.StageFile.Close(); err != nil {
- // ...
- }
- }
- },
- }
+ PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) {
+
+ // Parse logging options
+ {
+ if logOutput != "" {
+ logFile, err = os.OpenFile(logOutput, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
+ if err != nil {
+ return
+ }
+ toClose = append(toClose, logFile)
+ logJson = true
+ }
+ if logQuiet {
+ logLevel = zerolog.ErrorLevel
+ } else if logDebug {
+ logLevel = zerolog.DebugLevel
+ }
+ if logJson {
+ log = zerolog.New(logFile).With().Timestamp().Logger()
+ } else {
+ log = zerolog.New(zerolog.ConsoleWriter{Out: logFile}).With().Timestamp().Logger()
+ }
+ log = log.Level(logLevel)
+ }
+
+ // CPU / memory profiling
+ {
+ if cpuProfile != "" {
+ if cpuProfileFile, err = os.OpenFile(cpuProfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644); err != nil {
+ log.Error().Err(err).Msg("Failed to open CPU profile for writing")
+ return
+ }
+ toClose = append(toClose, cpuProfileFile)
+
+ if err = pprof.StartCPUProfile(cpuProfileFile); err != nil {
+ log.Error().Err(err).Msg("Failed to start CPU profile")
+ return
+ }
+ }
+ if memProfile != "" {
+ if memProfileFile, err = os.OpenFile(memProfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644); err != nil {
+ log.Error().Err(err).Msg("Failed to open memory profile for writing")
+ return
+ }
+ toClose = append(toClose, memProfileFile)
+ }
+ }
+
+ if proxy != "" {
+ rpcClient.Proxy = proxy
+ smbClient.Proxy = proxy
+ }
+
+ if outputPath != "" {
+ if outputMethod == "smb" {
+ if exec.Output.RemotePath == "" {
+ exec.Output.RemotePath = `C:\Windows\Temp\` + uuid.NewString()
+ }
+ exec.Output.Provider = &smb.OutputFileFetcher{
+ Client: &smbClient,
+ Share: `ADMIN$`, // TODO: dynamic
+ SharePath: `C:\Windows`,
+ File: exec.Output.RemotePath,
+ DeleteOutputFile: !exec.Output.NoDelete,
+ }
+ }
+ }
+ return
+ },
+
+ PersistentPostRun: func(cmd *cobra.Command, args []string) {
+
+ if memProfileFile != nil {
+ if err := pprof.WriteHeapProfile(memProfileFile); err != nil {
+ log.Error().Err(err).Msg("Failed to write memory profile")
+ return
+ }
+ }
+
+ if cpuProfileFile != nil {
+ pprof.StopCPUProfile()
+ }
+
+ for _, c := range toClose {
+ if c != nil {
+ if err := c.Close(); err != nil {
+ log.Warn().Err(err).Msg("Failed to close stream")
+ }
+ }
+ }
+
+ if exec.Input != nil && exec.Input.StageFile != nil {
+ if err := exec.Input.StageFile.Close(); err != nil {
+ // ...
+ }
+ }
+ },
+ }
)
func newFlagSet(name string) *flagSet {
- flags := pflag.NewFlagSet(name, pflag.ExitOnError)
- flags.SortFlags = false
- return &flagSet{
- Label: name,
- Flags: flags,
- }
+ flags := pflag.NewFlagSet(name, pflag.ExitOnError)
+ flags.SortFlags = false
+ return &flagSet{
+ Label: name,
+ Flags: flags,
+ }
}
func init() {
- // Auth init
- {
- gssapi.AddMechanism(ssp.SPNEGO)
- gssapi.AddMechanism(ssp.NTLM)
- gssapi.AddMechanism(ssp.KRB5)
- }
-
- // CPU / Memory profiling
- {
- rootCmd.PersistentFlags().StringVar(&cpuProfile, "cpu-profile", "", "Write CPU profile to `file`")
- rootCmd.PersistentFlags().StringVar(&memProfile, "mem-profile", "", "Write memory profile to `file`")
-
- if err := rootCmd.PersistentFlags().MarkHidden("cpu-profile"); err != nil {
- panic(err)
- }
- if err := rootCmd.PersistentFlags().MarkHidden("mem-profile"); err != nil {
- panic(err)
- }
- }
-
- // Cobra init
- {
- cobra.EnableCommandSorting = false
- {
- defaultNetRpcFlags = newFlagSet("Network")
- registerNetworkFlags(defaultNetRpcFlags.Flags)
- }
- {
- defaultLogFlags = newFlagSet("Logging")
- registerLoggingFlags(defaultLogFlags.Flags)
- }
- {
- defaultAuthFlags = newFlagSet("Authentication")
- adAuthOpts = &adauth.Options{
- Debug: log.Debug().Msgf,
- }
- adAuthOpts.RegisterFlags(defaultAuthFlags.Flags)
- }
-
- modules := &cobra.Group{
- ID: "module",
- Title: "Execution Commands:",
- }
- rootCmd.AddGroup(modules)
-
- cmdFlags[rootCmd] = []*flagSet{
- defaultLogFlags,
- defaultAuthFlags,
- }
-
- cobra.AddTemplateFunc("flags", func(fs *pflag.FlagSet) string {
- if width, _, err := term.GetSize(int(os.Stdout.Fd())); err == nil {
- return fs.FlagUsagesWrapped(width - 1)
- }
- return fs.FlagUsagesWrapped(80 - 1)
- })
-
- cobra.AddTemplateFunc("cmdFlags", func(cmd *cobra.Command) []*flagSet {
- return cmdFlags[cmd]
- })
-
- rootCmd.InitDefaultVersionFlag()
- rootCmd.InitDefaultHelpCmd()
- rootCmd.SetHelpTemplate("{{if (ne .Long \"\")}}{{.Long}}\n\n{{end}}" + helpTemplate)
- rootCmd.SetUsageTemplate(helpTemplate)
-
- // Modules init
- {
- dcomCmdInit()
- rootCmd.AddCommand(dcomCmd)
- wmiCmdInit()
- rootCmd.AddCommand(wmiCmd)
- scmrCmdInit()
- rootCmd.AddCommand(scmrCmd)
- tschCmdInit()
- rootCmd.AddCommand(tschCmd)
- }
- }
+ // Auth init
+ {
+ gssapi.AddMechanism(ssp.SPNEGO)
+ gssapi.AddMechanism(ssp.NTLM)
+ gssapi.AddMechanism(ssp.KRB5)
+ }
+
+ // CPU / Memory profiling
+ {
+ rootCmd.PersistentFlags().StringVar(&cpuProfile, "cpu-profile", "", "Write CPU profile to `file`")
+ rootCmd.PersistentFlags().StringVar(&memProfile, "mem-profile", "", "Write memory profile to `file`")
+
+ if err := rootCmd.PersistentFlags().MarkHidden("cpu-profile"); err != nil {
+ panic(err)
+ }
+ if err := rootCmd.PersistentFlags().MarkHidden("mem-profile"); err != nil {
+ panic(err)
+ }
+ }
+
+ // Cobra init
+ {
+ cobra.EnableCommandSorting = false
+ {
+ defaultNetRpcFlags = newFlagSet("Network")
+ registerNetworkFlags(defaultNetRpcFlags.Flags)
+ }
+ {
+ defaultLogFlags = newFlagSet("Logging")
+ registerLoggingFlags(defaultLogFlags.Flags)
+ }
+ {
+ defaultAuthFlags = newFlagSet("Authentication")
+ adAuthOpts = &adauth.Options{
+ Debug: log.Debug().Msgf,
+ }
+ adAuthOpts.RegisterFlags(defaultAuthFlags.Flags)
+ }
+
+ modules := &cobra.Group{
+ ID: "module",
+ Title: "Execution Commands:",
+ }
+ rootCmd.AddGroup(modules)
+
+ cmdFlags[rootCmd] = []*flagSet{
+ defaultLogFlags,
+ defaultAuthFlags,
+ }
+
+ cobra.AddTemplateFunc("flags", func(fs *pflag.FlagSet) string {
+ if width, _, err := term.GetSize(int(os.Stdout.Fd())); err == nil {
+ return fs.FlagUsagesWrapped(width - 1)
+ }
+ return fs.FlagUsagesWrapped(80 - 1)
+ })
+
+ cobra.AddTemplateFunc("cmdFlags", func(cmd *cobra.Command) []*flagSet {
+ return cmdFlags[cmd]
+ })
+
+ rootCmd.InitDefaultVersionFlag()
+ rootCmd.InitDefaultHelpCmd()
+ rootCmd.SetHelpTemplate("{{if (ne .Long \"\")}}{{.Long}}\n\n{{end}}" + helpTemplate)
+ rootCmd.SetUsageTemplate(helpTemplate)
+
+ // Modules init
+ {
+ dcomCmdInit()
+ rootCmd.AddCommand(dcomCmd)
+ wmiCmdInit()
+ rootCmd.AddCommand(wmiCmd)
+ scmrCmdInit()
+ rootCmd.AddCommand(scmrCmd)
+ tschCmdInit()
+ rootCmd.AddCommand(tschCmd)
+ }
+ }
}
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/pkg/goexec/scmr/scmr.go b/pkg/goexec/scmr/scmr.go
index 4831ac7..696415b 100644
--- a/pkg/goexec/scmr/scmr.go
+++ b/pkg/goexec/scmr/scmr.go
@@ -42,10 +42,10 @@ const (
SERVICE_STOPPED uint32 = 0x00000001
*/
- ServiceDeleteAccess uint32 = ServiceDelete
- ServiceModifyAccess uint32 = ServiceQueryConfig | ServiceChangeConfig | ServiceStop | ServiceStart | ServiceDelete
- ServiceCreateAccess uint32 = ScManagerCreateService | ServiceStart | ServiceStop | ServiceDelete
- ServiceAllAccess uint32 = ServiceCreateAccess | ServiceModifyAccess
+ ServiceDeleteAccess = ServiceDelete
+ ServiceModifyAccess = ServiceQueryConfig | ServiceChangeConfig | ServiceStop | ServiceStart | ServiceDelete
+ ServiceCreateAccess = ScManagerCreateService | ServiceStart | ServiceStop | ServiceDelete
+ ServiceAllAccess = ServiceCreateAccess | ServiceModifyAccess
)
type service struct {
diff --git a/pkg/goexec/tsch/task/action.go b/pkg/goexec/tsch/task/action.go
index de6c29f..903c633 100644
--- a/pkg/goexec/tsch/task/action.go
+++ b/pkg/goexec/tsch/task/action.go
@@ -85,7 +85,7 @@ type ShowMessageAction struct {
// NamedValues holds zero or more <Value name="…">…</Value> entries.
type NamedValues struct {
- XMLName xml.Name `xml:"HeaderFields"`
+ XMLName xml.Name //`xml:"HeaderFields"`
Value []NamedValue `xml:"Value"`
}
diff --git a/pkg/goexec/wmi/module.go b/pkg/goexec/wmi/module.go
index 90bbaa8..0aedd7e 100644
--- a/pkg/goexec/wmi/module.go
+++ b/pkg/goexec/wmi/module.go
@@ -1,141 +1,139 @@
package wmiexec
import (
- "context"
- "errors"
- "fmt"
- "github.com/FalconOpsLLC/goexec/pkg/goexec"
- "github.com/FalconOpsLLC/goexec/pkg/goexec/dce"
- "github.com/oiweiwei/go-msrpc/dcerpc"
- "github.com/oiweiwei/go-msrpc/msrpc/dcom"
- "github.com/oiweiwei/go-msrpc/msrpc/dcom/iactivation/v0"
- "github.com/oiweiwei/go-msrpc/msrpc/dcom/wmi"
- "github.com/oiweiwei/go-msrpc/msrpc/dcom/wmi/iwbemlevel1login/v0"
- "github.com/oiweiwei/go-msrpc/msrpc/dcom/wmi/iwbemservices/v0"
- "github.com/oiweiwei/go-msrpc/msrpc/dcom/wmio/query"
- "github.com/rs/zerolog"
+ "context"
+ "errors"
+ "fmt"
+ "github.com/FalconOpsLLC/goexec/pkg/goexec"
+ "github.com/FalconOpsLLC/goexec/pkg/goexec/dce"
+ "github.com/oiweiwei/go-msrpc/dcerpc"
+ "github.com/oiweiwei/go-msrpc/msrpc/dcom"
+ "github.com/oiweiwei/go-msrpc/msrpc/dcom/iactivation/v0"
+ "github.com/oiweiwei/go-msrpc/msrpc/dcom/wmi"
+ "github.com/oiweiwei/go-msrpc/msrpc/dcom/wmi/iwbemlevel1login/v0"
+ "github.com/oiweiwei/go-msrpc/msrpc/dcom/wmi/iwbemservices/v0"
+ "github.com/oiweiwei/go-msrpc/msrpc/dcom/wmio/query"
+ "github.com/rs/zerolog"
)
const (
- ModuleName = "WMI"
- DefaultEndpoint = "ncacn_ip_tcp:[135]"
+ ModuleName = "WMI"
+ DefaultEndpoint = "ncacn_ip_tcp:[135]"
)
type Wmi struct {
- goexec.Cleaner
- Client *dce.Client
+ goexec.Cleaner
+ Client *dce.Client
- Resource string
+ Resource string
- servicesClient iwbemservices.ServicesClient
+ servicesClient iwbemservices.ServicesClient
}
func (m *Wmi) Connect(ctx context.Context) (err error) {
- if err = m.Client.Connect(ctx); err == nil {
- m.AddCleaners(m.Client.Close)
- }
- return
+ if err = m.Client.Connect(ctx); err == nil {
+ m.AddCleaners(m.Client.Close)
+ }
+ return
}
func (m *Wmi) Init(ctx context.Context) (err error) {
- log := zerolog.Ctx(ctx).With().
- Str("module", ModuleName).Logger()
-
- if m.Client == nil || m.Client.Dce() == nil {
- return errors.New("DCE connection not initialized")
- }
-
- actClient, err := iactivation.NewActivationClient(ctx, m.Client.Dce())
- if err != nil {
- log.Error().Err(err).Msg("Failed to initialize IActivation client")
- return fmt.Errorf("create IActivation client: %w", err)
- }
-
- actResponse, err := actClient.RemoteActivation(ctx, &iactivation.RemoteActivationRequest{
- ORPCThis: ORPCThis,
- ClassID: wmi.Level1LoginClassID.GUID(),
- IIDs: []*dcom.IID{iwbemlevel1login.Level1LoginIID},
- RequestedProtocolSequences: []uint16{ProtocolSequenceRPC}, // FEATURE: Named pipe support?
- })
- if err != nil {
- log.Error().Err(err).Msg("Failed to activate remote object")
- return fmt.Errorf("request remote activation: %w", err)
- }
- if actResponse.HResult != 0 {
- return fmt.Errorf("remote activation failed with code %d", actResponse.HResult)
- }
-
- log.Info().Msg("Remote activation succeeded")
-
- var newOpts []dcerpc.Option
-
- for _, bind := range actResponse.OXIDBindings.GetStringBindings() {
- stringBinding, err := dcerpc.ParseStringBinding("ncacn_ip_tcp:" + bind.NetworkAddr) // TODO: try bind.String()
-
- if err != nil {
- log.Debug().Err(err).Msg("Failed to parse string binding")
- continue
- }
- stringBinding.NetworkAddress = m.Client.Target.AddressWithoutPort()
- newOpts = append(newOpts, dcerpc.WithEndpoint(stringBinding.String()))
- }
-
- if err = m.Client.Reconnect(ctx, newOpts...); err != nil {
- log.Error().Err(err).Msg("Failed to connect to remote instance")
- return fmt.Errorf("connect remote instance: %w", err)
- }
-
- log.Info().Msg("Connected to remote instance")
-
- ipid := actResponse.InterfaceData[0].GetStandardObjectReference().Std.IPID
- loginClient, err := iwbemlevel1login.NewLevel1LoginClient(ctx, m.Client.Dce(), dcom.WithIPID(ipid))
-
- if err != nil {
- log.Error().Err(err).Msg("Failed to create IWbemLevel1Login client")
- return fmt.Errorf("create IWbemLevel1Login client: %w", err)
- }
-
- login, err := loginClient.NTLMLogin(ctx, &iwbemlevel1login.NTLMLoginRequest{
- This: ORPCThis,
- NetworkResource: m.Resource,
- })
-
- log.Info().Msg("Completed NTLMLogin operation")
-
- if err != nil {
- log.Error().Err(err).Msg("Failed to login on remote instance")
- return fmt.Errorf("login: IWbemLevel1Login::NTLMLogin: %w", err)
- }
-
- ipid = login.Namespace.InterfacePointer().IPID()
- m.servicesClient, err = iwbemservices.NewServicesClient(ctx, m.Client.Dce(), dcom.WithIPID(ipid))
-
- if err != nil {
- log.Error().Err(err).Msg("Failed to create services client")
- return fmt.Errorf("create IWbemServices client: %w", err)
- }
-
- log.Info().Msg("Initialized services client")
-
- return
+ log := zerolog.Ctx(ctx).With().
+ Str("module", ModuleName).Logger()
+
+ if m.Client == nil || m.Client.Dce() == nil {
+ return errors.New("DCE connection not initialized")
+ }
+
+ actClient, err := iactivation.NewActivationClient(ctx, m.Client.Dce())
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to initialize IActivation client")
+ return fmt.Errorf("create IActivation client: %w", err)
+ }
+
+ actResponse, err := actClient.RemoteActivation(ctx, &iactivation.RemoteActivationRequest{
+ ORPCThis: ORPCThis,
+ ClassID: wmi.Level1LoginClassID.GUID(),
+ IIDs: []*dcom.IID{iwbemlevel1login.Level1LoginIID},
+ RequestedProtocolSequences: []uint16{ProtocolSequenceRPC}, // FEATURE: Named pipe support?
+ })
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to activate remote object")
+ return fmt.Errorf("request remote activation: %w", err)
+ }
+ if actResponse.HResult != 0 {
+ return fmt.Errorf("remote activation failed with code %d", actResponse.HResult)
+ }
+
+ log.Info().Msg("Remote activation succeeded")
+
+ var newOpts []dcerpc.Option
+
+ for _, bind := range actResponse.OXIDBindings.GetStringBindings() {
+ stringBinding, err := dcerpc.ParseStringBinding("ncacn_ip_tcp:" + bind.NetworkAddr) // TODO: try bind.String()
+
+ if err != nil {
+ log.Debug().Err(err).Msg("Failed to parse string binding")
+ continue
+ }
+ stringBinding.NetworkAddress = m.Client.Target.AddressWithoutPort()
+ newOpts = append(newOpts, dcerpc.WithEndpoint(stringBinding.String()))
+ }
+
+ if err = m.Client.Reconnect(ctx, newOpts...); err != nil {
+ log.Error().Err(err).Msg("Failed to connect to remote instance")
+ return fmt.Errorf("connect remote instance: %w", err)
+ }
+
+ log.Info().Msg("Connected to remote instance")
+
+ ipid := actResponse.InterfaceData[0].GetStandardObjectReference().Std.IPID
+ loginClient, err := iwbemlevel1login.NewLevel1LoginClient(ctx, m.Client.Dce(), dcom.WithIPID(ipid))
+
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to create IWbemLevel1Login client")
+ return fmt.Errorf("create IWbemLevel1Login client: %w", err)
+ }
+
+ login, err := loginClient.NTLMLogin(ctx, &iwbemlevel1login.NTLMLoginRequest{
+ This: ORPCThis,
+ NetworkResource: m.Resource,
+ })
+
+ log.Info().Msg("Completed NTLMLogin operation")
+
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to login on remote instance")
+ return fmt.Errorf("login: IWbemLevel1Login::NTLMLogin: %w", err)
+ }
+
+ ipid = login.Namespace.InterfacePointer().IPID()
+ m.servicesClient, err = iwbemservices.NewServicesClient(ctx, m.Client.Dce(), dcom.WithIPID(ipid))
+
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to create services client")
+ return fmt.Errorf("create IWbemServices client: %w", err)
+ }
+
+ log.Info().Msg("Initialized services client")
+
+ return
}
-func (m *Wmi) query(ctx context.Context, class, method string, values map[string]any) (outValues map[string]any, err error) {
- outValues = make(map[string]any)
-
- if m.servicesClient == nil {
- return nil, errors.New("module has not been initialized")
- }
- if out, err := query.NewBuilder(ctx, m.servicesClient, ComVersion).
- Spawn(class). // The class to instantiate (i.e., Win32_Process)
- Method(method). // The method to call (i.e., Create)
- Values(values). // The values to pass to method
- Exec().
- Object(); err == nil {
- return out.Values(), err
- } else {
- return nil, fmt.Errorf("spawn WMI query: %w", err)
- }
+func (m *Wmi) query(ctx context.Context, class, method string, values map[string]any) (map[string]any, error) {
+ if m.servicesClient == nil {
+ return nil, errors.New("module has not been initialized")
+ }
+ if out, err := query.NewBuilder(ctx, m.servicesClient, ComVersion).
+ Spawn(class). // The class to instantiate (i.e., Win32_Process)
+ Method(method). // The method to call (i.e., Create)
+ Values(values). // The values to pass to method
+ Exec().
+ Object(); err == nil {
+ return out.Values(), err
+ } else {
+ return nil, fmt.Errorf("spawn WMI query: %w", err)
+ }
}