Generated from Manticore v1.1.6 • 388 packages. View on pkg.go.dev

ms_rrp

import "github.com/TheManticoreProject/Manticore/network/dcerpc/ms-protocols/ms-rrp"

Package ms_rrp implements the high-level MS-RRP (Windows Remote Registry Protocol) client API over the winreg DCE/RPC interface (338cd001-2244-31f1-aaaa-900038001003 v1.0), carried over the \winreg named pipe on the IPC$ tree.

It is the protocol layer above the interface: callers hold a connected and authenticated SMB client and drive a RemoteRegistry, which binds winreg once and then exposes every interface method by its exact name (OpenLocalMachine, BaseRegOpenKey, BaseRegQueryValue, …) as a method on the struct, plus a small set of ergonomic, reg.exe-style helpers (OpenKeyByPath, QueryValueByPath, EnumKeys, …).

Unlike the stateless MS-SRVS layer, registry context handles CHAIN (HKLM -> subkey -> close) and are scoped to the RPC association, so RemoteRegistry binds a SINGLE \winreg pipe in Connect and reuses it for the lifetime of the client; a handle obtained on one association cannot be used on another. Close tears the pipe down, which releases any server-side handles.

References:

  • [MS-RRP] 3.1.5 winreg method behaviours; 2.2.4 REGSAM; [MS-ERREF] 2.2 Win32 codes
  • [MS-RPCE] DCE/RPC over SMB named pipes

Index

Constants

REGSAM access rights ([MS-RRP] 2.2.4), re-exported from the winreg interface and typed as ndr.DWORD so they can be passed directly as the samDesired argument of the Open* / BaseRegOpenKey / BaseRegCreateKey methods without conversion or importing the interface package.

const (
    KeyQueryValue       = ndr.DWORD(winreg.KeyQueryValue)
    KeySetValue         = ndr.DWORD(winreg.KeySetValue)
    KeyCreateSubKey     = ndr.DWORD(winreg.KeyCreateSubKey)
    KeyEnumerateSubKeys = ndr.DWORD(winreg.KeyEnumerateSubKeys)
    KeyNotify           = ndr.DWORD(winreg.KeyNotify)
    KeyCreateLink       = ndr.DWORD(winreg.KeyCreateLink)
    KeyWow6464Key       = ndr.DWORD(winreg.KeyWow64_64Key)
    KeyWow6432Key       = ndr.DWORD(winreg.KeyWow64_32Key)
    KeyRead             = ndr.DWORD(winreg.KeyRead)
    KeyWrite            = ndr.DWORD(winreg.KeyWrite)
    KeyExecute          = ndr.DWORD(winreg.KeyExecute)
    KeyAllAccess        = ndr.DWORD(winreg.KeyAllAccess)

    // MaximumAllowed is MAXIMUM_ALLOWED ([MS-DTYP] 2.4.3): grant the most access the caller
    // is permitted.
    MaximumAllowed = maximumAllowed
)

dwOptions for BaseRegCreateKey ([MS-RRP] 3.1.5.7), re-exported and typed as ndr.DWORD.

const (
    RegOptionNonVolatile = ndr.DWORD(winreg.RegOptionNonVolatile)
    RegOptionVolatile    = ndr.DWORD(winreg.RegOptionVolatile)
)

Registry value types (the RegistryValue.Type / dwType field) ([MS-RRP] 3.1.1.6), re-exported from the winreg interface as plain uint32 to match RegistryValue.Type.

const (
    RegNone     = winreg.RegNone
    RegSz       = winreg.RegSz
    RegExpandSz = winreg.RegExpandSz
    RegBinary   = winreg.RegBinary
    RegDword    = winreg.RegDword
    RegLink     = winreg.RegLink
    RegMultiSz  = winreg.RegMultiSz
    RegQword    = winreg.RegQword
)

Key-creation disposition values returned by BaseRegCreateKey / CreateKeyByPath ([MS-RRP] 3.1.5.7).

const (
    RegCreatedNewKey     = winreg.RegCreatedNewKey
    RegOpenedExistingKey = winreg.RegOpenedExistingKey
)

Variables

ErrNotConnected is returned by methods invoked before a successful Connect.

