Quantcast
Channel: Registry – Zerosignal.co.uk
Viewing all articles
Browse latest Browse all 2

Query 64 bit Registry with 32 bit PowerShell

$
0
0

I recently started writing some local checks for use with the Nagios agent, Check_MK. In its recent versions it supports executing PowerShell scripts, so I chose this over VBScript. It was a simple script to check the Microsoft Forefront Client Security definitions file date to verify it was up to date. Sounds simple enough, but the path to the definitions file is unique to each installation - this path is stored in the HKLM hive of the registry: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft Forefront\Client Security\1.0\AM\Signature Updates

I put together a script to query the registry, query the file properties and return a Nagios status code depending on the file's age. When I ran the code manually inside a PowerShell console it worked perfectly, but after I copied the script into Check_MK's local checks folder and had the agent run the script, I got a definite error - file not found!


PowerShell LogoI thought it was very odd that it couldn't find the file, as the Check_MK agent runs as system and shouldn't have any problems in accessing files or the registry. After adding a bit of debugging code, I saw that the value being returned from the registry was blank. Even stranger, when I widened my scope to enumerate the HKLM\Software\Microsoft\Microsoft Forefront key, I got a successful output! I searched the registry for other occurrences of keys with this name and discovered a subset of HKLM\Software is mirrored inside another regkey, HKLM\Software\Wow6432Node.

After some searching, I found that in 32 bit editions of Windows there is one registry that all applications access, but in 64 bit editions of Windows there is the main registry, accessible by all 64 bit applications AND a subset of that registry in the Wow6432Node key. 32 bit applications are transparently redirected to this key. The value I wanted to find from the Signature Updates key didn't exist in its Wow6432Node counterpart. I used Process Explorer to look at the Check_MK agent process and saw that it is a 32 bit application, and therefore runs PowerShell in 32 bit mode, hence it being redirected to Wow6432Node. I needed to explicitly query the 64 bit portion of the registry in order to get the key out.

Check_MK Agent 32bit

PowerShell 32 bit

Querying the 64 bit registry is possible through WMI instead of using PowerShell's registry PSDrive or .net procedures. I found a script to do it and adapted it for querying values and enumerating keys: http://gallery.technet.microsoft.com/scriptcenter/6062bbfc-53bf-4f92-994d-08f18c8324c0

 

My adapted version for querying known values (returns a string, or bool false if not found):

Function GetValueFromRegistryThruWMI([string]$computername, $regkey, $value){
	#Adapted from http://gallery.technet.microsoft.com/scriptcenter/6062bbfc-53bf-4f92-994d-08f18c8324c0
	#Thanks to Daniele Muscetta!
	#
	#Usage example: GetValueFromRegistryThruWMI "." "SOFTWARE\Microsoft\Microsoft Forefront\Client Security\1.0\AM\Signature Updates" "SignatureLocation"
	#

	#constant for the HLKM
	$HKLM = "&h80000002"

	#creates an SwbemNamedValueSet object
	$objNamedValueSet = New-Object -COM "WbemScripting.SWbemNamedValueSet"

	#adds the actual value that will requests the target to provide 64bit-registry info
	$objNamedValueSet.Add("__ProviderArchitecture", 64) | Out-Null

	#back to all the other usual COM objects for WMI that you have used a zillion times in VBScript
	$objLocator = New-Object -COM "Wbemscripting.SWbemLocator"
	$objServices = $objLocator.ConnectServer($computername,"root\default","","","","","",$objNamedValueSet)
	$objStdRegProv = $objServices.Get("StdRegProv")

	# Obtain an InParameters object specific to the method.
	$Inparams = ($objStdRegProv.Methods_ | where {$_.name -eq "GetStringValue"}).InParameters.SpawnInstance_()

	# Add the input parameters
	($Inparams.Properties_ | where {$_.name -eq "Hdefkey"}).Value = $HKLM
	($Inparams.Properties_ | where {$_.name -eq "Ssubkeyname"}).Value = $regkey
	($Inparams.Properties_ | where {$_.name -eq "Svaluename"}).Value = $value

	#Execute the method
	$Outparams = $objStdRegProv.ExecMethod_("GetStringValue", $Inparams, "", $objNamedValueSet)

	if (($Outparams.Properties_ | where {$_.name -eq "ReturnValue"}).Value -eq 0){
		$result = ($Outparams.Properties_ | where {$_.name -eq "sValue"}).Value
		return $result
	}else{
		Return $false
	}
}

 

My adapted version for enumerating keys (returns an array of keys):

Function EnumKeysThruWMI([string]$ComputerName, [string]$RegKey){
	#Adapted from http://gallery.technet.microsoft.com/scriptcenter/6062bbfc-53bf-4f92-994d-08f18c8324c0
	#Thanks to Daniele Muscetta!
	#
	#Usage example: EnumKeysThruWMI "." "SOFTWARE\Microsoft"
	#

	#HKLM: &h80000002
	#HKCU: &h80000001
	$RegHive = "&h80000002"
	
	#Creates an SwbemNamedValueSet object (sends additional parameters to the WMI request)
	#http://msdn.microsoft.com/en-us/library/windows/desktop/aa393732%28v=vs.85%29.aspx
	$objNamedValueSet = New-Object -COM "WbemScripting.SWbemNamedValueSet"
	
	#Adds the parameter that requests the target to provide 64bit registry info
	#http://msdn.microsoft.com/en-us/library/windows/desktop/aa393067%28v=vs.85%29.aspx
	$objNamedValueSet.Add("__ProviderArchitecture", 64) | Out-Null
	
	#Make connection to WMI and create a registry provider object
	#http://msdn.microsoft.com/en-us/library/windows/desktop/aa393664%28v=vs.85%29.aspx
	$objLocator = New-Object -COM "Wbemscripting.SWbemLocator"
	$objServices = $objLocator.ConnectServer($ComputerName,"root\default","","","","","",$objNamedValueSet)
	$objStdRegProv = $objServices.Get("StdRegProv")
	
	#Obtain an InParameters object specific to the method and assign additional parameters
	$Inparams = ($objStdRegProv.Methods_ | where {$_.name -eq "EnumKey"}).InParameters.SpawnInstance_()    
	($Inparams.Properties_ | where {$_.name -eq "hDefKey"}).Value = $RegHive
	($Inparams.Properties_ | where {$_.name -eq "sSubKeyName"}).Value = $RegKey
	
	#Run WMI query and extract results to an array
	[array]$result = ($objStdRegProv.ExecMethod_("EnumKey", $Inparams, "", $objNamedValueSet)).Properties_ | where {$_.name -eq "sNames"} | ForEach-Object -Process { foreach($val in $_.value){Write-Output $val} }
	return $result
}

 


Viewing all articles
Browse latest Browse all 2

Latest Images

Trending Articles





Latest Images