aboutsummaryrefslogtreecommitdiff
path: root/internal/exec/wmi
diff options
context:
space:
mode:
authorBryan McNulty <bryanmcnulty@protonmail.com>2025-04-09 07:48:16 -0500
committerBryan McNulty <bryanmcnulty@protonmail.com>2025-04-09 07:48:16 -0500
commit05873b432686fd584a07e98d37d4eb0cc5104da1 (patch)
tree7d4f73b83cc0876a0b29044d30d32f5a38385a00 /internal/exec/wmi
parentd417d3d4185725967c9333f59942ee348248f2b2 (diff)
downloadgoexec-05873b432686fd584a07e98d37d4eb0cc5104da1.tar.gz
goexec-05873b432686fd584a07e98d37d4eb0cc5104da1.zip
Remodel WMI module; Update TODO; Update deps
Diffstat (limited to 'internal/exec/wmi')
-rw-r--r--internal/exec/wmi/exec.go75
-rw-r--r--internal/exec/wmi/module.go4
2 files changed, 74 insertions, 5 deletions
diff --git a/internal/exec/wmi/exec.go b/internal/exec/wmi/exec.go
index 5f47738..b61bf5c 100644
--- a/internal/exec/wmi/exec.go
+++ b/internal/exec/wmi/exec.go
@@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
+ "github.com/FalconOpsLLC/goexec/internal/client/dce"
"github.com/FalconOpsLLC/goexec/internal/exec"
"github.com/RedTeamPentesting/adauth"
"github.com/RedTeamPentesting/adauth/dcerpcauth"
@@ -21,6 +22,7 @@ import (
const (
ProtocolSequenceRPC uint16 = 7
ProtocolSequenceNP uint16 = 15
+ DefaultWmiEndpoint string = "ncacn_ip_tcp:[135]"
)
var (
@@ -45,7 +47,74 @@ func (mod *Module) Cleanup(ctx context.Context, _ *exec.CleanupConfig) (err erro
return
}
-func (mod *Module) Connect(ctx context.Context, creds *adauth.Credential, target *adauth.Target, _ *exec.ConnectionConfig) (err error) {
+func (mod *Module) Connect(ctx context.Context, creds *adauth.Credential, target *adauth.Target, ccfg *exec.ConnectionConfig) (err error) {
+
+ log := zerolog.Ctx(ctx).With().
+ Str("method", ccfg.ConnectionMethod).
+ Str("func", "Connect").Logger()
+
+ if cfg, ok := ccfg.ConnectionMethodConfig.(dce.ConnectionMethodDCEConfig); !ok {
+ return errors.New("invalid configuration for DCE connection method")
+ } else {
+ var dceOpts []dcerpc.Option
+
+ // Create DCE connection
+ if mod.dce, err = cfg.GetDce(ctx, creds, target, DefaultWmiEndpoint, "", dceOpts...); err != nil {
+ log.Error().Err(err).Msg("Failed to initialize DCE dialer")
+ return fmt.Errorf("create DCE dialer: %w", err)
+ }
+ ia, err := iactivation.NewActivationClient(ctx, mod.dce)
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to create activation client")
+ return fmt.Errorf("create activation client: %w", err)
+ }
+ act, err := ia.RemoteActivation(ctx, &iactivation.RemoteActivationRequest{
+ ORPCThis: ORPCThis,
+ ClassID: wmi.Level1LoginClassID.GUID(),
+ IIDs: []*dcom.IID{iwbemlevel1login.Level1LoginIID},
+ RequestedProtocolSequences: []uint16{ProtocolSequenceRPC, ProtocolSequenceNP}, // TODO: dynamic
+ })
+ if err != nil {
+ return fmt.Errorf("request remote activation: %w", err)
+ }
+ if act.HResult != 0 {
+ return fmt.Errorf("remote activation failed with code %d", act.HResult)
+ }
+ retBinds := act.OXIDBindings.GetStringBindings()
+ if len(act.InterfaceData) < 1 || len(retBinds) < 1 {
+ return errors.New("remote activation failed")
+ }
+ ipid := act.InterfaceData[0].GetStandardObjectReference().Std.IPID
+ for _, sb := range retBinds {
+ //sb.NetworkAddr = target.AddressWithoutPort() // TODO: check if sb.NetworkAddr contains the port
+ dceOpts = append(dceOpts, dcerpc.WithEndpoint(sb.String()))
+ }
+
+ if mod.dce, err = cfg.GetDce(ctx, creds, target, DefaultWmiEndpoint, "", dceOpts...); err != nil {
+ log.Error().Err(err).Msg("Failed to initialize secondary DCE dialer")
+ }
+ loginClient, err := iwbemlevel1login.NewLevel1LoginClient(ctx, mod.dce, dcom.WithIPID(ipid))
+ if err != nil {
+ return fmt.Errorf("initialize wbem login client: %w", err)
+ }
+ login, err := loginClient.NTLMLogin(ctx, &iwbemlevel1login.NTLMLoginRequest{
+ This: ORPCThis,
+ NetworkResource: "//./root/cimv2", // TODO: make this dynamic
+ })
+ if err != nil {
+ return fmt.Errorf("ntlm login: %w", err)
+ }
+
+ mod.sc, err = iwbemservices.NewServicesClient(ctx, mod.dce, dcom.WithIPID(login.Namespace.InterfacePointer().IPID()))
+ if err != nil {
+ return fmt.Errorf("iwbemservices.NewServicesClient: %w", err)
+ }
+ }
+
+ return
+}
+
+func (mod *Module) _Connect(ctx context.Context, creds *adauth.Credential, target *adauth.Target, _ *exec.ConnectionConfig) (err error) {
var baseOpts, authOpts []dcerpc.Option
var ipid *dcom.IPID // This will store the IPID of the remote instance
@@ -157,8 +226,8 @@ func (mod *Module) Exec(ctx context.Context, ecfg *exec.ExecutionConfig) (err er
Str("module", "tsch").
Str("method", ecfg.ExecutionMethod).Logger()
- if ecfg.ExecutionMethod == MethodCustom {
- if cfg, ok := ecfg.ExecutionMethodConfig.(MethodCustomConfig); !ok {
+ if ecfg.ExecutionMethod == MethodCall {
+ if cfg, ok := ecfg.ExecutionMethodConfig.(MethodCallConfig); !ok {
return errors.New("invalid execution configuration")
} else {
diff --git a/internal/exec/wmi/module.go b/internal/exec/wmi/module.go
index f90af42..0e83aa8 100644
--- a/internal/exec/wmi/module.go
+++ b/internal/exec/wmi/module.go
@@ -16,7 +16,7 @@ type Module struct {
sc iwbemservices.ServicesClient
}
-type MethodCustomConfig struct {
+type MethodCallConfig struct {
Class string
Method string
Arguments map[string]any
@@ -28,6 +28,6 @@ type MethodProcessConfig struct {
}
const (
- MethodCustom = "custom"
+ MethodCall = "call"
MethodProcess = "process"
)