var ErrNotConnected = errors.New("ms_rrp: not connected; call Connect first")

type Handle

Handle is an open registry key context handle returned by the Open*/BaseRegCreateKey/ BaseRegOpenKey methods. It aliases the interface’s RPC_HKEY so it can be passed back to any method without conversion.

type Handle = msrrp.RPC_HKEY

type PipeDialer

PipeDialer is the SMB capability MS-RRP needs: opening a named-pipe transport over an established session. It is an alias of msproto.PipeDialer, shared with the other named-pipe protocols; network/smb/client.Client satisfies it.

type PipeDialer = msproto.PipeDialer

type RegistryValue

RegistryValue is a typed registry value: its REG_* type and its raw little-endian data bytes, exactly as carried on the wire. The decode helpers (String, Uint32, …) project the bytes per Type; the constructor helpers (StringValue, DwordValue, …) build the bytes for SetValue.

type RegistryValue struct {
    Type uint32
    Data []byte
}

func BinaryValue

func BinaryValue(b []byte) RegistryValue

BinaryValue builds a REG_BINARY value from raw bytes.

func DwordValue

func DwordValue(v uint32) RegistryValue

DwordValue builds a REG_DWORD value (little-endian).

func ExpandStringValue

func ExpandStringValue(s string) RegistryValue

ExpandStringValue builds a REG_EXPAND_SZ value from a Go string.

func MultiStringValue

func MultiStringValue(items []string) RegistryValue

MultiStringValue builds a REG_MULTI_SZ value: each string NUL-terminated, the block terminated by a final empty string.

func QwordValue

func QwordValue(v uint64) RegistryValue

QwordValue builds a REG_QWORD value (little-endian).

func StringValue

func StringValue(s string) RegistryValue

StringValue builds a REG_SZ value from a Go string.

func (RegistryValue) MultiString

func (v RegistryValue) MultiString() []string

MultiString decodes a REG_MULTI_SZ: a sequence of UTF-16LE strings, each NUL-terminated, the whole terminated by an empty string. Empty trailing entries are dropped.

func (RegistryValue) String

func (v RegistryValue) String() string

String decodes REG_SZ / REG_EXPAND_SZ / REG_LINK as a UTF-16LE string (trailing NULs stripped). For other types it returns the empty string; use the type-specific helpers.

func (RegistryValue) Uint32

func (v RegistryValue) Uint32() (uint32, bool)

Uint32 decodes a REG_DWORD (little-endian). ok is false if the data is too short.

func (RegistryValue) Uint64

func (v RegistryValue) Uint64() (uint64, bool)

Uint64 decodes a REG_QWORD (little-endian). ok is false if the data is too short.

type RemoteRegistry

RemoteRegistry is the connected MS-RRP client. It carries the binder for the session it is reached over and, once Connect has run, the single bound \winreg association that all method calls and chained key handles share. It is a msproto.Session: registry handles chain and are scoped to that one association.

type RemoteRegistry struct {
    // contains filtered or unexported fields
}

func New

func New(dialer PipeDialer) *RemoteRegistry

New returns a RemoteRegistry over the given pipe dialer (typically a *network/smb/client.Client). The dialer MUST be connected, authenticated, and tree-connected to IPC$ before Connect is called.

func (*RemoteRegistry) BaseRegCloseKey

func (r *RemoteRegistry) BaseRegCloseKey(hKey msrrp.PRPC_HKEY) (msrrp.PRPC_HKEY, error)

BaseRegCloseKey calls BaseRegCloseKey (opnum 5): releases an open key handle.

func (*RemoteRegistry) BaseRegCreateKey

func (r *RemoteRegistry) BaseRegCreateKey(hKey msrrp.RPC_HKEY, lpSubKey msrrp.RRP_UNICODE_STRING, lpClass msrrp.RRP_UNICODE_STRING, dwOptions ndr.DWORD, samDesired ndr.DWORD, lpSecurityAttributes *msrrp.RPC_SECURITY_ATTRIBUTES, lpdwDisposition *ndr.DWORD) (msrrp.PRPC_HKEY, *ndr.DWORD, error)

