Fixed proxy w/ EPM, fixed TSCH with ncacn_np

This commit is contained in:
Bryan McNulty
2025-04-22 15:49:46 -05:00
parent b76db931dc
commit ccef329bcd
5 changed files with 158 additions and 159 deletions
+1 -1
View File
@@ -40,7 +40,7 @@
## Bug Fixes
- [X] Fix SMB transport for SCMR module - `rpc_s_cannot_support: The requested operation is not supported.`
- [ ] Fix proxy - EPM, SMB don't use the proxy dialer
- [X] Fix proxy - EPM doesn't use the proxy dialer
- [ ] Fix SCMR `change` method so that dependencies field isn't permanently overwritten
## Lower Priority
+1 -1
View File
@@ -46,7 +46,7 @@ func registerExecutionFlags(fs *pflag.FlagSet) {
func registerExecutionOutputFlags(fs *pflag.FlagSet) {
fs.StringVarP(&outputPath, "out", "o", "", `Fetch execution output to file or "-" for standard output`)
fs.StringVarP(&outputMethod, "out-method", "m", "smb", "Method to fetch execution output")
fs.StringVar(&exec.Output.RemotePath, "out-remote", "", "Location to temporarily store output on remote filesystem")
//fs.StringVar(&exec.Output.RemotePath, "out-remote", "", "Location to temporarily store output on remote filesystem")
fs.BoolVar(&exec.Output.NoDelete, "no-delete-out", false, "Preserve output file on remote filesystem")
}
+67 -64
View File
@@ -1,107 +1,110 @@
package dce
import (
"context"
"fmt"
"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"
"context"
"fmt"
"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"
)
type Client struct {
Options
Options
conn dcerpc.Conn
hostname string
conn dcerpc.Conn
hostname string
}
func (c *Client) String() string {
return ClientName
return ClientName
}
func (c *Client) Reconnect(ctx context.Context, opts ...dcerpc.Option) (err error) {
c.DcerpcOptions = append(c.DcerpcOptions, opts...)
c.DcerpcOptions = append(c.DcerpcOptions, opts...)
return c.Connect(ctx)
return c.Connect(ctx)
}
func (c *Client) Dce() (dce dcerpc.Conn) {
return c.conn
return c.conn
}
func (c *Client) Logger(ctx context.Context) (log zerolog.Logger) {
return zerolog.Ctx(ctx).With().
Str("client", c.String()).Logger()
return zerolog.Ctx(ctx).With().
Str("client", c.String()).Logger()
}
func (c *Client) Connect(ctx context.Context) (err error) {
log := c.Logger(ctx)
ctx = log.WithContext(ctx)
log := c.Logger(ctx)
ctx = log.WithContext(ctx)
var do, eo []dcerpc.Option
var do, eo []dcerpc.Option
do = append(do, c.DcerpcOptions...)
do = append(do, c.authOptions...)
do = append(do, c.DcerpcOptions...)
do = append(do, c.authOptions...)
if c.Smb {
c.DcerpcOptions = append(c.DcerpcOptions, dcerpc.WithInsecure())
do = append(do, dcerpc.WithSeal())
var so []msrpcSMB2.DialerOption
if c.Smb {
var so []msrpcSMB2.DialerOption
if !c.NoSign {
so = append(so, msrpcSMB2.WithSign())
}
if !c.NoSeal {
so = append(so, msrpcSMB2.WithSeal())
}
if !c.NoSign {
so = append(so, msrpcSMB2.WithSign())
eo = append(eo, dcerpc.WithSign())
}
if !c.NoSeal {
so = append(so, msrpcSMB2.WithSeal())
eo = append(eo, dcerpc.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)
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))
}
} 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))
}
}
} else {
do = append(do, dcerpc.WithSMBDialer(smbDialer))
}
} else {
if !c.NoLog {
do = append(do, dcerpc.WithLogger(log))
eo = append(eo, dcerpc.WithLogger(log))
}
if !c.NoSign {
do = append(do, dcerpc.WithSign())
eo = append(eo, dcerpc.WithSign())
}
if !c.NoSeal {
do = append(do, dcerpc.WithSeal())
eo = append(eo, dcerpc.WithSeal())
}
}
if !c.NoEpm {
log.Debug().Msg("Using endpoint mapper")
if !c.NoLog {
do = append(do, dcerpc.WithLogger(log))
eo = append(eo, dcerpc.WithLogger(log))
}
eo = append(eo, c.epmOptions...)
eo = append(eo, c.authOptions...)
if !c.NoEpm {
log.Debug().Msg("Using endpoint mapper")
do = append(do, epm.EndpointMapper(ctx, c.Host, eo...))
}
eo = append(eo, c.EpmOptions...)
eo = append(eo, c.authOptions...)
for _, e := range c.stringBindings {
do = append(do, dcerpc.WithEndpoint(e.String()))
}
do = append(do, epm.EndpointMapper(ctx, c.Host, eo...))
}
if c.conn, err = dcerpc.Dial(ctx, c.Host, do...); err != nil {
for _, e := range c.stringBindings {
do = append(do, dcerpc.WithEndpoint(e.String()))
}
log.Error().Err(err).Msgf("Failed to connect to %s endpoint", c.String())
return fmt.Errorf("dial %s: %w", c.String(), err)
}
if c.conn, err = dcerpc.Dial(ctx, c.Host, do...); err != nil {
return
log.Error().Err(err).Msgf("Failed to connect to %s endpoint", c.String())
return fmt.Errorf("dial %s: %w", c.String(), err)
}
return
}
func (c *Client) Close(ctx context.Context) (err error) {
return c.conn.Close(ctx)
return c.conn.Close(ctx)
}
+87 -92
View File
@@ -1,118 +1,113 @@
package dce
import (
"context"
"fmt"
"github.com/FalconOpsLLC/goexec/pkg/goexec"
"github.com/RedTeamPentesting/adauth/dcerpcauth"
"github.com/oiweiwei/go-msrpc/dcerpc"
"net"
"context"
"fmt"
"github.com/FalconOpsLLC/goexec/pkg/goexec"
"github.com/RedTeamPentesting/adauth/dcerpcauth"
"github.com/oiweiwei/go-msrpc/dcerpc"
)
type Options struct {
goexec.ClientOptions
goexec.AuthOptions
goexec.ClientOptions
goexec.AuthOptions
// NoSign disables packet signing by omitting dcerpc.WithSign()
NoSign bool `json:"no_sign" yaml:"no_sign"`
// NoSign disables packet signing by omitting dcerpc.WithSign()
NoSign bool `json:"no_sign" yaml:"no_sign"`
// NoSeal disables packet stub encryption by omitting dcerpc.WithSeal()
NoSeal bool `json:"no_seal" yaml:"no_seal"`
// NoSeal disables packet stub encryption by omitting dcerpc.WithSeal()
NoSeal bool `json:"no_seal" yaml:"no_seal"`
// NoLog disables logging by omitting dcerpc.WithLogger(...)
NoLog bool `json:"no_log" yaml:"no_log"`
// NoLog disables logging by omitting dcerpc.WithLogger(...)
NoLog bool `json:"no_log" yaml:"no_log"`
// NoEpm disables DCE endpoint mapper communications
NoEpm bool `json:"no_epm" yaml:"no_epm"`
// NoEpm disables DCE endpoint mapper communications
NoEpm bool `json:"no_epm" yaml:"no_epm"`
// Endpoint stores the explicit DCE string binding to use
Endpoint string `json:"endpoint,omitempty" yaml:"endpoint,omitempty"`
// Endpoint stores the explicit DCE string binding to use
Endpoint string `json:"endpoint,omitempty" yaml:"endpoint,omitempty"`
// Filter stores the filter for returned endpoints from an endpoint mapper
Filter string `json:"filter,omitempty" yaml:"filter,omitempty"`
// Filter stores the filter for returned endpoints from an endpoint mapper
Filter string `json:"filter,omitempty" yaml:"filter,omitempty"`
// Smb enables SMB transport for DCE/RPC
Smb bool `json:"use_smb" yaml:"use_smb"`
// Smb enables SMB transport for DCE/RPC
Smb bool `json:"use_smb" yaml:"use_smb"`
netDialer goexec.Dialer
dialer dcerpc.Dialer
authOptions []dcerpc.Option
DcerpcOptions []dcerpc.Option
epmOptions []dcerpc.Option
stringBindings []*dcerpc.StringBinding
stringBindings []*dcerpc.StringBinding
dialer dcerpc.Dialer
authOptions []dcerpc.Option
DcerpcOptions []dcerpc.Option
EpmOptions []dcerpc.Option
}
func (c *Client) Parse(ctx context.Context) (err error) {
// Reset internals
{
c.netDialer = nil
c.dialer = nil
c.stringBindings = []*dcerpc.StringBinding{}
c.authOptions = []dcerpc.Option{}
c.DcerpcOptions = []dcerpc.Option{}
c.epmOptions = []dcerpc.Option{
dcerpc.WithSign(), // Require signing for EPM
}
}
// Reset internals
{
c.dialer = nil
c.stringBindings = []*dcerpc.StringBinding{}
c.authOptions = []dcerpc.Option{}
c.DcerpcOptions = []dcerpc.Option{}
c.EpmOptions = []dcerpc.Option{
dcerpc.WithSign(), // Require signing for EPM
}
}
if !c.NoSeal {
// Enable encryption
c.DcerpcOptions = append(c.DcerpcOptions, dcerpc.WithSeal(), dcerpc.WithSecurityLevel(dcerpc.AuthLevelPktPrivacy))
c.epmOptions = append(c.epmOptions, dcerpc.WithSeal(), dcerpc.WithSecurityLevel(dcerpc.AuthLevelPktPrivacy))
}
if !c.NoSign {
// Enable signing
c.DcerpcOptions = append(c.DcerpcOptions, dcerpc.WithSign())
//c.epmOptions = append(c.epmOptions, dcerpc.WithSign())
}
if !c.NoSeal {
// Enable encryption
c.DcerpcOptions = append(c.DcerpcOptions, dcerpc.WithSeal(), dcerpc.WithSecurityLevel(dcerpc.AuthLevelPktPrivacy))
c.EpmOptions = append(c.EpmOptions, dcerpc.WithSeal(), dcerpc.WithSecurityLevel(dcerpc.AuthLevelPktPrivacy))
}
if !c.NoSign {
// Enable signing
c.DcerpcOptions = append(c.DcerpcOptions, dcerpc.WithSign())
//c.EpmOptions = append(c.EpmOptions, dcerpc.WithSign())
}
// Parse DCERPC endpoint
if c.Endpoint != "" {
sb, err := dcerpc.ParseStringBinding(c.Endpoint)
if err != nil {
return err
}
if sb.ProtocolSequence == dcerpc.ProtocolSequenceNamedPipe {
c.Smb = true
}
c.stringBindings = append(c.stringBindings, sb)
}
// Parse DCERPC endpoint
if c.Endpoint != "" {
sb, err := dcerpc.ParseStringBinding(c.Endpoint)
if err != nil {
return err
}
if sb.ProtocolSequence == dcerpc.ProtocolSequenceNamedPipe {
c.Smb = true
}
c.stringBindings = append(c.stringBindings, sb)
}
// Parse EPM filter
if c.Filter != "" {
sb, err := dcerpc.ParseStringBinding(c.Filter)
if err != nil {
return err
}
if sb.ProtocolSequence == dcerpc.ProtocolSequenceNamedPipe {
c.Smb = true
}
c.stringBindings = append(c.stringBindings, sb)
}
// Parse EPM filter
if c.Filter != "" {
sb, err := dcerpc.ParseStringBinding(c.Filter)
if err != nil {
return err
}
if sb.ProtocolSequence == dcerpc.ProtocolSequenceNamedPipe {
c.Smb = true
}
c.stringBindings = append(c.stringBindings, sb)
}
if c.Proxy == "" {
c.netDialer = &net.Dialer{} // FUTURE: additional dial c
if c.Proxy != "" {
// Parse proxy URL
d, err := goexec.ParseProxyURI(c.Proxy)
if err != nil {
return err
}
var ok bool
if c.dialer, ok = d.(dcerpc.Dialer); !ok {
return fmt.Errorf("cannot cast %T to dcerpc.Dialer", d)
}
c.DcerpcOptions = append(c.DcerpcOptions, dcerpc.WithDialer(c.dialer))
c.EpmOptions = append(c.EpmOptions, dcerpc.WithDialer(c.dialer))
}
} else {
// Parse proxy URL
d, err := goexec.ParseProxyURI(c.Proxy)
if err != nil {
return err
}
var ok bool
if c.dialer, ok = d.(dcerpc.Dialer); !ok {
return fmt.Errorf("cannot cast %T to dcerpc.Dialer", d)
}
c.DcerpcOptions = append(c.DcerpcOptions, dcerpc.WithDialer(c.dialer))
}
// Parse authentication parameters
if c.authOptions, err = dcerpcauth.AuthenticationOptions(ctx, c.Credential, c.Target, &dcerpcauth.Options{}); err != nil {
return fmt.Errorf("parse auth c: %w", err)
}
// Parse authentication parameters
if c.authOptions, err = dcerpcauth.AuthenticationOptions(ctx, c.Credential, c.Target, &dcerpcauth.Options{}); err != nil {
return fmt.Errorf("parse auth c: %w", err)
}
c.Host = c.Target.AddressWithoutPort()
c.Host = c.Target.AddressWithoutPort()
return
return
}
+2 -1
View File
@@ -7,6 +7,7 @@ import (
"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"
)
@@ -51,7 +52,7 @@ func (m *Tsch) Init(ctx context.Context) (err error) {
}
// Create ITaskSchedulerService Client
m.tsch, err = itaskschedulerservice.NewTaskSchedulerServiceClient(ctx, m.Client.Dce())
m.tsch, err = itaskschedulerservice.NewTaskSchedulerServiceClient(ctx, m.Client.Dce(), dcerpc.WithSeal())
return
}