What’s new in the PSF, June 2020

My latest submission has been integrated into the Develop branch to the Package Support Framework GitHub repository. PR#145 adds a new type of fixup, RegLegacyFixups, created for certain Registry issues seen in some packages. There are a couple of small fixes added to standard components as well (see the Pull Request for details on those), but the new fixup module is the big item of importance.

The RegLegacyFixups dll is a new addition to the Package Support Framework. Currently it houses only one type of fixup, but it is designed to allow additional registry based fixups to be added to it in the future.

This fixup joins the other available fixup modules to fix issues with older software packaged into MSIX packages, FileRedirectionFixup and DynamicLibraryFixup (I usually ignore Electron as it is new and only apps under active development are using it) , along with the extra modules that aid us in debugging such as TraceFixup and WaitForDebugger.

The design of the RegLegacyFixups module will allow you to select and configure different types of fixups housed in the module. As mentioned, at this time there is only one type available, but hopefully more in the future. This type focuses on apps with “Access_Denied” issues on operations involving registry keys within the package.

ModifyKeyAccess

The ModifyKeyAccess type fixup in the RegLegacyFixups module allows for control of requests by the application to open and create registry keys. This can be used to solve issues with applications that request more permissions than they really need. While the request may have been allowed in the natively running program, sometimes the request isn’t when accessing a key that is part of the application hive. So by modifying the requested access field of the request in-flight, we can eliminate the failure and allow the system to return the registry with supportable rights.

When you select this type, you may specify additional parameters used to filter requests made and what type of change should be made. You specify the hive (HKCU or HKLM) of the request, and the relative path (using a regex pattern). You also specify the access type to filter for and how that access request should be modified.

An example issue

A program installer creates a set of registry keys and items in the HKCU hive under the Software key for that vendor. The runtime software wants to open the key and plans to use the opened key handle to work with items under that key. The application likely uses one of the CreateKey interfaces, so as to create the key if it is missing or open it if present. But whether it uses one of those or just an OpenKey interface is used, the request allows the developer to choose the type of access desired. Access types are bit-mask oriented with details like read and write and delete, as well as to enumerate or create/change subitems, or even modify the owner and ACLs. Convenience types are provided the developers that combine these, one of which is to request Full Access.

Prior to containerization, the developer probably never had to worry about what access the app requested for HKCU keys, because the app was allowed to do whatever it wanted with those keys. So requesting full access, or other convenience types with lots of permissions was common.

Under MSIX, some of the access types are prohibited. What is prohibited depends on which hive is being requested and which version of the OS the app is running on (as Microsoft has made adjustments to the MSIX Runtime in recent OS releases), so I won’t attempt to provide those specifics here.

But the result of an app requesting full access, or even some of the RW convenience items that include currently prohibited accesses, is unexpected. The end result is that the application gets an ACCESS_DENIED response to the request. Especially with HKCU requests, the application often does not contain any logic to deal with the request failing. It might try to use the null key returned and crash, it might hang, or do other unsavory things like try to fix the install.

Configuring the fixup

Here is an example of the json for configuring this fixup.

"fixups": [
	{
		"dll":"RegLegacyFixups.dll",
		"config": [
			{
				"type": "ModifyKeyAccess",
				"remediation": [
					{
						"hive": "HKCU",
						"patterns": [
							"^Software\\\\Vendor.*"
						]
						"access": "Full2RW"
					},
					{
						"hive": "HKLM",
						"patterns": [
							"^[Ss][Oo][Ff][Tt][Ww][Aa][Rr][Ee]\\\\Vendor.*"
						]
						"access": "RW2MaxAllowed"
					}
				]
			}
		]
	}
]

The fields are define as:

Remediation TypePurpose
ModifyKeyAccessAllows for modification of access parameters in calls to open registry keys. This remediation targets the samDesired parameter that specifies the permissions granted to the application when opening the key. This remediation type does not target calls for registry values.
HiveMeaning
HKCUHKEY_CURRENT_USER
HKLMHKEY_LOCAL_MACHINE
AccessPurpose
Full2RWIf the caller requested full access (for example STANDARD_RIGHTS_ALL), modify the call to remove KEY_CREATE_LINK.
Full2RIf the caller requested full access (for example STANDARD_RIGHTS_ALL), modify the call to remove KEY_CREATE_LINK, KEY_CREATE_SUB_KEY, and KEY_CREATE_VALUE.
Full2MaxAllowedIf the caller requested full access (for example STANDARD_RIGHTS_ALL), modify the call to request MAXIMUM_ALLOWED.
RW2RIf the caller requested Read/Write access, modify the call to remove KEY_CREATE_LINK, KEY_CREATE_SUB_KEY, and KEY_CREATE_VALUE.
RW2MaxAllowedIf the caller requested Read/Write access, modify the call to request MAXIMUM_ALLOWED.

Of these, the RW2MaxAllowed is proving to be most useful. This will filter on requests for both read/write and full access, and no matter what set of bits were actually requested, it will request a special setting of Maximum_Allowed, which allows the MSIX Runtime to return a key with whatever rights are currently allowed in that situation.

Making this modification will likely solve the initial issue of the application requesting too much access. Of course, once the application has the key, if it tries to perform a prohibited action using that key there could be new problems.

The application that produced the original ProcMon trace shown ealier in this article was configured to use this fixup on HKCU with a pattern of “^[Ss][Oo][Ff][Tt][Ww][Aa][Rr][Ee]\\\\instedit.*” (any path under HKCU starting with a case insensitive Software key and subkey starting with instedit) and an access setting of RW2MaxAllowed. This solved the issue (the app process originally hanged without display) and we can see the modified request succeed here:

I’ll note that we aren’t doing anything about redirecting requests at this time, so you remain dependent on the OS for that support. Adding that in the future is a possibility, but I am focusing on something concrete and simpler first. We can’t fix everything with this today, but over time we can add to this fixup to address more issues.

Version 3.8 of PsfTooling will be released shortly containing support for this build of the Psf, and other goodies. I’ll post on this blog when it becomes available.

UPDATE: PstTooling 3.8 is now released and described here.

By Tim Mangan

Tim is a Microsoft MVP, and a Citrix CTP Fellow. He is an expert in App-V and MSIX.