BaseRegCreateKey calls BaseRegCreateKey (opnum 6): creates or opens a subkey.

func (*RemoteRegistry) BaseRegDeleteKey

func (r *RemoteRegistry) BaseRegDeleteKey(hKey msrrp.RPC_HKEY, lpSubKey msrrp.RRP_UNICODE_STRING) error

BaseRegDeleteKey calls BaseRegDeleteKey (opnum 7): deletes a subkey with no subkeys.

func (*RemoteRegistry) BaseRegDeleteKeyEx

func (r *RemoteRegistry) BaseRegDeleteKeyEx(hKey msrrp.RPC_HKEY, lpSubKey msrrp.RRP_UNICODE_STRING, accessMask ndr.DWORD, reserved ndr.DWORD) error

BaseRegDeleteKeyEx calls BaseRegDeleteKeyEx (opnum 35): deletes a subkey honouring the KEY_WOW64_* view selected by accessMask.

func (*RemoteRegistry) BaseRegDeleteValue

func (r *RemoteRegistry) BaseRegDeleteValue(hKey msrrp.RPC_HKEY, lpValueName msrrp.RRP_UNICODE_STRING) error

BaseRegDeleteValue calls BaseRegDeleteValue (opnum 8): removes a named value.

func (*RemoteRegistry) BaseRegEnumKey

func (r *RemoteRegistry) BaseRegEnumKey(hKey msrrp.RPC_HKEY, dwIndex ndr.DWORD, lpNameIn msrrp.RRP_UNICODE_STRING, lpClassIn *msrrp.RRP_UNICODE_STRING, lpftLastWriteTime *msdtyp.FILETIME) (msrrp.RRP_UNICODE_STRING, *msdtyp.RPC_UNICODE_STRING, *msdtyp.FILETIME, error)

BaseRegEnumKey calls BaseRegEnumKey (opnum 9): returns the subkey at dwIndex.

func (*RemoteRegistry) BaseRegEnumValue

func (r *RemoteRegistry) BaseRegEnumValue(hKey msrrp.RPC_HKEY, dwIndex ndr.DWORD, lpValueNameIn msrrp.RRP_UNICODE_STRING, lpType *ndr.DWORD, lpData []uint8, lpcbData *ndr.DWORD, lpcbLen *ndr.DWORD) (msdtyp.RPC_UNICODE_STRING, *ndr.DWORD, []uint8, *ndr.DWORD, *ndr.DWORD, error)

BaseRegEnumValue calls BaseRegEnumValue (opnum 10): returns the value at dwIndex.

func (*RemoteRegistry) BaseRegFlushKey

func (r *RemoteRegistry) BaseRegFlushKey(hKey msrrp.RPC_HKEY) error

BaseRegFlushKey calls BaseRegFlushKey (opnum 11): writes a key’s changes to disk.

func (*RemoteRegistry) BaseRegGetKeySecurity

func (r *RemoteRegistry) BaseRegGetKeySecurity(hKey msrrp.RPC_HKEY, securityInformation ndr.DWORD, pRpcSecurityDescriptorIn msrrp.RPC_SECURITY_DESCRIPTOR) (msrrp.RPC_SECURITY_DESCRIPTOR, error)

BaseRegGetKeySecurity calls BaseRegGetKeySecurity (opnum 12): returns the parts of a key’s security descriptor selected by securityInformation (an OWNER/GROUP/DACL/SACL bitmask).

func (*RemoteRegistry) BaseRegGetVersion

func (r *RemoteRegistry) BaseRegGetVersion(hKey msrrp.RPC_HKEY) (ndr.DWORD, error)

BaseRegGetVersion calls BaseRegGetVersion (opnum 26): returns the registry version.

func (*RemoteRegistry) BaseRegLoadKey

func (r *RemoteRegistry) BaseRegLoadKey(hKey msrrp.RPC_HKEY, lpSubKey msrrp.RRP_UNICODE_STRING, lpFile msrrp.RRP_UNICODE_STRING) error

BaseRegLoadKey calls BaseRegLoadKey (opnum 13): loads a hive file under a subkey.

func (*RemoteRegistry) BaseRegOpenKey

