aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryan McNulty <bryanmcnulty@protonmail.com>2025-04-26 07:49:48 -0500
committerBryan McNulty <bryanmcnulty@protonmail.com>2025-04-26 07:49:48 -0500
commitb2f118985aab63d2e574967549d3238844bbaae9 (patch)
tree409ba8ed6c437a3d2417c90861b4662134a8b204
parent7770ce5c15dff99c1100f9fe6e41c502a94cd713 (diff)
downloadgoexec-b2f118985aab63d2e574967549d3238844bbaae9.tar.gz
goexec-b2f118985aab63d2e574967549d3238844bbaae9.zip
Add go-msrpc error references to all modules
-rw-r--r--pkg/goexec/dcom/dcom.go44
-rw-r--r--pkg/goexec/dcom/module.go247
-rw-r--r--pkg/goexec/scmr/create.go219
-rw-r--r--pkg/goexec/scmr/module.go3
-rw-r--r--pkg/goexec/tsch/change.go219
-rw-r--r--pkg/goexec/tsch/demand.go133
-rw-r--r--pkg/goexec/tsch/module.go255
-rw-r--r--pkg/goexec/wmi/module.go236
8 files changed, 689 insertions, 667 deletions
diff --git a/pkg/goexec/dcom/dcom.go b/pkg/goexec/dcom/dcom.go
index 41f48d6..a504e1a 100644
--- a/pkg/goexec/dcom/dcom.go
+++ b/pkg/goexec/dcom/dcom.go
@@ -1,33 +1,33 @@
package dcomexec
import (
- googleUUID "github.com/google/uuid"
- "github.com/oiweiwei/go-msrpc/midl/uuid"
- "github.com/oiweiwei/go-msrpc/msrpc/dcom"
- "github.com/oiweiwei/go-msrpc/msrpc/dtyp"
+ googleUUID "github.com/google/uuid"
+ "github.com/oiweiwei/go-msrpc/midl/uuid"
+ "github.com/oiweiwei/go-msrpc/msrpc/dcom"
+ "github.com/oiweiwei/go-msrpc/msrpc/dtyp"
)
const (
- LcEnglishUs uint32 = 0x409
+ LcEnglishUs uint32 = 0x409
)
var (
- ShellWindowsUuid = uuid.MustParse("9BA05972-F6A8-11CF-A442-00A0C90A8F39")
- Mmc20Uuid = uuid.MustParse("49B2791A-B1AE-4C90-9B8E-E860BA07F889")
+ //ShellWindowsUuid = uuid.MustParse("9BA05972-F6A8-11CF-A442-00A0C90A8F39")
+ //Mmc20Uuid = uuid.MustParse("49B2791A-B1AE-4C90-9B8E-E860BA07F889")
- RandCid = dcom.CID(*dtyp.GUIDFromUUID(uuid.MustParse(googleUUID.NewString())))
- IDispatchIID = &dcom.IID{
- Data1: 0x20400,
- Data2: 0x0,
- Data3: 0x0,
- Data4: []byte{0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46},
- }
- ComVersion = &dcom.COMVersion{
- MajorVersion: 5,
- MinorVersion: 7,
- }
- ORPCThis = &dcom.ORPCThis{
- Version: ComVersion,
- CID: &RandCid,
- }
+ RandCid = dcom.CID(*dtyp.GUIDFromUUID(uuid.MustParse(googleUUID.NewString())))
+ IDispatchIID = &dcom.IID{
+ Data1: 0x20400,
+ Data2: 0x0,
+ Data3: 0x0,
+ Data4: []byte{0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46},
+ }
+ ComVersion = &dcom.COMVersion{
+ MajorVersion: 5,
+ MinorVersion: 7,
+ }
+ ORPCThis = &dcom.ORPCThis{
+ Version: ComVersion,
+ CID: &RandCid,
+ }
)
diff --git a/pkg/goexec/dcom/module.go b/pkg/goexec/dcom/module.go
index 1aa44c1..b6fc4d4 100644
--- a/pkg/goexec/dcom/module.go
+++ b/pkg/goexec/dcom/module.go
@@ -1,142 +1,145 @@
package dcomexec
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/midl/uuid"
- "github.com/oiweiwei/go-msrpc/msrpc/dcom"
- "github.com/oiweiwei/go-msrpc/msrpc/dcom/iremotescmactivator/v0"
- "github.com/oiweiwei/go-msrpc/msrpc/dcom/oaut/idispatch/v0"
- "github.com/oiweiwei/go-msrpc/msrpc/dtyp"
- "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/midl/uuid"
+ "github.com/oiweiwei/go-msrpc/msrpc/dcom"
+ "github.com/oiweiwei/go-msrpc/msrpc/dcom/iremotescmactivator/v0"
+ "github.com/oiweiwei/go-msrpc/msrpc/dcom/oaut/idispatch/v0"
+ "github.com/oiweiwei/go-msrpc/msrpc/dtyp"
+ "github.com/rs/zerolog"
+
+ _ "github.com/oiweiwei/go-msrpc/msrpc/erref/ntstatus"
+ _ "github.com/oiweiwei/go-msrpc/msrpc/erref/win32"
)
const (
- ModuleName = "DCOM"
+ ModuleName = "DCOM"
)
type Dcom struct {
- goexec.Cleaner
- goexec.Executor
+ goexec.Cleaner
+ goexec.Executor
- Client *dce.Client
- ClassID string
+ Client *dce.Client
+ ClassID string
- dispatchClient idispatch.DispatchClient
+ dispatchClient idispatch.DispatchClient
}
func (m *Dcom) 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 *Dcom) 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")
- }
-
- m.ClassID = "49B2791A-B1AE-4C90-9B8E-E860BA07F889"
- //m.ClassID = "9BA05972-F6A8-11CF-A442-00A0C90A8F39"
- class := dcom.ClassID(*dtyp.GUIDFromUUID(uuid.MustParse(m.ClassID)))
-
- if class.GUID() == nil {
- return fmt.Errorf("invalid class ID: %s", m.ClassID)
- }
-
- opts := []dcerpc.Option{
- dcerpc.WithSign(),
- }
-
- inst := &dcom.InstantiationInfoData{
- ClassID: &class,
- IID: []*dcom.IID{IDispatchIID},
- ClientCOMVersion: ComVersion,
- }
- ac := &dcom.ActivationContextInfoData{}
- loc := &dcom.LocationInfoData{}
- scm := &dcom.SCMRequestInfoData{
- RemoteRequest: &dcom.CustomRemoteRequestSCMInfo{
- RequestedProtocolSequences: []uint16{7},
- },
- }
-
- ap := &dcom.ActivationProperties{
- DestinationContext: 2,
- Properties: []dcom.ActivationProperty{inst, ac, loc, scm},
- }
-
- apin, err := ap.ActivationPropertiesIn()
- if err != nil {
- return err
- }
-
- act, err := iremotescmactivator.NewRemoteSCMActivatorClient(ctx, m.Client.Dce())
- if err != nil {
- return err
- }
-
- cr, err := act.RemoteCreateInstance(ctx, &iremotescmactivator.RemoteCreateInstanceRequest{
- ORPCThis: &dcom.ORPCThis{
- Version: ComVersion,
- Flags: 1,
- CID: &RandCid,
- },
- ActPropertiesIn: apin,
- })
- if err != nil {
- return err
- }
- log.Info().Msg("RemoteCreateInstance succeeded")
-
- apout := new(dcom.ActivationProperties)
- if err = apout.Parse(cr.ActPropertiesOut); err != nil {
- return err
- }
- si := apout.SCMReplyInfoData()
- pi := apout.PropertiesOutInfo()
-
- if si == nil {
- return fmt.Errorf("remote create instance response: SCMReplyInfoData is nil")
- }
-
- if pi == nil {
- return fmt.Errorf("remote create instance response: PropertiesOutInfo is nil")
- }
-
- // Ensure that the string bindings don't contain the target hostname
- for _, bind := range si.RemoteReply.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 = ""
- opts = append(opts, dcerpc.WithEndpoint(stringBinding.String()))
- }
-
- err = m.Client.Reconnect(ctx, opts...)
- if err != nil {
- return err
- }
- log.Info().Msg("created new DCERPC dialer")
-
- m.dispatchClient, err = idispatch.NewDispatchClient(ctx, m.Client.Dce(), dcom.WithIPID(pi.InterfaceData[0].IPID()))
- if err != nil {
- return err
- }
- log.Info().Msg("created IDispatch 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")
+ }
+
+ m.ClassID = "49B2791A-B1AE-4C90-9B8E-E860BA07F889"
+ //m.ClassID = "9BA05972-F6A8-11CF-A442-00A0C90A8F39"
+ class := dcom.ClassID(*dtyp.GUIDFromUUID(uuid.MustParse(m.ClassID)))
+
+ if class.GUID() == nil {
+ return fmt.Errorf("invalid class ID: %s", m.ClassID)
+ }
+
+ opts := []dcerpc.Option{
+ dcerpc.WithSign(),
+ }
+
+ inst := &dcom.InstantiationInfoData{
+ ClassID: &class,
+ IID: []*dcom.IID{IDispatchIID},
+ ClientCOMVersion: ComVersion,
+ }
+ ac := &dcom.ActivationContextInfoData{}
+ loc := &dcom.LocationInfoData{}
+ scm := &dcom.SCMRequestInfoData{
+ RemoteRequest: &dcom.CustomRemoteRequestSCMInfo{
+ RequestedProtocolSequences: []uint16{7},
+ },
+ }
+
+ ap := &dcom.ActivationProperties{
+ DestinationContext: 2,
+ Properties: []dcom.ActivationProperty{inst, ac, loc, scm},
+ }
+
+ apin, err := ap.ActivationPropertiesIn()
+ if err != nil {
+ return err
+ }
+
+ act, err := iremotescmactivator.NewRemoteSCMActivatorClient(ctx, m.Client.Dce())
+ if err != nil {
+ return err
+ }
+
+ cr, err := act.RemoteCreateInstance(ctx, &iremotescmactivator.RemoteCreateInstanceRequest{
+ ORPCThis: &dcom.ORPCThis{
+ Version: ComVersion,
+ Flags: 1,
+ CID: &RandCid,
+ },
+ ActPropertiesIn: apin,
+ })
+ if err != nil {
+ return err
+ }
+ log.Info().Msg("RemoteCreateInstance succeeded")
+
+ apout := new(dcom.ActivationProperties)
+ if err = apout.Parse(cr.ActPropertiesOut); err != nil {
+ return err
+ }
+ si := apout.SCMReplyInfoData()
+ pi := apout.PropertiesOutInfo()
+
+ if si == nil {
+ return fmt.Errorf("remote create instance response: SCMReplyInfoData is nil")
+ }
+
+ if pi == nil {
+ return fmt.Errorf("remote create instance response: PropertiesOutInfo is nil")
+ }
+
+ // Ensure that the string bindings don't contain the target hostname
+ for _, bind := range si.RemoteReply.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 = ""
+ opts = append(opts, dcerpc.WithEndpoint(stringBinding.String()))
+ }
+
+ err = m.Client.Reconnect(ctx, opts...)
+ if err != nil {
+ return err
+ }
+ log.Info().Msg("created new DCERPC dialer")
+
+ m.dispatchClient, err = idispatch.NewDispatchClient(ctx, m.Client.Dce(), dcom.WithIPID(pi.InterfaceData[0].IPID()))
+ if err != nil {
+ return err
+ }
+ log.Info().Msg("created IDispatch Client")
+
+ return
}
diff --git a/pkg/goexec/scmr/create.go b/pkg/goexec/scmr/create.go
index b0f8774..f0245af 100644
--- a/pkg/goexec/scmr/create.go
+++ b/pkg/goexec/scmr/create.go
@@ -1,126 +1,129 @@
package scmrexec
import (
- "context"
- "fmt"
- "github.com/FalconOpsLLC/goexec/internal/util"
- "github.com/FalconOpsLLC/goexec/pkg/goexec"
- "github.com/oiweiwei/go-msrpc/msrpc/scmr/svcctl/v2"
- "github.com/rs/zerolog"
+ "context"
+ "fmt"
+ "github.com/FalconOpsLLC/goexec/internal/util"
+ "github.com/FalconOpsLLC/goexec/pkg/goexec"
+ "github.com/oiweiwei/go-msrpc/msrpc/scmr/svcctl/v2"
+ "github.com/rs/zerolog"
+
+ _ "github.com/oiweiwei/go-msrpc/msrpc/erref/ntstatus"
+ _ "github.com/oiweiwei/go-msrpc/msrpc/erref/win32"
)
const (
- MethodCreate = "Create"
+ MethodCreate = "Create"
)
type ScmrCreate struct {
- Scmr
- goexec.Cleaner
- goexec.Executor
+ Scmr
+ goexec.Cleaner
+ goexec.Executor
- IO goexec.ExecutionIO
+ IO goexec.ExecutionIO
- NoDelete bool
- NoStart bool
- ServiceName string
- DisplayName string
+ NoDelete bool
+ NoStart bool
+ ServiceName string
+ DisplayName string
}
func (m *ScmrCreate) ensure() {
- if m.ServiceName == "" {
- m.ServiceName = util.RandomString()
- }
- if m.DisplayName == "" {
- m.DisplayName = m.ServiceName
- }
+ if m.ServiceName == "" {
+ m.ServiceName = util.RandomString()
+ }
+ if m.DisplayName == "" {
+ m.DisplayName = m.ServiceName
+ }
}
func (m *ScmrCreate) Execute(ctx context.Context, in *goexec.ExecutionIO) (err error) {
- m.ensure()
-
- log := zerolog.Ctx(ctx).With().
- Str("service", m.ServiceName).Logger()
-
- svc := &service{name: m.ServiceName}
-
- resp, err := m.ctl.CreateServiceW(ctx, &svcctl.CreateServiceWRequest{
- ServiceManager: m.scm,
- ServiceName: m.ServiceName,
- DisplayName: m.DisplayName,
- BinaryPathName: in.String(),
- ServiceType: ServiceWin32OwnProcess,
- StartType: ServiceDemandStart,
- DesiredAccess: ServiceAllAccess, // TODO: Replace
- })
-
- if err != nil {
- log.Error().Err(err).Msg("Create service request failed")
- return fmt.Errorf("create service request: %w", err)
- }
-
- if resp.Return != 0 {
- log.Error().Err(err).Msg("Failed to create service")
- return fmt.Errorf("create service returned non-zero exit code: %02x", resp.Return)
- }
-
- if !m.NoDelete {
- m.AddCleaners(func(ctxInner context.Context) error {
-
- r, errInner := m.ctl.DeleteService(ctxInner, &svcctl.DeleteServiceRequest{
- Service: svc.handle,
- })
- if errInner != nil {
- return fmt.Errorf("delete service: %w", errInner)
- }
- if r.Return != 0 {
- return fmt.Errorf("delete service returned non-zero exit code: %02x", r.Return)
- }
- log.Info().Msg("Deleted service")
-
- return nil
- })
- }
-
- m.AddCleaners(func(ctxInner context.Context) error {
-
- r, errInner := m.ctl.CloseService(ctxInner, &svcctl.CloseServiceRequest{
- ServiceObject: svc.handle,
- })
- if errInner != nil {
- return fmt.Errorf("close service: %w", errInner)
- }
- if r.Return != 0 {
- return fmt.Errorf("close service returned non-zero exit code: %02x", r.Return)
- }
- log.Info().Msg("Closed service handle")
-
- return nil
- })
-
- log.Info().Msg("Created service")
- svc.handle = resp.Service
-
- if !m.NoStart {
-
- err = m.startService(ctx, svc)
-
- if err != nil {
- log.Error().Err(err).Msg("Failed to start service")
- return fmt.Errorf("start service: %w", err)
- }
- }
- if svc.handle == nil {
-
- if err = m.Reconnect(ctx); err != nil {
- return err
- }
- svc, err = m.openService(ctx, svc.name)
-
- if err != nil {
- log.Error().Err(err).Msg("Failed to reopen service handle")
- return fmt.Errorf("reopen service: %w", err)
- }
- }
-
- return
+ m.ensure()
+
+ log := zerolog.Ctx(ctx).With().
+ Str("service", m.ServiceName).Logger()
+
+ svc := &service{name: m.ServiceName}
+
+ resp, err := m.ctl.CreateServiceW(ctx, &svcctl.CreateServiceWRequest{
+ ServiceManager: m.scm,
+ ServiceName: m.ServiceName,
+ DisplayName: m.DisplayName,
+ BinaryPathName: in.String(),
+ ServiceType: ServiceWin32OwnProcess,
+ StartType: ServiceDemandStart,
+ DesiredAccess: ServiceAllAccess, // TODO: Replace
+ })
+
+ if err != nil {
+ log.Error().Err(err).Msg("Create service request failed")
+ return fmt.Errorf("create service request: %w", err)
+ }
+
+ if resp.Return != 0 {
+ log.Error().Err(err).Msg("Failed to create service")
+ return fmt.Errorf("create service returned non-zero exit code: %02x", resp.Return)
+ }
+
+ if !m.NoDelete {
+ m.AddCleaners(func(ctxInner context.Context) error {
+
+ r, errInner := m.ctl.DeleteService(ctxInner, &svcctl.DeleteServiceRequest{
+ Service: svc.handle,
+ })
+ if errInner != nil {
+ return fmt.Errorf("delete service: %w", errInner)
+ }
+ if r.Return != 0 {
+ return fmt.Errorf("delete service returned non-zero exit code: %02x", r.Return)
+ }
+ log.Info().Msg("Deleted service")
+
+ return nil
+ })
+ }
+
+ m.AddCleaners(func(ctxInner context.Context) error {
+
+ r, errInner := m.ctl.CloseService(ctxInner, &svcctl.CloseServiceRequest{
+ ServiceObject: svc.handle,
+ })
+ if errInner != nil {
+ return fmt.Errorf("close service: %w", errInner)
+ }
+ if r.Return != 0 {
+ return fmt.Errorf("close service returned non-zero exit code: %02x", r.Return)
+ }
+ log.Info().Msg("Closed service handle")
+
+ return nil
+ })
+
+ log.Info().Msg("Created service")
+ svc.handle = resp.Service
+
+ if !m.NoStart {
+
+ err = m.startService(ctx, svc)
+
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to start service")
+ return fmt.Errorf("start service: %w", err)
+ }
+ }
+ if svc.handle == nil {
+
+ if err = m.Reconnect(ctx); err != nil {
+ return err
+ }
+ svc, err = m.openService(ctx, svc.name)
+
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to reopen service handle")
+ return fmt.Errorf("reopen service: %w", err)
+ }
+ }
+
+ return
}
diff --git a/pkg/goexec/scmr/module.go b/pkg/goexec/scmr/module.go
index 708da23..56ce3fd 100644
--- a/pkg/goexec/scmr/module.go
+++ b/pkg/goexec/scmr/module.go
@@ -11,6 +11,9 @@ import (
"github.com/oiweiwei/go-msrpc/midl/uuid"
"github.com/oiweiwei/go-msrpc/msrpc/scmr/svcctl/v2"
"github.com/rs/zerolog"
+
+ _ "github.com/oiweiwei/go-msrpc/msrpc/erref/ntstatus"
+ _ "github.com/oiweiwei/go-msrpc/msrpc/erref/win32"
)
type Scmr struct {
diff --git a/pkg/goexec/tsch/change.go b/pkg/goexec/tsch/change.go
index 44877c9..908b25a 100644
--- a/pkg/goexec/tsch/change.go
+++ b/pkg/goexec/tsch/change.go
@@ -1,152 +1,155 @@
package tschexec
import (
- "context"
- "encoding/xml"
- "fmt"
- "github.com/FalconOpsLLC/goexec/pkg/goexec"
- "github.com/FalconOpsLLC/goexec/pkg/goexec/tsch/task"
- "github.com/oiweiwei/go-msrpc/msrpc/tsch/itaskschedulerservice/v1"
- "github.com/rs/zerolog"
- "regexp"
- "time"
+ "context"
+ "encoding/xml"
+ "fmt"
+ "github.com/FalconOpsLLC/goexec/pkg/goexec"
+ "github.com/FalconOpsLLC/goexec/pkg/goexec/tsch/task"
+ "github.com/oiweiwei/go-msrpc/msrpc/tsch/itaskschedulerservice/v1"
+ "github.com/rs/zerolog"
+ "regexp"
+ "time"
+
+ _ "github.com/oiweiwei/go-msrpc/msrpc/erref/ntstatus"
+ _ "github.com/oiweiwei/go-msrpc/msrpc/erref/win32"
)
const (
- FlagTaskUpdate uint32 = 0b_00000000_00000000_00000000_00000100
- MethodChange = "Change"
- DefaultWaitTime = 1 * time.Second
+ FlagTaskUpdate uint32 = 0b_00000000_00000000_00000000_00000100
+ MethodChange = "Change"
+ DefaultWaitTime = 1 * time.Second
)
type TschChange struct {
- Tsch
- goexec.Executor
- goexec.Cleaner
+ Tsch
+ goexec.Executor
+ goexec.Cleaner
- IO goexec.ExecutionIO
+ IO goexec.ExecutionIO
- WorkingDirectory string
- NoStart bool
- NoRevert bool
- WaitTime time.Duration
+ WorkingDirectory string
+ NoStart bool
+ NoRevert bool
+ WaitTime time.Duration
}
func (m *TschChange) Execute(ctx context.Context, execIO *goexec.ExecutionIO) (err error) {
- log := zerolog.Ctx(ctx).With().
- Str("module", ModuleName).
- Str("method", MethodChange).
- Str("task", m.TaskPath).
- Logger()
+ log := zerolog.Ctx(ctx).With().
+ Str("module", ModuleName).
+ Str("method", MethodChange).
+ Str("task", m.TaskPath).
+ Logger()
- retrieveResponse, err := m.tsch.RetrieveTask(ctx, &itaskschedulerservice.RetrieveTaskRequest{
- Path: m.TaskPath,
- })
+ retrieveResponse, err := m.tsch.RetrieveTask(ctx, &itaskschedulerservice.RetrieveTaskRequest{
+ Path: m.TaskPath,
+ })
- if err != nil {
- log.Error().Err(err).Msg("Failed to retrieve task")
- return fmt.Errorf("retrieve task: %w", err)
- }
- if retrieveResponse.Return != 0 {
- log.Error().Err(err).Str("code", fmt.Sprintf("0x%02x", retrieveResponse.Return)).
- Msg("Failed to retrieve task")
- return fmt.Errorf("retrieve task returned non-zero exit code: %02x", retrieveResponse.Return)
- }
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to retrieve task")
+ return fmt.Errorf("retrieve task: %w", err)
+ }
+ if retrieveResponse.Return != 0 {
+ log.Error().Err(err).Str("code", fmt.Sprintf("0x%02x", retrieveResponse.Return)).
+ Msg("Failed to retrieve task")
+ return fmt.Errorf("retrieve task returned non-zero exit code: %02x", retrieveResponse.Return)
+ }
- log.Info().Msg("Successfully retrieved existing task definition")
- log.Debug().Str("xml", retrieveResponse.XML).Msg("Got task definition")
+ log.Info().Msg("Successfully retrieved existing task definition")
+ log.Debug().Str("xml", retrieveResponse.XML).Msg("Got task definition")
- tk := task.Task{}
+ tk := task.Task{}
- enc := regexp.MustCompile(`(?i)^<\?xml .*?\?>`)
- tkStr := enc.ReplaceAllString(retrieveResponse.XML, `<?xml version="1.0" encoding="utf-8"?>`)
+ enc := regexp.MustCompile(`(?i)^<\?xml .*?\?>`)
+ tkStr := enc.ReplaceAllString(retrieveResponse.XML, `<?xml version="1.0" encoding="utf-8"?>`)
- if err = xml.Unmarshal([]byte(tkStr), &tk); err != nil {
- log.Error().Err(err).Msg("Failed to unmarshal task XML")
+ if err = xml.Unmarshal([]byte(tkStr), &tk); err != nil {
+ log.Error().Err(err).Msg("Failed to unmarshal task XML")
- return fmt.Errorf("unmarshal task XML: %w", err)
- }
+ return fmt.Errorf("unmarshal task XML: %w", err)
+ }
- cmd := execIO.CommandLine()
+ cmd := execIO.CommandLine()
- tk.Actions.Exec = append(tk.Actions.Exec, task.ExecAction{
- Command: cmd[0],
- Arguments: cmd[1],
- WorkingDirectory: m.WorkingDirectory,
- })
+ tk.Actions.Exec = append(tk.Actions.Exec, task.ExecAction{
+ Command: cmd[0],
+ Arguments: cmd[1],
+ WorkingDirectory: m.WorkingDirectory,
+ })
- doc, err := xml.Marshal(tk)
+ doc, err := xml.Marshal(tk)
- if err != nil {
- log.Error().Err(err).Msg("failed to marshal task XML")
- return fmt.Errorf("marshal task: %w", err)
- }
+ if err != nil {
+ log.Error().Err(err).Msg("failed to marshal task XML")
+ return fmt.Errorf("marshal task: %w", err)
+ }
- taskXml := TaskXmlHeader + string(doc)
- log.Debug().Str("xml", taskXml).Msg("Serialized new task")
+ taskXml := TaskXmlHeader + string(doc)
+ log.Debug().Str("xml", taskXml).Msg("Serialized new task")
- registerResponse, err := m.tsch.RegisterTask(ctx, &itaskschedulerservice.RegisterTaskRequest{
- Path: m.TaskPath,
- XML: taskXml,
- Flags: FlagTaskUpdate,
- })
+ registerResponse, err := m.tsch.RegisterTask(ctx, &itaskschedulerservice.RegisterTaskRequest{
+ Path: m.TaskPath,
+ XML: taskXml,
+ Flags: FlagTaskUpdate,
+ })
- if !m.NoRevert {
+ if !m.NoRevert {
- m.AddCleaners(func(ctxInner context.Context) error {
+ m.AddCleaners(func(ctxInner context.Context) error {
- revertResponse, err := m.tsch.RegisterTask(ctx, &itaskschedulerservice.RegisterTaskRequest{
- Path: m.TaskPath,
- XML: retrieveResponse.XML,
- Flags: FlagTaskUpdate,
- })
+ revertResponse, err := m.tsch.RegisterTask(ctx, &itaskschedulerservice.RegisterTaskRequest{
+ Path: m.TaskPath,
+ XML: retrieveResponse.XML,
+ Flags: FlagTaskUpdate,
+ })
- if err != nil {
- return err
- }
- if revertResponse.Return != 0 {
- return fmt.Errorf("revert task definition returned non-zero exit code: %02x", revertResponse.Return)
- }
- return nil
- })
- }
+ if err != nil {
+ return err
+ }
+ if revertResponse.Return != 0 {
+ return fmt.Errorf("revert task definition returned non-zero exit code: %02x", revertResponse.Return)
+ }
+ return nil
+ })
+ }
- if err != nil {
- log.Error().Err(err).Msg("Failed to update task")
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to update task")
- return fmt.Errorf("update task: %w", err)
- }
- if registerResponse.Return != 0 {
- log.Error().Err(err).Str("code", fmt.Sprintf("0x%02x", registerResponse.Return)).Msg("Failed to update task definition")
+ return fmt.Errorf("update task: %w", err)
+ }
+ if registerResponse.Return != 0 {
+ log.Error().Err(err).Str("code", fmt.Sprintf("0x%02x", registerResponse.Return)).Msg("Failed to update task definition")
- return fmt.Errorf("update task returned non-zero exit code: %02x", registerResponse.Return)
- }
- log.Info().Msg("Successfully updated task definition")
+ return fmt.Errorf("update task returned non-zero exit code: %02x", registerResponse.Return)
+ }
+ log.Info().Msg("Successfully updated task definition")
- if !m.NoStart {
+ if !m.NoStart {
- runResponse, err := m.tsch.Run(ctx, &itaskschedulerservice.RunRequest{
- Path: m.TaskPath,
- })
+ runResponse, err := m.tsch.Run(ctx, &itaskschedulerservice.RunRequest{
+ Path: m.TaskPath,
+ })
- if err != nil {
- log.Error().Err(err).Msg("Failed to run modified task")
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to run modified task")
- return fmt.Errorf("run task: %w", err)
- }
+ return fmt.Errorf("run task: %w", err)
+ }
- if ret := uint32(runResponse.Return); ret != 0 {
- log.Error().Str("code", fmt.Sprintf("0x%08x", ret)).Msg("Run task returned non-zero exit code")
+ if ret := uint32(runResponse.Return); ret != 0 {
+ log.Error().Str("code", fmt.Sprintf("0x%08x", ret)).Msg("Run task returned non-zero exit code")
- return fmt.Errorf("run task returned non-zero exit code: 0x%08x", ret)
- }
+ return fmt.Errorf("run task returned non-zero exit code: 0x%08x", ret)
+ }
- log.Info().Msg("Successfully started modified task")
- }
+ log.Info().Msg("Successfully started modified task")
+ }
- if m.WaitTime <= 0 {
- m.WaitTime = DefaultWaitTime
- }
- time.Sleep(m.WaitTime)
- return
+ if m.WaitTime <= 0 {
+ m.WaitTime = DefaultWaitTime
+ }
+ time.Sleep(m.WaitTime)
+ return
}
diff --git a/pkg/goexec/tsch/demand.go b/pkg/goexec/tsch/demand.go
index 74a41fe..62e546f 100644
--- a/pkg/goexec/tsch/demand.go
+++ b/pkg/goexec/tsch/demand.go
@@ -1,81 +1,84 @@
package tschexec
import (
- "context"
- "fmt"
- "github.com/FalconOpsLLC/goexec/pkg/goexec"
- "github.com/oiweiwei/go-msrpc/msrpc/tsch/itaskschedulerservice/v1"
- "github.com/rs/zerolog"
+ "context"
+ "fmt"
+ "github.com/FalconOpsLLC/goexec/pkg/goexec"
+ "github.com/oiweiwei/go-msrpc/msrpc/tsch/itaskschedulerservice/v1"
+ "github.com/rs/zerolog"
+
+ _ "github.com/oiweiwei/go-msrpc/msrpc/erref/ntstatus"
+ _ "github.com/oiweiwei/go-msrpc/msrpc/erref/win32"
)
const (
- MethodDemand = "Demand"
+ MethodDemand = "Demand"
)
type TschDemand struct {
- Tsch
- goexec.Executor
- goexec.Cleaner
+ Tsch
+ goexec.Executor
+ goexec.Cleaner
- IO goexec.ExecutionIO
+ IO goexec.ExecutionIO
- NoDelete bool
- NoStart bool
- SessionId uint32
+ NoDelete bool
+ NoStart bool
+ SessionId uint32
}
func (m *TschDemand) Execute(ctx context.Context, execIO *goexec.ExecutionIO) (err error) {
- log := zerolog.Ctx(ctx).With().
- Str("module", ModuleName).
- Str("method", MethodDemand).
- Str("task", m.TaskPath).
- Logger()
-
- path, err := m.registerTask(ctx,
- &registerOptions{
- AllowStartOnDemand: true,
- AllowHardTerminate: true,
- Hidden: !m.NotHidden,
- triggers: taskTriggers{},
- },
- execIO,
- )
- if err != nil {
- return err
- }
-
- log.Info().Msg("Task registered")
-
- if !m.NoDelete {
- m.AddCleaners(func(ctxInner context.Context) error {
- return m.deleteTask(ctxInner, path)
- })
- }
-
- if !m.NoStart {
-
- var flags uint32
- if m.SessionId != 0 {
- flags |= 4
- }
-
- runResponse, err := m.tsch.Run(ctx, &itaskschedulerservice.RunRequest{
- Path: path,
- Flags: flags,
- SessionID: m.SessionId,
- })
-
- if err != nil {
- log.Error().Err(err).Msg("Failed to run task")
- return fmt.Errorf("run task: %w", err)
- }
- if ret := uint32(runResponse.Return); ret != 0 {
- log.Error().Str("code", fmt.Sprintf("0x%08x", ret)).Msg("Task returned non-zero exit code")
- return fmt.Errorf("task returned non-zero exit code: 0x%08x", ret)
- }
-
- log.Info().Msg("Task started successfully")
- }
- return
+ log := zerolog.Ctx(ctx).With().
+ Str("module", ModuleName).
+ Str("method", MethodDemand).
+ Str("task", m.TaskPath).
+ Logger()
+
+ path, err := m.registerTask(ctx,
+ &registerOptions{
+ AllowStartOnDemand: true,
+ AllowHardTerminate: true,
+ Hidden: !m.NotHidden,
+ triggers: taskTriggers{},
+ },
+ execIO,
+ )
+ if err != nil {
+ return err
+ }
+
+ log.Info().Msg("Task registered")
+
+ if !m.NoDelete {
+ m.AddCleaners(func(ctxInner context.Context) error {
+ return m.deleteTask(ctxInner, path)
+ })
+ }
+
+ if !m.NoStart {
+
+ var flags uint32
+ if m.SessionId != 0 {
+ flags |= 4
+ }
+
+ runResponse, err := m.tsch.Run(ctx, &itaskschedulerservice.RunRequest{
+ Path: path,
+ Flags: flags,
+ SessionID: m.SessionId,
+ })
+
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to run task")
+ return fmt.Errorf("run task: %w", err)
+ }
+ if ret := uint32(runResponse.Return); ret != 0 {
+ log.Error().Str("code", fmt.Sprintf("0x%08x", ret)).Msg("Task returned non-zero exit code")
+ return fmt.Errorf("task returned non-zero exit code: 0x%08x", ret)
+ }
+
+ log.Info().Msg("Task started successfully")
+ }
+ return
}
diff --git a/pkg/goexec/tsch/module.go b/pkg/goexec/tsch/module.go
index 677856d..6ca4cca 100644
--- a/pkg/goexec/tsch/module.go
+++ b/pkg/goexec/tsch/module.go
@@ -1,163 +1,166 @@
package tschexec
import (
- "context"
- "encoding/xml"
- "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/tsch/itaskschedulerservice/v1"
- "github.com/rs/zerolog"
+ "context"
+ "encoding/xml"
+ "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/tsch/itaskschedulerservice/v1"
+ "github.com/rs/zerolog"
+
+ _ "github.com/oiweiwei/go-msrpc/msrpc/erref/ntstatus"
+ _ "github.com/oiweiwei/go-msrpc/msrpc/erref/win32"
)
const (
- ModuleName = "TSCH"
+ ModuleName = "TSCH"
)
type Tsch struct {
- goexec.Cleaner
+ goexec.Cleaner
- Client *dce.Client
- tsch itaskschedulerservice.TaskSchedulerServiceClient
+ Client *dce.Client
+ tsch itaskschedulerservice.TaskSchedulerServiceClient
- TaskPath string
- UserSid string
- NotHidden bool
+ TaskPath string
+ UserSid string
+ NotHidden bool
}
type registerOptions struct {
- AllowStartOnDemand bool
- AllowHardTerminate bool
- StartWhenAvailable bool
- Hidden bool
- DeleteAfter string
+ AllowStartOnDemand bool
+ AllowHardTerminate bool
+ StartWhenAvailable bool
+ Hidden bool
+ DeleteAfter string
- triggers taskTriggers
+ triggers taskTriggers
}
func (m *Tsch) 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 *Tsch) Init(ctx context.Context) (err error) {
- if m.Client.Dce() == nil {
- return errors.New("DCE connection not initialized")
- }
+ if m.Client.Dce() == nil {
+ return errors.New("DCE connection not initialized")
+ }
- // Create ITaskSchedulerService Client
- m.tsch, err = itaskschedulerservice.NewTaskSchedulerServiceClient(ctx, m.Client.Dce(), dcerpc.WithSeal())
- return
+ // Create ITaskSchedulerService Client
+ m.tsch, err = itaskschedulerservice.NewTaskSchedulerServiceClient(ctx, m.Client.Dce(), dcerpc.WithSeal())
+ return
}
func (m *Tsch) registerTask(ctx context.Context, opts *registerOptions, in *goexec.ExecutionIO) (path string, err error) {
- log := zerolog.Ctx(ctx).With().
- Str("task", m.TaskPath).
- Logger()
-
- ctx = log.WithContext(ctx)
-
- principalId := "LocalSystem"
-
- settings := taskSettings{
- MultipleInstancesPolicy: "IgnoreNew",
- IdleSettings: taskIdleSettings{
- StopOnIdleEnd: true,
- RestartOnIdle: false,
- },
- Enabled: true,
- Priority: 7, // a pretty standard value for scheduled tasks
- AllowHardTerminate: opts.AllowHardTerminate,
- AllowStartOnDemand: opts.AllowStartOnDemand,
- Hidden: opts.Hidden,
- StartWhenAvailable: opts.StartWhenAvailable,
- DeleteExpiredTaskAfter: opts.DeleteAfter,
- }
-
- principals := taskPrincipals{
- Principals: []taskPrincipal{
- {
- ID: principalId,
- UserID: m.UserSid,
- RunLevel: "HighestAvailable",
- },
- }}
-
- cmdline := in.CommandLine()
-
- actions := taskActions{
- Context: principalId,
- Exec: []taskActionExec{
- {
- Command: cmdline[0],
- Arguments: cmdline[1],
- },
- },
- }
-
- def := simpleTask{
- TaskVersion: TaskXmlVersion,
- TaskNamespace: TaskXmlNamespace,
- Triggers: opts.triggers,
- Actions: actions,
- Principals: principals,
- Settings: settings,
- }
-
- // Generate task XML content. See https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tsch/0d6383e4-de92-43e7-b0bb-a60cfa36379f
-
- doc, err := xml.Marshal(def)
-
- if err != nil {
- log.Error().Err(err).Msg("failed to marshal task XML")
- return "", fmt.Errorf("marshal task: %w", err)
- }
-
- taskXml := TaskXmlHeader + string(doc)
-
- log.Debug().Str("content", taskXml).Msg("Generated task XML")
-
- registerResponse, err := m.tsch.RegisterTask(ctx, &itaskschedulerservice.RegisterTaskRequest{
- Path: m.TaskPath,
- XML: taskXml,
- Flags: 0, // FEATURE: dynamic
- SDDL: "",
- LogonType: 0, // FEATURE: dynamic
- CredsCount: 0,
- Creds: nil,
- })
-
- if err != nil {
- log.Error().Err(err).Msg("Failed to register task")
- return "", fmt.Errorf("register task: %w", err)
- }
- log.Info().Msg("Scheduled task registered")
-
- return registerResponse.ActualPath, nil
+ log := zerolog.Ctx(ctx).With().
+ Str("task", m.TaskPath).
+ Logger()
+
+ ctx = log.WithContext(ctx)
+
+ principalId := "LocalSystem"
+
+ settings := taskSettings{
+ MultipleInstancesPolicy: "IgnoreNew",
+ IdleSettings: taskIdleSettings{
+ StopOnIdleEnd: true,
+ RestartOnIdle: false,
+ },
+ Enabled: true,
+ Priority: 7, // a pretty standard value for scheduled tasks
+ AllowHardTerminate: opts.AllowHardTerminate,
+ AllowStartOnDemand: opts.AllowStartOnDemand,
+ Hidden: opts.Hidden,
+ StartWhenAvailable: opts.StartWhenAvailable,
+ DeleteExpiredTaskAfter: opts.DeleteAfter,
+ }
+
+ principals := taskPrincipals{
+ Principals: []taskPrincipal{
+ {
+ ID: principalId,
+ UserID: m.UserSid,
+ RunLevel: "HighestAvailable",
+ },
+ }}
+
+ cmdline := in.CommandLine()
+
+ actions := taskActions{
+ Context: principalId,
+ Exec: []taskActionExec{
+ {
+ Command: cmdline[0],
+ Arguments: cmdline[1],
+ },
+ },
+ }
+
+ def := simpleTask{
+ TaskVersion: TaskXmlVersion,
+ TaskNamespace: TaskXmlNamespace,
+ Triggers: opts.triggers,
+ Actions: actions,
+ Principals: principals,
+ Settings: settings,
+ }
+
+ // Generate task XML content. See https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tsch/0d6383e4-de92-43e7-b0bb-a60cfa36379f
+
+ doc, err := xml.Marshal(def)
+
+ if err != nil {
+ log.Error().Err(err).Msg("failed to marshal task XML")
+ return "", fmt.Errorf("marshal task: %w", err)
+ }
+
+ taskXml := TaskXmlHeader + string(doc)
+
+ log.Debug().Str("content", taskXml).Msg("Generated task XML")
+
+ registerResponse, err := m.tsch.RegisterTask(ctx, &itaskschedulerservice.RegisterTaskRequest{
+ Path: m.TaskPath,
+ XML: taskXml,
+ Flags: 0, // FEATURE: dynamic
+ SDDL: "",
+ LogonType: 0, // FEATURE: dynamic
+ CredsCount: 0,
+ Creds: nil,
+ })
+
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to register task")
+ return "", fmt.Errorf("register task: %w", err)
+ }
+ log.Info().Msg("Scheduled task registered")
+
+ return registerResponse.ActualPath, nil
}
func (m *Tsch) deleteTask(ctx context.Context, taskPath string) (err error) {
- log := zerolog.Ctx(ctx).With().
- Str("path", taskPath).Logger()
+ log := zerolog.Ctx(ctx).With().
+ Str("path", taskPath).Logger()
- _, err = m.tsch.Delete(ctx, &itaskschedulerservice.DeleteRequest{
- Path: taskPath,
- })
+ _, err = m.tsch.Delete(ctx, &itaskschedulerservice.DeleteRequest{
+ Path: taskPath,
+ })
- if err != nil {
- log.Error().Err(err).Msg("Failed to delete task")
- return fmt.Errorf("delete task: %w", err)
- }
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to delete task")
+ return fmt.Errorf("delete task: %w", err)
+ }
- log.Info().Msg("Task deleted")
+ log.Info().Msg("Task deleted")
- return
+ return
}
diff --git a/pkg/goexec/wmi/module.go b/pkg/goexec/wmi/module.go
index 0aedd7e..1cad285 100644
--- a/pkg/goexec/wmi/module.go
+++ b/pkg/goexec/wmi/module.go
@@ -1,139 +1,143 @@
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"
+
+ _ "github.com/oiweiwei/go-msrpc/msrpc/erref/ntstatus"
+ _ "github.com/oiweiwei/go-msrpc/msrpc/erref/win32"
+ _ "github.com/oiweiwei/go-msrpc/msrpc/erref/wmi"
)
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) (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)
- }
+ 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)
+ }
}