ntdll/NtSetValueKey.ps1
function NtSetValueKey { <# .SYNOPSIS Creates or replaces a registry key's value entry. .PARAMETER KeyHandle Pointer to a registry key HANDLE where the value will be written. .PARAMETER ValueType Specifies the type of the registry key value to be written, e.g. REG_SZ. .PARAMETER ValueName Specifies the name of the registry key value to be written. .PARAMETER ValueData Specifies the data to be written for the registry value. .DESCRIPTION Set the data for a value associated with a key. .NOTES Author: Brian Reitz (@brian_psu) License: BSD 3-Clause Required Dependencies: PSReflect, UNICODE_STRING (Enumeration), REGISTRY_VALUE_TYPES (Enumeration) Optional Dependencies: None (func ntdll NtSetValueKey ([Int32]) @( [IntPtr], #_In_ HANDLE KeyHandle, $UNICODE_STRING.MakeByRefType(),#_In_ PUNICODE_STRING ValueName, [Int32], #_In_opt_ ULONG TitleIndex, [Int32], #_In_ ULONG Type, [IntPtr], #_In_opt_ PVOID Data, [Int32] #_In_ ULONG DataSize ) -EntryPoint NtSetValueKey), .LINK https://msdn.microsoft.com/en-us/library/windows/hardware/ff567109(v=vs.85).aspx .EXAMPLE <Usage Example> #> param ( [Parameter(Mandatory = $true)] [IntPtr] $KeyHandle, [Parameter(Mandatory = $true)] [string] $ValueName, [Parameter(Mandatory = $true)] [ValidateSet('RegNone','RegSz','RegBinary','RegDWord','RegDWordBigEndian','RegLink','RegMultiSz','RegExpandSz','RegResourceList','RegResourceRequirementsList','RegFullResourceDescriptor')] [string] $ValueType, [Parameter()] [string] $ValueData ) switch($ValueType) { RegNone { $RegType = $REG_VALUE_TYPE::REG_NONE } RegBinary { $RegType = $REG_VALUE_TYPE::REG_BINARY } RegDWord { $RegType = $REG_VALUE_TYPE::REG_DWORD } RegDWordBigEndian { $RegType = $REG_VALUE_TYPE::REG_DWORD_BIG_ENDIAN } RegLink { $RegType = $REG_VALUE_TYPE::REG_LINK } RegMultiSz { $RegType = $REG_VALUE_TYPE::REG_MULTI_SZ } RegExpandSz { $RegType = $REG_VALUE_TYPE::REG_EXPAND_SZ } RegSz { $RegType = $REG_VALUE_TYPE::REG_SZ } } if($RegType -ne $REG_VALUE_TYPE::REG_SZ) { throw [System.NotImplementedException]"The $($RegType) Registry Value Type is not implemented yet." } # Create a $UNICODE_STRING structure and a pointer to it. $vName = [Activator]::CreateInstance($UNICODE_STRING) $vName.Length = $ValueName.Length * 2 $vName.MaximumLength = $ValueName.Length * 2 $vName.Buffer = [System.Runtime.InteropServices.Marshal]::StringToCoTaskMemUni($ValueName) $pValueName = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($UNICODE_STRING::GetSize()) [System.Runtime.InteropServices.Marshal]::StructureToPtr($vName, $pValueName, $true) # For data of type REG_SZ, we can use $UNICODE_STRING if ($ValueData) { $vData = [Activator]::CreateInstance($UNICODE_STRING) $vData.Length = $ValueData.Length * 2 $vData.MaximumLength = $ValueData.Length * 2 $vData.Buffer = [System.Runtime.InteropServices.Marshal]::StringToCoTaskMemUni($ValueData) } $TitleIndex = 0 # this is always set to 0 according to MSDN # "This parameter is reserved. Device and intermediate drivers should set this parameter to zero." # $KeyHandle, [ref]$pValueName, $TitleIndex, $ValueType, $vData.Buffer, $ValueData.Length $SUCCESS = $ntdll::NtSetValueKey($KeyHandle, [ref]$pValueName, $TitleIndex, $RegType, $vData.Buffer, $vData.Length); $LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error() if(-not $SUCCESS) { Write-Debug "NtSetValueKey Error: $(([ComponentModel.Win32Exception] $LastError).Message)" } # free our memory after allocation # Cannot convert argument "hglobal", with value: "UNICODE_STRING", for "FreeHGlobal" to type "System.IntPtr" #[System.Runtime.InteropServices.Marshal]::FreeHGlobal($pValueName) } |