mirror of
https://github.com/oiweiwei/go-msrpc
synced 2026-06-08 16:28:58 +00:00
164 lines
4.5 KiB
Go
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
|
|
}
|