Skip to content

Repository files navigation

always-hku

Open the HKEY_USERS registry root of any Windows user by SID — even when that user is not logged on.

On Windows, HKEY_USERS\{SID} is only mounted while a user has an active session. For a user who is not logged on, their NTUSER.DAT hive is not in memory and must be loaded explicitly. always-hku does this for you and cleans up afterwards.

How it works

Open(sid, access) performs these steps:

  1. If HKU\{SID} already exists (user logged on, or hive already mounted), open it directly. Close will not unload it.
  2. Otherwise read the profile directory from HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\{SID} (the ProfileImagePath value).
  3. Load {ProfileDirectory}\NTUSER.DAT as HKU\tmp-{SID}.
  4. Close unloads the hive again — but only when this library loaded it.

Requirements

Loading a hive needs SeBackupPrivilege and SeRestorePrivilege, which a process normally holds only when running elevated (Administrator or SYSTEM). Open enables these privileges automatically; if they are not held it returns an error explaining that the process is likely not elevated.

Install

go get github.com/jc-lab/always-hku

Usage

package main

import (
	"fmt"
	"log"

	alwayshku "github.com/jc-lab/always-hku"
	"golang.org/x/sys/windows/registry"
)

func main() {
	const sid = "S-1-5-21-1111111111-2222222222-3333333333-1001"

	// Pass 0 for access to default to registry.READ.
	key, err := alwayshku.Open(sid, registry.READ)
	if err != nil {
		log.Fatal(err)
	}
	defer key.Close() // unloads the hive if it was loaded

	if key.Loaded() {
		fmt.Println("hive was loaded from NTUSER.DAT and will be unloaded on Close")
	}

	// UserKey embeds registry.Key, so use it like any opened key.
	names, err := key.ReadSubKeyNames(-1)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(names)
}

For write access, pass registry.WRITE or registry.ALL_ACCESS (the hive is loaded read/write in that case).

API

Symbol Description
Open(sid string, access uint32) (*UserKey, error) Open the user's registry root. access == 0 defaults to registry.READ.
(*UserKey).Close() error Close the key; unload the hive if this library loaded it. Idempotent.
(*UserKey).SID() string The SID the key was opened for.
(*UserKey).Loaded() bool Whether this library loaded the hive (so Close will unload it).
(*UserKey).MountName() string The HKEY_USERS subkey name: {SID} or tmp-{SID}.

UserKey embeds golang.org/x/sys/windows/registry.Key, exposing all of its methods (GetStringValue, ReadSubKeyNames, SetStringValue, ...).

Errors

  • ErrEmptySID — the SID was blank.
  • ErrProfileNotFound — no profile is registered for the SID under ProfileList.
  • ErrUnsupported — returned on non-Windows platforms.

License

See LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages