ntdll/NtEnumerateKey.ps1
function NtEnumerateKey { <# .SYNOPSIS Provides information about a subkey of an open registry key. .PARAMETER KeyHandle Handle to the registry key that contains the subkeys to be enumerated. .PARAMETER Index The index of the subkey that you want information for. .PARAMETER KeyInformationClass Specifies a KEY_INFORMATION_CLASS value that determines the type of information returned in the KeyInformation buffer. .NOTES Author: Jared Atkinson (@jaredcatkinson), Brian Reitz (@brian_psu) License: BSD 3-Clause Required Dependencies: PSReflect, KEY_INFORMATION_CLASS (Enumeration), KEY_BASIC_INFORMATION, KEY_FULL_INFORMATION, KEY_NODE_INFORMATION, KEY_NAME_INFORMATION (Structures) Optional Dependencies: None (func ntdll NtEnumerateKey ([UInt32]) @( [IntPtr], #_In_ HANDLE KeyHandle, [UInt32], #_In_ ULONG Index, $KEY_INFORMATION_CLASS, #_In_ KEY_INFORMATION_CLASS KeyInformationClass, [IntPtr], #_Out_opt_ PVOID KeyInformation, [UInt32], #_In_ ULONG Length, [UInt32].MakeByRefType() #_Out_ PULONG ResultLength ) -EntryPoint NtEnumerateKey), .LINK https://msdn.microsoft.com/en-us/library/windows/hardware/ff566447(v=vs.85).aspx .EXAMPLE $MyKeyHandle = NtOpenKey -KeyName "\Registry\Machine\SOFTWARE\Microsoft\Windows\CurrentVersion" $KeyInfo = NtEnumerateKey -KeyHandle $MyKeyHandle -Index 0 -KeyInformationClass KeyFullInformation NtClose -KeyHandle $MyKeyHandle #> param ( [Parameter(Mandatory = $true)] [IntPtr] $KeyHandle, # Index of the subkey we wish to enumerate [Parameter()] [int] $Index = 0, [Parameter()] [ValidateSet('KeyBasicInformation','KeyFullInformation','KeyNodeInformation')] [string] $KeyInformationClass = 'KeyBasicInformation' ) #> $SubKeyPtrSize = 0 $status = $ntdll::NtEnumerateKey($KeyHandle, $Index, $KEY_INFORMATION_CLASS::$KeyInformationClass, 0, $SubKeyPtrSize, [ref]$SubKeyPtrSize) # if it returns STATUS_NO_MORE_ENTRIES, that means the Index is not valid (i.e. there isn't a subkey at that index) if($status -eq 0x8000001A) { throw [System.IndexOutOfRangeException] "Index out-of-bounds, or the given registry key has no subkeys." } # allocate the correct size and assign the value to our buffer [IntPtr]$SubKeyPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SubKeyPtrSize) $status = $ntdll::NtEnumerateKey($KeyHandle, $Index, $KEY_INFORMATION_CLASS::$KeyInformationClass, $SubKeyPtr, $SubKeyPtrSize, [ref]$SubKeyPtrSize) # if there are no errors, cast to specific type if(!$status){ switch($KeyInformationClass) { KeyBasicInformation { $KeyBasicInformation = $SubKeyPtr -as $KEY_BASIC_INFORMATION Write-Output $KeyBasicInformation } KeyNodeInformation { $KeyNodeInformation = $SubKeyPtr -as $KEY_NODE_INFORMATION Write-Output $KeyNodeInformation } KeyFullInformation { $KeyFullInformation = $SubKeyPtr -as $KEY_FULL_INFORMATION Write-Output $KeyFullInformation } } } [System.Runtime.InteropServices.Marshal]::FreeHGlobal($SubKeyPtr) } |