Files
2025-09-26 09:16:34 -05:00

102 lines
3.7 KiB
Go

package dcomexec
import (
"context"
"fmt"
"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/iactivation/v0"
"github.com/oiweiwei/go-msrpc/msrpc/dcom/iremotescmactivator/v0"
"github.com/oiweiwei/go-msrpc/msrpc/dtyp"
"github.com/oiweiwei/go-msrpc/msrpc/erref/hresult"
_ "github.com/oiweiwei/go-msrpc/msrpc/erref/ntstatus"
_ "github.com/oiweiwei/go-msrpc/msrpc/erref/win32"
)
const (
OptRemoteCreateInstance = "RemoteCreateInstance"
OptRemoteActivation = "RemoteActivation"
)
// remoteCreateInstance creates a new instance of a COM class on a remote machine using RemoteCreateInstance (opnum 4).
func (m *Dcom) remoteCreateInstance(ctx context.Context, conn dcerpc.Conn, cls *uuid.UUID, iid *dcom.IID) (opts []dcerpc.Option, err error) {
if cls == nil {
return nil, fmt.Errorf("class ID is nil")
}
ap := &dcom.ActivationProperties{
DestinationContext: 2,
Properties: []dcom.ActivationProperty{
&dcom.InstantiationInfoData{
ClassID: (*dcom.ClassID)(dtyp.GUIDFromUUID(cls)),
IID: []*dcom.IID{iid},
ClientCOMVersion: m.comVersion,
},
&dcom.ActivationContextInfoData{},
&dcom.LocationInfoData{},
&dcom.SCMRequestInfoData{
RemoteRequest: &dcom.CustomRemoteRequestSCMInfo{
RequestedProtocolSequences: []uint16{7, 15}, // ncacn_ip_tcp, ncacn_np
},
},
},
}
apin, err := ap.ActivationPropertiesIn()
if err != nil {
return nil, err
}
act, err := iremotescmactivator.NewRemoteSCMActivatorClient(ctx, conn)
if err != nil {
return nil, err
}
cr, err := act.RemoteCreateInstance(ctx, &iremotescmactivator.RemoteCreateInstanceRequest{
ORPCThis: &dcom.ORPCThis{Version: m.comVersion},
ActPropertiesIn: apin,
})
if err != nil {
return nil, err
}
apout := new(dcom.ActivationProperties)
if err = apout.Parse(cr.ActPropertiesOut); err != nil {
return nil, err
}
if si := apout.SCMReplyInfoData(); si != nil {
opts = append(opts, normalizeStringBindings(si.RemoteReply.OXIDBindings.GetStringBindings())...)
} else {
return nil, fmt.Errorf("remote create instance response: SCMReplyInfoData is nil")
}
if pi := apout.PropertiesOutInfo(); pi != nil && pi.InterfaceData != nil && len(pi.InterfaceData) > 0 {
opts = append(opts, dcom.WithIPID(pi.InterfaceData[0].GetStandardObjectReference().Std.IPID))
} else {
return nil, fmt.Errorf("remote create instance response: PropertiesOutInfo is nil")
}
return opts, err
}
// remoteActivation activates a COM class on a remote machine using RemoteActivation (opnum 0).
func (m *Dcom) remoteActivation(ctx context.Context, conn dcerpc.Conn, cls *uuid.UUID, iid *dcom.IID) (opts []dcerpc.Option, err error) {
if cls == nil {
return nil, fmt.Errorf("class ID is nil")
}
ac, err := iactivation.NewActivationClient(ctx, conn)
if err != nil {
return nil, fmt.Errorf("init activation client: %w", err)
}
act, err := ac.RemoteActivation(ctx, &iactivation.RemoteActivationRequest{
ORPCThis: &dcom.ORPCThis{Version: m.comVersion},
ClassID: dtyp.GUIDFromUUID(cls),
IIDs: []*dcom.IID{iid},
RequestedProtocolSequences: []uint16{7, 15}, // ncacn_ip_tcp, ncacn_np
})
if err != nil {
return nil, fmt.Errorf("remote activation: %w", err)
}
if act.HResult != 0 {
return nil, hresult.FromCode(uint32(act.HResult))
}
return append(normalizeStringBindings(act.OXIDBindings.GetStringBindings()),
dcom.WithIPID(act.InterfaceData[0].GetStandardObjectReference().Std.IPID)), nil
}