Files

164 lines
4.5 KiB
Go

//go:build exclude
// rrp.go script dumps the windows registry keys on the remote machine (very slowly).
// NOTE that SMB cannot use security other than WithInsecure() and WithSeal().
package main
import (
"context"
"encoding/binary"
"encoding/hex"
"fmt"
"os"
"strings"
"github.com/oiweiwei/go-msrpc/dcerpc"
"github.com/oiweiwei/go-msrpc/msrpc/rrp/winreg/v1"
"github.com/oiweiwei/go-msrpc/ssp"
"github.com/oiweiwei/go-msrpc/ssp/credential"
"github.com/oiweiwei/go-msrpc/ssp/gssapi"
_ "github.com/oiweiwei/go-msrpc/msrpc/erref/win32"
)
func init() {
// add credentials.
gssapi.AddCredential(credential.NewFromPassword(os.Getenv("USERNAME"), os.Getenv("PASSWORD")))
// add mechanism.
gssapi.AddMechanism(ssp.SPNEGO)
gssapi.AddMechanism(ssp.NTLM)
}
func main() {
ctx := gssapi.NewSecurityContext(context.Background())
cc, err := dcerpc.Dial(ctx, os.Getenv("SERVER"), dcerpc.WithEndpoint("ncacn_np:[winreg]"))
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
cli, err := winreg.NewWinregClient(ctx, cc, dcerpc.WithSeal())
if err != nil {
fmt.Fprintln(os.Stderr, "cli", err)
os.Exit(1)
}
key, err := cli.OpenCurrentUser(ctx, &winreg.OpenCurrentUserRequest{
DesiredAccess: winreg.KeyQueryValue | winreg.KeyEnumerateSubKeys,
})
if err != nil {
fmt.Fprintln(os.Stderr, "key", err)
os.Exit(1)
}
k := "\\\\HCLASS_CURRENT_USER"
if err := RecursiveEnumerateKeys(ctx, cli, 0, k, key.Key); err != nil {
fmt.Fprintln(os.Stderr, "key", err)
os.Exit(1)
}
kkey, err := cli.BaseRegOpenKey(ctx, &winreg.BaseRegOpenKeyRequest{
Key: key.Key,
SubKey: &winreg.UnicodeString{
Buffer: "Software\\Classes\\Extensions\\ContractId\u0000",
},
DesiredAccess: winreg.KeyQueryValue | winreg.KeyEnumerateSubKeys,
})
if err != nil {
fmt.Fprintln(os.Stderr, "key", err)
os.Exit(1)
}
if err := RecursiveEnumerateKeys(ctx, cli, 0, k+"\\Software\\Classes\\Extensions\\ContractId", kkey.ResultKey); err != nil {
fmt.Fprintln(os.Stderr, "key", err)
os.Exit(1)
}
}
func RecursiveEnumerateKeys(ctx context.Context, cli winreg.WinregClient, i int, n string, h *winreg.Key) error {
info, err := cli.BaseRegQueryInfoKey(ctx, &winreg.BaseRegQueryInfoKeyRequest{
Key: h,
ClassIn: &winreg.UnicodeString{
MaximumLength: 1024,
},
})
if err != nil {
return fmt.Errorf("enumerate: query_info: %v", err)
}
fmt.Println(fmt.Sprintf("[%d]", i), n, fmt.Sprintf("[subkeys=%d, values=%d]", info.SubKeysCount, info.ValuesCount))
for i := 0; i < int(info.ValuesCount); i++ {
value, err := cli.BaseRegEnumValue(ctx, &winreg.BaseRegEnumValueRequest{
Key: h,
Index: uint32(i),
ValueNameIn: &winreg.UnicodeString{
MaximumLength: uint16(info.MaxValueNameLength) + 2,
},
DataLength: info.MaxValueLength,
})
if err != nil {
return err
}
switch t := fmt.Sprintf("{%d}", value.Type); value.Type {
case winreg.RegDword:
fmt.Println("\t", value.ValueNameOut.Buffer, "=", t, binary.LittleEndian.Uint32(value.Data))
case winreg.RegDwordBigEndian:
fmt.Println("\t", value.ValueNameOut.Buffer, "=", t, binary.BigEndian.Uint32(value.Data))
case winreg.RegMultistring:
fmt.Println("\t", value.ValueNameOut.Buffer, "=", t)
for i, b := range strings.Split(string(value.Data), string([]byte{0})) {
fmt.Println("\t\t", fmt.Sprintf("[%d]", i), b)
}
case winreg.RegQword:
fmt.Println("\t", value.ValueNameOut.Buffer, "=", t, binary.LittleEndian.Uint64(value.Data))
case winreg.RegNone:
fmt.Println("\t", value.ValueNameOut.Buffer, "=", t, "{NONE}")
case winreg.RegString, winreg.RegExpandString:
fmt.Println("\t", value.ValueNameOut.Buffer, "=", t, string(value.Data))
default:
fmt.Println("\t", value.ValueNameOut.Buffer, "=", t, hex.EncodeToString(value.Data))
}
}
for i := 0; i < int(info.SubKeysCount); i++ {
sub, err := cli.BaseRegEnumKey(ctx, &winreg.BaseRegEnumKeyRequest{
Key: h,
Index: uint32(i),
NameIn: &winreg.UnicodeString{
MaximumLength: uint16(info.MaxSubKeyLength) + 2,
},
ClassIn: &winreg.UnicodeString{
MaximumLength: uint16(info.MaxClassLength) + 2,
},
LastWriteTime: info.LastWriteTime,
})
if err != nil {
return fmt.Errorf("enumerate: enum_keys: %v", err)
}
open, err := cli.BaseRegOpenKey(ctx, &winreg.BaseRegOpenKeyRequest{
Key: h,
SubKey: sub.NameOut,
DesiredAccess: winreg.KeyQueryValue | winreg.KeyEnumerateSubKeys,
})
if err != nil {
return fmt.Errorf("open: sub_key: %v", err)
}
RecursiveEnumerateKeys(ctx, cli, i, n+"\\"+sub.NameOut.Buffer, open.ResultKey)
}
return nil
}