mirror of
https://github.com/oiweiwei/go-msrpc
synced 2026-06-08 16:28:58 +00:00
233 lines
6.1 KiB
Go
233 lines
6.1 KiB
Go
//go:build ignore
|
|
|
|
// csra_enum_certdb.go performs enumeration of certificate database tables using CSRA interface.
|
|
// Usage:
|
|
//
|
|
// go run csra_enum_certdb.go username%password@ncacn_ip_tcp:dc01.msad.local[privacy] --count=10 --table=req --authority=msad-DC01-CA-1
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/oiweiwei/go-msrpc/dcerpc"
|
|
"github.com/oiweiwei/go-msrpc/midl/uuid"
|
|
|
|
"github.com/oiweiwei/go-msrpc/ssp/gssapi"
|
|
|
|
config "github.com/oiweiwei/go-msrpc/config"
|
|
config_flag "github.com/oiweiwei/go-msrpc/config/flag"
|
|
|
|
"github.com/oiweiwei/go-msrpc/msrpc/dcom"
|
|
csra_client "github.com/oiweiwei/go-msrpc/msrpc/dcom/csra/client"
|
|
"github.com/oiweiwei/go-msrpc/msrpc/dcom/csra/icertadmind/v0"
|
|
"github.com/oiweiwei/go-msrpc/msrpc/dcom/csra/icertadmind2/v0"
|
|
"github.com/oiweiwei/go-msrpc/msrpc/dcom/iactivation/v0"
|
|
"github.com/oiweiwei/go-msrpc/msrpc/dcom/iobjectexporter/v0"
|
|
"github.com/oiweiwei/go-msrpc/msrpc/dtyp"
|
|
|
|
"github.com/oiweiwei/go-msrpc/msrpc/erref/hresult"
|
|
_ "github.com/oiweiwei/go-msrpc/msrpc/erref/hresult"
|
|
_ "github.com/oiweiwei/go-msrpc/msrpc/erref/ntstatus"
|
|
_ "github.com/oiweiwei/go-msrpc/msrpc/erref/win32"
|
|
|
|
. "github.com/oiweiwei/go-msrpc/examples/common"
|
|
)
|
|
|
|
var (
|
|
cfg = config.New()
|
|
count int
|
|
authority string
|
|
table string
|
|
)
|
|
|
|
func init() {
|
|
config_flag.BindFlags(cfg, flag.CommandLine)
|
|
flag.IntVar(&count, "count", 100, "Number of entries to fetch per page")
|
|
flag.StringVar(&authority, "authority", "msad-DC01-CA-1", "CA Authority name")
|
|
flag.StringVar(&table, "table", "request", "table to enumerate (request, extension, attribute, crl)")
|
|
}
|
|
|
|
func main() {
|
|
|
|
if err := config_flag.ParseAndValidate(cfg, flag.CommandLine); err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
return
|
|
}
|
|
|
|
var tableID uint32
|
|
|
|
switch table := strings.ToLower(table); {
|
|
case strings.HasPrefix(table, "req"):
|
|
tableID = 0x00000000
|
|
case strings.HasPrefix(table, "ext"):
|
|
tableID = 0x00003000
|
|
case strings.HasPrefix(table, "attr"):
|
|
tableID = 0x00004000
|
|
case strings.HasPrefix(table, "crl"):
|
|
tableID = 0x00005000
|
|
default:
|
|
fmt.Fprintln(os.Stderr, "unknown table:", table)
|
|
return
|
|
}
|
|
|
|
ctx := gssapi.NewSecurityContext(context.Background())
|
|
|
|
// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dcom/2be2642e-67a1-4690-883b-642b505ddb1d
|
|
|
|
// ObjectExporter uses well-known endpoint 135.
|
|
cc, err := dcerpc.Dial(ctx, cfg.ServerAddr(), cfg.DialOptions(ctx)...)
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, "dial_well_known_endpoint", err)
|
|
return
|
|
}
|
|
|
|
defer cc.Close(ctx)
|
|
|
|
// new object exporter client.
|
|
cli, err := iobjectexporter.NewObjectExporterClient(ctx, cc, cfg.ClientOptions(ctx)...)
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, "new_object_exporter", err)
|
|
return
|
|
}
|
|
|
|
// server-alive to determine the bindings.
|
|
srv, err := cli.ServerAlive2(ctx, &iobjectexporter.ServerAlive2Request{})
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, "server_alive2", err)
|
|
return
|
|
}
|
|
|
|
// new activation-client.
|
|
iact, err := iactivation.NewActivationClient(ctx, cc, cfg.ClientOptions(ctx)...)
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, "new_activation_client", err)
|
|
return
|
|
}
|
|
|
|
act, err := iact.RemoteActivation(ctx, &iactivation.RemoteActivationRequest{
|
|
ORPCThis: &dcom.ORPCThis{Version: srv.COMVersion},
|
|
ClassID: dtyp.GUIDFromUUID(uuid.MustParse("d99e6e73-fc88-11d0-b498-00a0c90312f3")), // CertAdminD2
|
|
IIDs: []*dcom.IID{icertadmind2.CertAdminD2IID},
|
|
// for TCP/IP it must be []uint16{7} / for named pipes: []uint16{15}.
|
|
RequestedProtocolSequences: []uint16{7, 15},
|
|
})
|
|
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, "remote_activation", err)
|
|
return
|
|
}
|
|
|
|
if act.HResult != 0 {
|
|
fmt.Fprintln(os.Stderr, hresult.FromCode(uint32(act.HResult)))
|
|
return
|
|
}
|
|
|
|
// dial WMI using OXID bindings. (use ncacn_tcp_ip).
|
|
conn, err := dcerpc.Dial(ctx, cfg.ServerAddr(), append(cfg.DialOptions(ctx), act.OXIDBindings.EndpointsByProtocol("ncacn_ip_tcp")...)...)
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, "dial_wmi_endpoint", err)
|
|
return
|
|
}
|
|
|
|
defer conn.Close(ctx)
|
|
|
|
// establish context that will be shared between NewLevel1LoginClient and
|
|
// NewServicesClient.
|
|
ctx = gssapi.NewSecurityContext(ctx)
|
|
|
|
csraCli, err := csra_client.NewClient(ctx, conn, cfg.ClientOptions(ctx)...)
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
return
|
|
}
|
|
|
|
csraCli = csraCli.IPID(ctx, act.InterfaceData[0].IPID())
|
|
|
|
_, err = csraCli.CertAdminD2().Ping2(ctx, &icertadmind2.Ping2Request{
|
|
This: &dcom.ORPCThis{Version: srv.COMVersion},
|
|
})
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
return
|
|
}
|
|
|
|
columns, err := csraCli.CertAdminD2().EnumViewColumnTable(ctx, &icertadmind2.EnumViewColumnTableRequest{
|
|
This: &dcom.ORPCThis{Version: srv.COMVersion},
|
|
Table: tableID,
|
|
Authority: authority,
|
|
ColumnCount: 100,
|
|
})
|
|
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
return
|
|
}
|
|
|
|
index := make(map[uint32]string)
|
|
|
|
dbColumns, err := columns.ColumnInfo.Columns(int(columns.ColumnOutCount))
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
return
|
|
}
|
|
|
|
var colsOut []uint32
|
|
|
|
for i := range dbColumns {
|
|
index[dbColumns[i].Index] = dbColumns[i].Name
|
|
colsOut = append(colsOut, dbColumns[i].Index)
|
|
}
|
|
|
|
ret := []map[string]any{}
|
|
|
|
view, err := csraCli.CertAdminD2().CertAdminD().OpenView(ctx, &icertadmind.OpenViewRequest{
|
|
This: &dcom.ORPCThis{Version: srv.COMVersion},
|
|
Authority: authority,
|
|
ColumnsOut: colsOut,
|
|
ID: 1,
|
|
Count: uint32(count),
|
|
})
|
|
|
|
defer func() {
|
|
_, err := csraCli.CertAdminD2().CertAdminD().CloseView(ctx, &icertadmind.CloseViewRequest{
|
|
This: &dcom.ORPCThis{Version: srv.COMVersion},
|
|
Authority: authority,
|
|
})
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, "close_view", err)
|
|
}
|
|
}()
|
|
|
|
resultRows := view.ResultRows
|
|
|
|
if err != nil && !errors.Is(err, hresult.ErrorArithmeticOverflow) {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
return
|
|
}
|
|
|
|
rows, _, err := resultRows.Rows()
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, "parse rows", err)
|
|
return
|
|
}
|
|
|
|
for i := range rows {
|
|
o := make(map[string]any)
|
|
for _, col := range rows[i].Columns {
|
|
o["@RowID"] = rows[i].ID
|
|
if val, _ := col.Value(); val != nil {
|
|
o[index[col.Index]] = val
|
|
}
|
|
}
|
|
ret = append(ret, o)
|
|
}
|
|
|
|
fmt.Println(J(ret))
|
|
|
|
}
|