func (r *RemoteRegistry) BaseRegOpenKey(hKey msrrp.RPC_HKEY, lpSubKey msrrp.RRP_UNICODE_STRING, dwOptions ndr.DWORD, samDesired ndr.DWORD) (msrrp.PRPC_HKEY, error)

BaseRegOpenKey calls BaseRegOpenKey (opnum 15): opens an existing subkey.

func (*RemoteRegistry) BaseRegQueryInfoKey

func (r *RemoteRegistry) BaseRegQueryInfoKey(hKey msrrp.RPC_HKEY, lpClassIn msrrp.RRP_UNICODE_STRING) (msdtyp.RPC_UNICODE_STRING, ndr.DWORD, ndr.DWORD, ndr.DWORD, ndr.DWORD, ndr.DWORD, ndr.DWORD, ndr.DWORD, msdtyp.FILETIME, error)

BaseRegQueryInfoKey calls BaseRegQueryInfoKey (opnum 16): returns subkey/value counts, maximum lengths, and the last-write time of a key.

func (*RemoteRegistry) BaseRegQueryMultipleValues

func (r *RemoteRegistry) BaseRegQueryMultipleValues(hKey msrrp.RPC_HKEY, val_listIn []msrrp.RVALENT, num_vals ndr.DWORD, lpvalueBuf []byte, ldwTotsize ndr.DWORD) ([]msrrp.RVALENT, []byte, ndr.DWORD, error)

BaseRegQueryMultipleValues calls BaseRegQueryMultipleValues (opnum 29).

func (*RemoteRegistry) BaseRegQueryMultipleValues2

func (r *RemoteRegistry) BaseRegQueryMultipleValues2(hKey msrrp.RPC_HKEY, val_listIn []msrrp.RVALENT, num_vals ndr.DWORD, lpvalueBuf []byte, ldwTotsize ndr.DWORD) ([]msrrp.RVALENT, []byte, ndr.DWORD, error)

BaseRegQueryMultipleValues2 calls BaseRegQueryMultipleValues2 (opnum 34).

func (*RemoteRegistry) BaseRegQueryValue

func (r *RemoteRegistry) BaseRegQueryValue(hKey msrrp.RPC_HKEY, lpValueName msrrp.RRP_UNICODE_STRING, lpType *ndr.DWORD, lpData []uint8, lpcbData *ndr.DWORD, lpcbLen *ndr.DWORD) (*ndr.DWORD, []uint8, *ndr.DWORD, *ndr.DWORD, error)

BaseRegQueryValue calls BaseRegQueryValue (opnum 17). It mirrors the interface function exactly (minus the invoker); for ergonomic reads use QueryValueByPath / queryValue.

func (*RemoteRegistry) BaseRegReplaceKey

func (r *RemoteRegistry) BaseRegReplaceKey(hKey msrrp.RPC_HKEY, lpSubKey msrrp.RRP_UNICODE_STRING, lpNewFile msrrp.RRP_UNICODE_STRING, lpOldFile msrrp.RRP_UNICODE_STRING) error

BaseRegReplaceKey calls BaseRegReplaceKey (opnum 18).

func (*RemoteRegistry) BaseRegRestoreKey

func (r *RemoteRegistry) BaseRegRestoreKey(hKey msrrp.RPC_HKEY, lpFile msrrp.RRP_UNICODE_STRING, flags ndr.DWORD) error

BaseRegRestoreKey calls BaseRegRestoreKey (opnum 19).

func (*RemoteRegistry) BaseRegSaveKey

func (r *RemoteRegistry) BaseRegSaveKey(hKey msrrp.RPC_HKEY, lpFile msrrp.RRP_UNICODE_STRING, pSecurityAttributes *msrrp.RPC_SECURITY_ATTRIBUTES) error

BaseRegSaveKey calls BaseRegSaveKey (opnum 20): saves a key and its subtree to a file.

func (*RemoteRegistry) BaseRegSaveKeyEx

func (r *RemoteRegistry) BaseRegSaveKeyEx(hKey msrrp.RPC_HKEY, lpFile msrrp.RRP_UNICODE_STRING, pSecurityAttributes *msrrp.RPC_SECURITY_ATTRIBUTES, flags ndr.DWORD) error

