i'm trying to watch all over the windows registry to find some keys and values. There are some keys, that can't be opened with registry.READ permission, so for me to read values and keys, i have to use registry.QUERY_VALUE and registry.ENUMERATE_SUB_KEYS permissions; BUT after successfully opening key with k.OpenKey() (for example HKEY_LOCAL_MACHINE\SOFTWARE) with such permissions the k.ReadSubKeyNames() function gives an error in BOTH cases:
ReadSubKeyNames: HKEY_LOCAL_MACHINE\SOFTWARE Access is denied.
Of course actual registry keys permission QUERY_VALUE and ENUMERATE_SUB_KEYS is enabled for Administrator (i'm using administrator profile)
How should i get Sub key names without using registry.READ permission and what is the problem?
Code sample:
var (
queryVal uint32 = registry.QUERY_VALUE
enumSubs uint32 = registry.ENUMERATE_SUB_KEYS
)
k, err = registry.OpenKey(globalK, p, queryVal)
if err != nil {
logErr(wrapErr(fmt.Sprintf("registry.OpenKey: %s", keyPath), err))
return
}
defer k.Close()
newKey := someLocalType{
}
keyStat, err := k.Stat()
if err != nil {
logWarn(fmt.Sprintf("Stat: %s %v", keyPath, err))
return
}
newKey.mod = keyStat.ModTime()
n, err := k.ReadValueNames(-1)
if err != nil {
logWarn(fmt.Sprintf("ReadValueNames: %s %v", keyPath, err))
return
}
for _, each := range n {
v, err := getKeyValue(k, each, keyStat.MaxValueLen)
if err != nil {
logWarn(fmt.Sprintf("getKeyValue: %s %v", keyPath, err))
continue
}
newKey.val = append(newKey.val, v)
}
var k1 registry.Key
if len(p) != 0 {
k1, err = registry.OpenKey(globalK, p, enumSubs)
if err != nil {
logErr(wrapErr(fmt.Sprintf("registry.OpenKey: %s", keyPath), err))
return
}
defer k1.Close()
} else {
k1 = globalK
}
subNames, err := k1.ReadSubKeyNames(-1)
if err != nil {
logWarn(fmt.Sprintf("ReadSubKeyNames: %s %v", keyPath, err))
return
}
for _, each := range subNames {
newPath := joinPath(p, each)
scanKey(globalK, newPath, c)
}
return
The answer is using combined value:
combinedRights := registry.QUERY_VALUE | registry.ENUMERATE_SUB_KEYS
Because k.ReadSubKeyNames() uses k.Stat() inside it, and k.Stat() require registry.QUERY_VALUE right to return successfully, and after that k.ReadSubKeyNames() uses syscall to enumerate subkeys and there are registry.ENUMERATE_SUB_KEYS right is used. Windows registry rights could be summarized using OR on them, so that is the answer.