Every now and again, I bump up against a setup application (it’s almost always a setup application) that tries to drop older versions of protected operating system files. It’s fairly easy to mitigate, but I thought I would go through some of the mechanics, and some of the places where the mitigation can break down.
Let’s take a walk down memory lane…
Introduced in Windows 2000 and brought over to Windows ME … I’ll pause for everyone to recover from the shivers in your spine … we offered a feature called System File Protection. This feature is designed to protect the integrity of the operating system. This feature had a couple of issues, which I talk about here: http://blogs.msdn.com/cjacks/archive/2007/04/20/windows-resource-protection-wrp-and-activex-control-installation-on-windows-vista.aspx.
So now, things are better, except of course the applications that break, which is why we didn’t just modify the ACLs in the first place. So, one by one, we just start applying our WRP shims to applications that need it, and this got us back where we needed to be for application compatibility. We automatically apply this shim if we detect that you are a setup. We apply this shim to regsvr32.exe. We throw it everyplace that we think we’re going to catch people trying to write to protected operating system files.
So, how does it work?
Well, first we always try to run the original API. If that fails, then we check to see if you are a WRP protected file. We do that for performance – if what you are trying to do already works, we don’t need to fix you, nor do we need to run code to determine if we ought to fix you. We just let you go on doing your thing.
But if the operation didn’t work, then we’ll check to see if the file is WRP protected. If so, then we’ll pretend that things worked.
How do we pretend?
Well, if you’re trying to delete, we can just return success. Move? Success. Change attributes? Success.
But what if you’re trying to write?
In that case, we don’t get very far by returning success, because we need to return a handle that is valid or the application could AV. So, we just create a temp file, and return a handle to this temp file.
Right now, I’m running an application attempting to update kernel32.dll, and I find this in %temp%: WRP112.tmp.
That’s where I’ll be writing when I write. My application continues to work, and we resolve the issue.
But let’s back up a minute – what happens if I am trying to drop my file in a non-standard location and register it from there? Here, we can run into issues. Clearly, the application is intentionally trying to circumvent protection mechanisms. They drop the dll somewhere other than the location of the protected dll (which succeeds) and then call regsvr32.dll. (Some people think they’re really tricky – I once saw an app drop some version of shell32.dll from Windows 2000, but they called it shell32.ico, then called regsvr32 on it.)
Our check to see if it’s a protected operating system file says “no” because it isn’t owned by Trusted Installer, and we don’t fix it up.
With people trying to be tricky like this, I usually end up modifying the package to remove this drop. But I suppose I could CorrectFilePaths to hit my protected location…