ntdll/NtQueryValueKey.ps1

function NtQueryValueKey
{
    <#
    .SYNOPSIS
 
    Returns a value entry for a registry key.
 
    .PARAMETER KeyHandle
 
    Pointer to a handle to the registry key to read value entries from.
 
    .PARAMETER ValueName
 
    The name of the value entry to obtain data for.
 
    .PARAMETER KeyValueInformationClass
 
    Specifies a KEY_VALUE_INFORMATION_CLASS value that determines the type of information returned in the KeyValueInformation buffer.
 
    .NOTES
 
    Author: Jared Atkinson (@jaredcatkinson), Brian Reitz (@brian_psu)
    License: BSD 3-Clause
    Required Dependencies: PSReflect, KEY_VALUE_INFORMATION_CLASS (Enumeration), KEY_VALUE_BASIC_INFORMATION, KEY_VALUE_FULL_INFORMATION, KEY_VALUE_PARTIAL_INFORMATION (Structures)
    Optional Dependencies: None
 
    (func ntdll NtQueryValueKey ([UInt32]) @(
        [IntPtr], #_In_ HANDLE KeyHandle,
        $UNICODE_STRING.MakeByRefType(), #_In_ PUNICODE_STRING ValueName,
        $KEY_VALUE_INFORMATION_CLASS, #_In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
        [IntPtr], #_Out_opt_ PVOID KeyValueInformation,
        [UInt32], #_In_ ULONG Length,
        [UInt32].MakeByRefType() #_Out_ PULONG ResultLength
    ) -EntryPoint NtQueryValueKey),
 
    .LINK
 
    https://msdn.microsoft.com/en-us/library/windows/hardware/ff567069(v=vs.85).aspx
 
    .EXAMPLE
     
    $MyKeyHandle = NtOpenKey -KeyName "\Registry\Machine\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
    $KeyInfo = NtQueryValueKey -KeyHandle $MyKeyHandle -ValueName "Viscosity" -KeyValueInformationClass KeyValueFullInformation
    NtClose -KeyHandle $MyKeyHandle
 
    #>


    param
    (
        [Parameter(Mandatory = $true)]
        [IntPtr]
        $KeyHandle,

        [Parameter(Mandatory = $true)]
        [string]
        $ValueName,

        [Parameter()]
        [ValidateSet('KeyValueBasicInformation','KeyValueFullInformation','KeyValuePartialInformation')]
        [string]
        $KeyValueInformationClass = 'KeyValueBasicInformation'
    )
#>
    $KeyValueInfoPtrSize = 0
    $KeyValueName = RtlInitUnicodeString -SourceString $ValueName

    # initial query to determine the necessary buffer size
    $status = $ntdll::NtQueryValueKey($KeyHandle, [ref]$KeyValueName, $KEY_VALUE_INFORMATION_CLASS::$KeyValueInformationClass, 0, $KeyValueInfoPtrSize, [ref]$KeyValueInfoPtrSize)

    # allocate the correct size and assign the value to our buffer
    [IntPtr]$KeyValueInfoPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($KeyValueInfoPtrSize)
    $status = $ntdll::NtQueryValueKey($KeyHandle, [ref]$KeyValueName, $KEY_VALUE_INFORMATION_CLASS::$KeyValueInformationClass, $KeyValueInfoPtr, $KeyValueInfoPtrSize, [ref]$KeyValueInfoPtrSize)

    if(!$status){
        switch($KeyValueInformationClass)
        {
            KeyValueBasicInformation
            {
                $KeyValueBasicInformation = $KeyValueInfoPtr -as $KEY_VALUE_BASIC_INFORMATION
                Write-Output $KeyValueBasicInformation
            }
            KeyValueFullInformation
            {
                $KeyValueFullInformation = $KeyValueInfoPtr -as $KEY_VALUE_FULL_INFORMATION
                if($KeyValueFullInformation.DataLength -gt 0) {
                    $DataPtr = [IntPtr]::Add($KeyValueInfoPtr, $KeyValueFullInformation.DataOffset)
                    $KeyValueData = New-Object byte[] $KeyValueFullInformation.DataLength
                    [System.Runtime.InteropServices.Marshal]::Copy($DataPtr, $KeyValueData, 0, $KeyValueFullInformation.DataLength)
                    # Need to check Registry Value Type to see what kind of data this is before printing
                    Write-Output $KeyValueFullInformation
                    [System.Text.Encoding]::Unicode.GetString($KeyValueData)
                } else {
                Write-Output $KeyValueFullInformation
                }
            }
            KeyValuePartialInformation
            {
                $KeyValuePartialInformation = $KeyValueInfoPtr -as $KEY_VALUE_PARTIAL_INFORMATION
                Write-Output $KeyValuePartialInformation          
            }
        }
    }
    [System.Runtime.InteropServices.Marshal]::FreeHGlobal($KeyValueInfoPtr)
}