aboutsummaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
authorBryan McNulty <bryanmcnulty@protonmail.com>2025-04-22 15:09:05 -0500
committerBryan McNulty <bryanmcnulty@protonmail.com>2025-04-22 15:09:05 -0500
commit4f30c57774947e9dd0664e60babadff9c3b1ebd9 (patch)
tree40de91ef9690d59f38e4ac1ddea5930ad48ab464 /pkg
parent9ba28f28184d7d8966a53abac2bec22dd581cde3 (diff)
downloadgoexec-4f30c57774947e9dd0664e60babadff9c3b1ebd9.tar.gz
goexec-4f30c57774947e9dd0664e60babadff9c3b1ebd9.zip
Fix ncacn_np transport with SCMR module
Diffstat (limited to 'pkg')
-rw-r--r--pkg/goexec/dce/client.go37
-rw-r--r--pkg/goexec/scmr/module.go260
2 files changed, 156 insertions, 141 deletions
diff --git a/pkg/goexec/dce/client.go b/pkg/goexec/dce/client.go
index 2fab71d..18400f6 100644
--- a/pkg/goexec/dce/client.go
+++ b/pkg/goexec/dce/client.go
@@ -6,6 +6,7 @@ import (
"github.com/RedTeamPentesting/adauth/smbauth"
"github.com/oiweiwei/go-msrpc/dcerpc"
"github.com/oiweiwei/go-msrpc/msrpc/epm/epm/v3"
+ msrpcSMB2 "github.com/oiweiwei/go-msrpc/smb2"
"github.com/rs/zerolog"
)
@@ -16,10 +17,6 @@ type Client struct {
hostname string
}
-func NewClient() *Client {
- return new(Client)
-}
-
func (c *Client) String() string {
return ClientName
}
@@ -50,20 +47,32 @@ func (c *Client) Connect(ctx context.Context) (err error) {
do = append(do, c.authOptions...)
if c.Smb {
- if smbDialer, err := smbauth.Dialer(ctx, c.Credential, c.Target, &smbauth.Options{}); err != nil {
+ c.DcerpcOptions = append(c.DcerpcOptions, dcerpc.WithInsecure())
+
+ var so []msrpcSMB2.DialerOption
+
+ if !c.NoSign {
+ so = append(so, msrpcSMB2.WithSign())
+ }
+ if !c.NoSeal {
+ so = append(so, msrpcSMB2.WithSeal())
+ }
+
+ if smbDialer, err := smbauth.Dialer(ctx, c.Credential, c.Target, &smbauth.Options{SMBOptions: so}); err != nil {
return fmt.Errorf("parse smb auth: %w", err)
+
} else {
do = append(do, dcerpc.WithSMBDialer(smbDialer))
}
- }
-
- if !c.NoSign {
- do = append(do, dcerpc.WithSign())
- eo = append(eo, dcerpc.WithSign())
- }
- if !c.NoSeal {
- do = append(do, dcerpc.WithSeal(), dcerpc.WithSecurityLevel(dcerpc.AuthLevelPktPrivacy))
- eo = append(eo, dcerpc.WithSeal(), dcerpc.WithSecurityLevel(dcerpc.AuthLevelPktPrivacy))
+ } else {
+ if !c.NoSign {
+ do = append(do, dcerpc.WithSign())
+ eo = append(eo, dcerpc.WithSign())
+ }
+ if !c.NoSeal {
+ do = append(do, dcerpc.WithSeal(), dcerpc.WithSecurityLevel(dcerpc.AuthLevelPktPrivacy))
+ eo = append(eo, dcerpc.WithSeal(), dcerpc.WithSecurityLevel(dcerpc.AuthLevelPktPrivacy))
+ }
}
if !c.NoLog {
diff --git a/pkg/goexec/scmr/module.go b/pkg/goexec/scmr/module.go
index 7b16247..708da23 100644
--- a/pkg/goexec/scmr/module.go
+++ b/pkg/goexec/scmr/module.go
@@ -1,186 +1,192 @@
package scmrexec
import (
- "context"
- "errors"
- "fmt"
- "github.com/FalconOpsLLC/goexec/internal/util"
- "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/scmr/svcctl/v2"
- "github.com/rs/zerolog"
+ "context"
+ "errors"
+ "fmt"
+ "github.com/FalconOpsLLC/goexec/internal/util"
+ "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/scmr/svcctl/v2"
+ "github.com/rs/zerolog"
)
type Scmr struct {
- goexec.Cleaner
+ goexec.Cleaner
- Client *dce.Client
- ctl svcctl.SvcctlClient
- scm *svcctl.Handle
+ Client *dce.Client
+ ctl svcctl.SvcctlClient
+ scm *svcctl.Handle
- hostname string
+ hostname string
}
const (
- ModuleName = "SCMR"
+ ModuleName = "SCMR"
- DefaultEndpoint = "ncacn_np:[svcctl]"
- ScmrUuid = "367ABB81-9844-35F1-AD32-98F038001003"
+ DefaultEndpoint = "ncacn_np:[svcctl]"
+ ScmrUuid = "367ABB81-9844-35F1-AD32-98F038001003"
)
func (m *Scmr) 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 *Scmr) 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.hostname, err = m.Client.Target.Hostname(ctx)
- if err != nil {
- log.Debug().Err(err).Msg("Failed to determine target hostname")
- }
- if m.hostname == "" {
- m.hostname = util.RandomHostname()
- }
-
- m.ctl, err = svcctl.NewSvcctlClient(ctx, m.Client.Dce(), dcerpc.WithObjectUUID(uuid.MustParse(ScmrUuid)))
- if err != nil {
- log.Error().Err(err).Msg("Failed to initialize SVCCTL client")
- return fmt.Errorf("create SVCCTL client: %w", err)
- }
- log.Info().Msg("Created SVCCTL client")
-
- resp, err := m.ctl.OpenSCMW(ctx, &svcctl.OpenSCMWRequest{
- MachineName: m.hostname,
- DatabaseName: "ServicesActive\x00",
- DesiredAccess: ServiceAllAccess, // TODO: Replace
- })
- if err != nil {
- log.Debug().Err(err).Msg("Failed to open SCM handle")
- return fmt.Errorf("open SCM handle: %w", err)
- }
- log.Info().Msg("Opened SCM handle")
-
- m.scm = resp.SCM
-
- 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.hostname, err = m.Client.Target.Hostname(ctx)
+ if err != nil {
+ log.Debug().Err(err).Msg("Failed to determine target hostname")
+ }
+ if m.hostname == "" {
+ m.hostname = util.RandomHostname()
+ }
+
+ svcctlOpts := []dcerpc.Option{dcerpc.WithObjectUUID(uuid.MustParse(ScmrUuid))}
+
+ if m.Client.Smb {
+ svcctlOpts = append(svcctlOpts, dcerpc.WithInsecure())
+ }
+
+ m.ctl, err = svcctl.NewSvcctlClient(ctx, m.Client.Dce(), svcctlOpts...)
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to initialize SVCCTL client")
+ return fmt.Errorf("create SVCCTL client: %w", err)
+ }
+ log.Info().Msg("Created SVCCTL client")
+
+ resp, err := m.ctl.OpenSCMW(ctx, &svcctl.OpenSCMWRequest{
+ MachineName: m.hostname,
+ DatabaseName: "ServicesActive",
+ DesiredAccess: ServiceAllAccess,
+ })
+ if err != nil {
+ log.Debug().Err(err).Msg("Failed to open SCM handle")
+ return fmt.Errorf("open SCM handle: %w", err)
+ }
+ log.Info().Msg("Opened SCM handle")
+
+ m.scm = resp.SCM
+
+ return
}
func (m *Scmr) Reconnect(ctx context.Context) (err error) {
- if err = m.Client.Reconnect(ctx); err != nil {
- return fmt.Errorf("reconnect: %w", err)
- }
- if err = m.Init(ctx); err != nil {
- return fmt.Errorf("reconnect SCMR: %w", err)
- }
- return
+ if err = m.Client.Reconnect(ctx); err != nil {
+ return fmt.Errorf("reconnect: %w", err)
+ }
+ if err = m.Init(ctx); err != nil {
+ return fmt.Errorf("reconnect SCMR: %w", err)
+ }
+ return
}
// openService will a handle to the desired service
func (m *Scmr) openService(ctx context.Context, name string) (svc *service, err error) {
- log := zerolog.Ctx(ctx)
+ log := zerolog.Ctx(ctx)
- resp, err := m.ctl.OpenServiceW(ctx, &svcctl.OpenServiceWRequest{
- ServiceManager: m.scm,
- ServiceName: name,
- DesiredAccess: ServiceAllAccess, // TODO: dynamic
- })
- if err != nil {
- log.Error().Err(err).Msg("Failed to open service handle")
- return nil, fmt.Errorf("open service: %w", err)
- }
+ resp, err := m.ctl.OpenServiceW(ctx, &svcctl.OpenServiceWRequest{
+ ServiceManager: m.scm,
+ ServiceName: name,
+ DesiredAccess: ServiceAllAccess, // TODO: dynamic
+ })
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to open service handle")
+ return nil, fmt.Errorf("open service: %w", err)
+ }
- log.Info().Msg("Opened service handle")
+ log.Info().Msg("Opened service handle")
- svc = new(service)
- svc.name = name
- svc.handle = resp.Service
+ svc = new(service)
+ svc.name = name
+ svc.handle = resp.Service
- return
+ return
}
func (m *Scmr) startService(ctx context.Context, svc *service) error {
- log := zerolog.Ctx(ctx).With().
- Str("service", svc.name).Logger()
+ log := zerolog.Ctx(ctx).With().
+ Str("service", svc.name).Logger()
- sr, err := m.ctl.StartServiceW(ctx, &svcctl.StartServiceWRequest{Service: svc.handle})
+ sr, err := m.ctl.StartServiceW(ctx, &svcctl.StartServiceWRequest{Service: svc.handle})
- if err != nil {
+ if err != nil {
- if errors.Is(err, context.DeadlineExceeded) { // Check if execution timed out (execute "cmd.exe /c notepad" for test case)
- log.Warn().Msg("Service execution deadline exceeded")
- svc.handle = nil
- return nil
+ if errors.Is(err, context.DeadlineExceeded) { // Check if execution timed out (execute "cmd.exe /c notepad" for test case)
+ log.Warn().Msg("Service execution deadline exceeded")
+ svc.handle = nil
+ return nil
- } else if sr.Return == ErrorServiceRequestTimeout {
- log.Info().Msg("Received request timeout. Execution was likely successful")
- return nil
- }
+ } else if sr.Return == ErrorServiceRequestTimeout {
+ log.Info().Msg("Received request timeout. Execution was likely successful")
+ return nil
+ }
- log.Error().Err(err).Msg("Failed to start service")
- return fmt.Errorf("start service: %w", err)
- }
- log.Info().Msg("Service started successfully")
- return nil
+ log.Error().Err(err).Msg("Failed to start service")
+ return fmt.Errorf("start service: %w", err)
+ }
+ log.Info().Msg("Service started successfully")
+ return nil
}
func (m *Scmr) deleteService(ctx context.Context, svc *service) (err error) {
- log := zerolog.Ctx(ctx).With().
- Str("service", svc.name).Logger()
+ log := zerolog.Ctx(ctx).With().
+ Str("service", svc.name).Logger()
- deleteResponse, err := m.ctl.DeleteService(ctx, &svcctl.DeleteServiceRequest{
- Service: svc.handle,
- })
+ deleteResponse, err := m.ctl.DeleteService(ctx, &svcctl.DeleteServiceRequest{
+ Service: svc.handle,
+ })
- if err != nil {
- log.Error().Err(err).Msg("Failed to delete service")
- return fmt.Errorf("delete service: %w", err)
- }
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to delete service")
+ return fmt.Errorf("delete service: %w", err)
+ }
- if deleteResponse.Return != 0 {
- log.Error().Err(err).Str("code", fmt.Sprintf("0x%02x", deleteResponse.Return)).Msg("Failed to delete service")
- return fmt.Errorf("delete service returned non-zero exit code: 0x%02x", deleteResponse.Return)
- }
+ if deleteResponse.Return != 0 {
+ log.Error().Err(err).Str("code", fmt.Sprintf("0x%02x", deleteResponse.Return)).Msg("Failed to delete service")
+ return fmt.Errorf("delete service returned non-zero exit code: 0x%02x", deleteResponse.Return)
+ }
- log.Info().Msg("Deleted service")
- return
+ log.Info().Msg("Deleted service")
+ return
}
func (m *Scmr) closeService(ctx context.Context, svc *service) (err error) {
- log := zerolog.Ctx(ctx).With().
- Str("service", svc.name).Logger()
+ log := zerolog.Ctx(ctx).With().
+ Str("service", svc.name).Logger()
- closResponse, err := m.ctl.CloseService(ctx, &svcctl.CloseServiceRequest{
- ServiceObject: svc.handle,
- })
+ closResponse, err := m.ctl.CloseService(ctx, &svcctl.CloseServiceRequest{
+ ServiceObject: svc.handle,
+ })
- if err != nil {
- log.Error().Err(err).Msg("Failed to close service handle")
- return fmt.Errorf("close service: %w", err)
- }
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to close service handle")
+ return fmt.Errorf("close service: %w", err)
+ }
- if closResponse.Return != 0 {
- log.Error().Err(err).Str("code", fmt.Sprintf("0x%02x", closResponse.Return)).Msg("Failed to close service handle")
- return fmt.Errorf("close service returned non-zero exit code: 0x%02x", closResponse.Return)
- }
+ if closResponse.Return != 0 {
+ log.Error().Err(err).Str("code", fmt.Sprintf("0x%02x", closResponse.Return)).Msg("Failed to close service handle")
+ return fmt.Errorf("close service returned non-zero exit code: 0x%02x", closResponse.Return)
+ }
- log.Info().Msg("Closed service handle")
- return
+ log.Info().Msg("Closed service handle")
+ return
}