aboutsummaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
authorBryan McNulty <bryanmcnulty@protonmail.com>2025-04-26 04:37:05 -0500
committerBryan McNulty <bryanmcnulty@protonmail.com>2025-04-26 04:37:05 -0500
commit6c8dbb0a38f02316dfd17326d95a1b4a547cfeae (patch)
tree63983913a8a3f44e1b71106a03f1cb455287a6b5 /pkg
parentcbf293d06b869941b16c51da086a58dd9af58f04 (diff)
downloadgoexec-6c8dbb0a38f02316dfd17326d95a1b4a547cfeae.tar.gz
goexec-6c8dbb0a38f02316dfd17326d95a1b4a547cfeae.zip
`scmr`: `change`: Restore original lpBinaryPathName
Diffstat (limited to 'pkg')
-rw-r--r--pkg/goexec/scmr/change.go254
1 files changed, 127 insertions, 127 deletions
diff --git a/pkg/goexec/scmr/change.go b/pkg/goexec/scmr/change.go
index 014ad08..3dd506e 100644
--- a/pkg/goexec/scmr/change.go
+++ b/pkg/goexec/scmr/change.go
@@ -1,143 +1,143 @@
package scmrexec
import (
- "context"
- "fmt"
- "github.com/FalconOpsLLC/goexec/pkg/goexec"
- "github.com/oiweiwei/go-msrpc/msrpc/scmr/svcctl/v2"
- "github.com/rs/zerolog"
+ "context"
+ "errors"
+ "fmt"
+ "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 (
- MethodChange = "Change"
+ MethodChange = "Change"
)
type ScmrChange struct {
- Scmr
- goexec.Cleaner
- goexec.Executor
+ Scmr
+ goexec.Cleaner
+ goexec.Executor
- IO goexec.ExecutionIO
+ IO goexec.ExecutionIO
- NoStart bool
- ServiceName string
+ NoStart bool
+ ServiceName string
}
func (m *ScmrChange) Execute(ctx context.Context, in *goexec.ExecutionIO) (err error) {
- log := zerolog.Ctx(ctx).With().
- Str("service", m.ServiceName).
- Logger()
-
- svc := &service{name: m.ServiceName}
-
- openResponse, err := m.ctl.OpenServiceW(ctx, &svcctl.OpenServiceWRequest{
- ServiceManager: m.scm,
- ServiceName: svc.name,
- DesiredAccess: ServiceAllAccess,
- })
-
- if err != nil {
- log.Error().Err(err).Msg("Failed to open service handle")
- return fmt.Errorf("open service request: %w", err)
- }
- if openResponse.Return != 0 {
- log.Error().Err(err).Msg("Failed to open service handle")
- return fmt.Errorf("create service: %w", err)
- }
-
- svc.handle = openResponse.Service
- log.Info().Msg("Opened service handle")
-
- defer 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
- })
-
- // Note the original service configuration
- queryResponse, err := m.ctl.QueryServiceConfigW(ctx, &svcctl.QueryServiceConfigWRequest{
- Service: svc.handle,
- BufferLength: 8 * 1024,
- })
-
- if err != nil {
- log.Error().Err(err).Msg("Failed to fetch service configuration")
- return fmt.Errorf("get service config: %w", err)
- }
- if queryResponse.Return != 0 {
- log.Error().Err(err).Msg("Failed to query service configuration")
- return fmt.Errorf("query service config: %w", err)
- }
-
- log.Info().Str("binaryPath", queryResponse.ServiceConfig.BinaryPathName).Msg("Fetched original service configuration")
- svc.originalConfig = queryResponse.ServiceConfig
-
- stopResponse, err := m.ctl.ControlService(ctx, &svcctl.ControlServiceRequest{
- Service: svc.handle,
- Control: ServiceControlStop,
- })
-
- if err != nil {
- if stopResponse == nil || stopResponse.Return != ErrorServiceNotActive {
-
- log.Error().Err(err).Msg("Failed to stop existing service")
- return fmt.Errorf("stop service: %w", err)
- }
-
- log.Debug().Msg("Service is not running")
-
- // TODO: restore state
- /*
- defer m.AddCleaners(func(ctxInner context.Context) error {
- // ...
- return nil
- })
- */
-
- } else {
- log.Info().Msg("Stopped existing service")
- }
-
- changeResponse, err := m.ctl.ChangeServiceConfigW(ctx, &svcctl.ChangeServiceConfigWRequest{
- Service: svc.handle,
- BinaryPathName: in.String(),
- DisplayName: svc.originalConfig.DisplayName,
- ServiceType: svc.originalConfig.ServiceType,
- StartType: ServiceDemandStart,
- ErrorControl: svc.originalConfig.ErrorControl,
- LoadOrderGroup: svc.originalConfig.LoadOrderGroup,
- ServiceStartName: svc.originalConfig.ServiceStartName,
- TagID: svc.originalConfig.TagID,
- //Dependencies: []byte(svc.originalConfig.Dependencies), // TODO
- })
-
- if err != nil {
- log.Error().Err(err).Msg("Failed to request service configuration change")
- return fmt.Errorf("change service config request: %w", err)
- }
- if changeResponse.Return != 0 {
- log.Error().Err(err).Msg("Failed to change service configuration")
- return fmt.Errorf("change service config: %w", err)
- }
-
- if !m.NoStart {
-
- err = m.startService(ctx, svc)
- if err != nil {
- log.Error().Err(err).Msg("Failed to start service")
- }
- }
-
- return
+ log := zerolog.Ctx(ctx).With().
+ Str("service", m.ServiceName).
+ Logger()
+
+ svc := &service{name: m.ServiceName}
+
+ openResponse, err := m.ctl.OpenServiceW(ctx, &svcctl.OpenServiceWRequest{
+ ServiceManager: m.scm,
+ ServiceName: svc.name,
+ DesiredAccess: ServiceAllAccess,
+ })
+
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to open service handle")
+ return fmt.Errorf("open service request: %w", err)
+ }
+ if openResponse.Return != 0 {
+ log.Error().Err(err).Msg("Failed to open service handle")
+ return fmt.Errorf("create service: %w", err)
+ }
+
+ svc.handle = openResponse.Service
+ log.Info().Msg("Opened service handle")
+
+ defer m.AddCleaners(func(ctxInner context.Context) error {
+ return m.closeService(ctxInner, svc)
+ })
+
+ // Note the original service configuration
+ queryResponse, err := m.ctl.QueryServiceConfigW(ctx, &svcctl.QueryServiceConfigWRequest{
+ Service: svc.handle,
+ BufferLength: 8 * 1024,
+ })
+
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to fetch service configuration")
+ return fmt.Errorf("get service config: %w", err)
+ }
+
+ log.Info().Str("binaryPath", queryResponse.ServiceConfig.BinaryPathName).Msg("Fetched original service configuration")
+ svc.originalConfig = queryResponse.ServiceConfig
+
+ stopResponse, err := m.ctl.ControlService(ctx, &svcctl.ControlServiceRequest{
+ Service: svc.handle,
+ Control: ServiceControlStop,
+ })
+
+ if err != nil {
+ if stopResponse == nil || stopResponse.Return != ErrorServiceNotActive {
+
+ log.Error().Err(err).Msg("Failed to stop existing service")
+ return fmt.Errorf("stop service: %w", err)
+ }
+
+ log.Debug().Msg("Service is not running")
+
+ // FEATURE: restore state
+ /*
+ defer m.AddCleaners(func(ctxInner context.Context) error {
+ // ...
+ return nil
+ })
+ */
+
+ } else {
+ log.Info().Msg("Stopped existing service")
+ }
+
+ req := &svcctl.ChangeServiceConfigWRequest{
+ Service: svc.handle,
+ BinaryPathName: in.String(),
+ DisplayName: svc.originalConfig.DisplayName,
+ ServiceType: svc.originalConfig.ServiceType,
+ StartType: ServiceDemandStart,
+ ErrorControl: svc.originalConfig.ErrorControl,
+ LoadOrderGroup: svc.originalConfig.LoadOrderGroup,
+ ServiceStartName: svc.originalConfig.ServiceStartName,
+ TagID: svc.originalConfig.TagID,
+ //Dependencies: []byte(svc.originalConfig.Dependencies), // TODO
+ }
+
+ _, err = m.ctl.ChangeServiceConfigW(ctx, req)
+
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to request service configuration change")
+ return fmt.Errorf("change service config request: %w", err)
+ }
+
+ m.AddCleaners(func(ctxInner context.Context) error {
+ req.BinaryPathName = svc.originalConfig.BinaryPathName
+
+ if ctxInner.Err() != nil && errors.Is(ctxInner.Err(), context.DeadlineExceeded) {
+ ctxInner = context.WithoutCancel(context.Background())
+ }
+ _, err := m.ctl.ChangeServiceConfigW(ctxInner, req)
+
+ if err != nil {
+ return fmt.Errorf("restore service config: %w", err)
+ }
+ return nil
+ })
+
+ if !m.NoStart {
+
+ err = m.startService(ctx, svc)
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to start service")
+ }
+ }
+
+ return
}