BaseRegSaveKeyEx calls BaseRegSaveKeyEx (opnum 31): saves a key with format flags.

func (*RemoteRegistry) BaseRegSetKeySecurity

func (r *RemoteRegistry) BaseRegSetKeySecurity(hKey msrrp.RPC_HKEY, securityInformation ndr.DWORD, pRpcSecurityDescriptor msrrp.RPC_SECURITY_DESCRIPTOR) error

BaseRegSetKeySecurity calls BaseRegSetKeySecurity (opnum 21): sets the parts of a key’s security descriptor selected by securityInformation.

func (*RemoteRegistry) BaseRegSetValue

func (r *RemoteRegistry) BaseRegSetValue(hKey msrrp.RPC_HKEY, lpValueName msrrp.RRP_UNICODE_STRING, dwType ndr.DWORD, lpData []uint8, cbData ndr.DWORD) error

BaseRegSetValue calls BaseRegSetValue (opnum 22): writes a value’s type and data.

func (*RemoteRegistry) BaseRegUnLoadKey

func (r *RemoteRegistry) BaseRegUnLoadKey(hKey msrrp.RPC_HKEY, lpSubKey msrrp.RRP_UNICODE_STRING) error

BaseRegUnLoadKey calls BaseRegUnLoadKey (opnum 23): unloads a previously loaded hive.

func (*RemoteRegistry) Close

func (r *RemoteRegistry) Close() error

Close tears down the winreg association, releasing any server-side key handles still open on it. It is safe to call on a client that was never connected.

func (*RemoteRegistry) Connect

func (r *RemoteRegistry) Connect() error

Connect opens the \winreg pipe and binds the winreg abstract syntax, establishing the single association that all subsequent calls and key handles use. It is idempotent: calling it on an already-connected client is a no-op.

func (*RemoteRegistry) CreateKeyByPath

func (r *RemoteRegistry) CreateKeyByPath(keyPath string, samDesired ndr.DWORD) (Handle, ndr.DWORD, error)

CreateKeyByPath creates (or opens, if it already exists) the key at keyPath, returning the new handle and the disposition (RegCreatedNewKey / RegOpenedExistingKey). The caller must BaseRegCloseKey the returned handle.

func (*RemoteRegistry) DeleteKeyByPath

func (r *RemoteRegistry) DeleteKeyByPath(keyPath string) error

DeleteKeyByPath deletes the key at keyPath. The key must have no subkeys (per BaseRegDeleteKey). Root keys cannot be deleted.

func (*RemoteRegistry) DeleteValueByPath

func (r *RemoteRegistry) DeleteValueByPath(keyPath, valueName string) error

DeleteValueByPath opens keyPath for write, removes valueName, and closes the key.

func (*RemoteRegistry) EnumKeys

func (r *RemoteRegistry) EnumKeys(h Handle) ([]string, error)

EnumKeys returns the names of all immediate subkeys of an open key, looping BaseRegEnumKey until ERROR_NO_MORE_ITEMS. Subkey names are capped at 255 UTF-16 code units by the registry, but the name/class buffers grow and retry the same index on ERROR_MORE_DATA to stay robust if a server reports a longer name. The server counts the terminating NUL in the returned name’s length, so it is stripped to yield a clean Go string usable as a path component.

func (*RemoteRegistry) EnumKeysByPath

func (r *RemoteRegistry) EnumKeysByPath(keyPath string) ([]string, error)

EnumKeysByPath opens keyPath, enumerates its subkeys, and closes the key.

func (*RemoteRegistry) EnumValues

func (r *RemoteRegistry) EnumValues(h Handle) ([]ValueEntry, error)

EnumValues returns all values of an open key, looping BaseRegEnumValue until ERROR_NO_MORE_ITEMS. The data buffer is negotiated per value: it grows and retries the same index on ERROR_MORE_DATA (e.g. values whose data exceeds the initial buffer). The server counts the terminating NUL in the returned value name’s length, so it is stripped.

func (*RemoteRegistry) EnumValuesByPath

func (r *RemoteRegistry) EnumValuesByPath(keyPath string) ([]ValueEntry, error)

EnumValuesByPath opens keyPath, enumerates its values, and closes the key.

func (*RemoteRegistry) Interface

func (r *RemoteRegistry) Interface() syntax.SyntaxID

Interface reports the DCE/RPC abstract syntax MS-RRP speaks (winreg v1.0).

func (*RemoteRegistry) IsConnected

func (r *RemoteRegistry) IsConnected() bool

IsConnected reports whether Connect has succeeded and Close has not yet run.

func (*RemoteRegistry) OpenClassesRoot

func (r *RemoteRegistry) OpenClassesRoot(serverName *ndr.WSTR, samDesired ndr.DWORD) (msrrp.PRPC_HKEY, error)

OpenClassesRoot calls OpenClassesRoot (opnum 0): opens HKEY_CLASSES_ROOT.

func (*RemoteRegistry) OpenCurrentConfig

func (r *RemoteRegistry) OpenCurrentConfig(serverName *ndr.WSTR, samDesired ndr.DWORD) (msrrp.PRPC_HKEY, error)

OpenCurrentConfig calls OpenCurrentConfig (opnum 27): opens HKEY_CURRENT_CONFIG.

func (*RemoteRegistry) OpenCurrentUser

func (r *RemoteRegistry) OpenCurrentUser(serverName *ndr.WSTR, samDesired ndr.DWORD) (msrrp.PRPC_HKEY, error)

OpenCurrentUser calls OpenCurrentUser (opnum 1): opens HKEY_CURRENT_USER.

func (*RemoteRegistry) OpenKeyByPath

func (r *RemoteRegistry) OpenKeyByPath(keyPath string, samDesired ndr.DWORD) (Handle, error)

OpenKeyByPath opens the key at a full path such as “HKLM\\SOFTWARE\\Microsoft”, with the requested access. The caller owns the returned handle and must BaseRegCloseKey it. The transient root handle is closed before returning.

func (*RemoteRegistry) OpenLocalMachine

func (r *RemoteRegistry) OpenLocalMachine(serverName *ndr.WSTR, samDesired ndr.DWORD) (msrrp.PRPC_HKEY, error)

OpenLocalMachine calls OpenLocalMachine (opnum 2): opens HKEY_LOCAL_MACHINE.

func (*RemoteRegistry) OpenPerformanceData

func (r *RemoteRegistry) OpenPerformanceData(serverName *ndr.WSTR, samDesired ndr.DWORD) (msrrp.PRPC_HKEY, error)

OpenPerformanceData calls OpenPerformanceData (opnum 3): opens HKEY_PERFORMANCE_DATA.

func (*RemoteRegistry) OpenPerformanceNlsText

func (r *RemoteRegistry) OpenPerformanceNlsText(serverName *ndr.WSTR, samDesired ndr.DWORD) (msrrp.PRPC_HKEY, error)

OpenPerformanceNlsText calls OpenPerformanceNlsText (opnum 33).

func (*RemoteRegistry) OpenPerformanceText

func (r *RemoteRegistry) OpenPerformanceText(serverName *ndr.WSTR, samDesired ndr.DWORD) (msrrp.PRPC_HKEY, error)

OpenPerformanceText calls OpenPerformanceText (opnum 32).

func (*RemoteRegistry) OpenUsers

func (r *RemoteRegistry) OpenUsers(serverName *ndr.WSTR, samDesired ndr.DWORD) (msrrp.PRPC_HKEY, error)

OpenUsers calls OpenUsers (opnum 4): opens HKEY_USERS.

func (*RemoteRegistry) QueryValueByPath

func (r *RemoteRegistry) QueryValueByPath(keyPath, valueName string) (RegistryValue, error)

QueryValueByPath opens keyPath for read, reads valueName, and closes the key.

func (*RemoteRegistry) SetValueByPath

func (r *RemoteRegistry) SetValueByPath(keyPath, valueName string, value RegistryValue) error

SetValueByPath opens keyPath for write, writes value under valueName, and closes the key.

type ValueEntry

ValueEntry pairs a value’s name with its typed data, as returned by EnumValues.

type ValueEntry struct {
    Name  string
    Value RegistryValue
}