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...
It seems that everywhere I turn, the computer press keeps implying that the only people who leave UAC turned on are people who don't really understand computers. In June 2008, for example, it's #6 on their list of tips (page 64 in the print edition):
6. Turn off annoying prompts. Vista added the "A Program Needs Your Permission to Continue" prompt to help prevent you from inadvertently installing malware or making unauthorized changes to your computer. It's annoying to see that dialog box constantly pop up. If you're computer savvy, you can turn it off by deactivating User Account Control in the User Accounts Control Panel.
Et tu, PCMag?
Clearly, we understand that there are a lot of people who are going to turn off UAC. But coercing people to turn off a feature that helps them by implying that not doing so means they aren't computer savvy... yowzers. I consider myself computer savvy, but I would never turn it off. I just do not trust the public Internet or everything I download from it to be an Administrator on my computer. UAC gives me a means to express my inherent mistrust.
Because it turns out it actually does help prevent you from inadvertently installing malware.
And of course I know you can just be more careful. But, if you think about it, being secure means going through a decision every time you launch something. You can either do a mental prompt before you take any action (does clicking this thing put me at risk, since I'll be giving it admin rights?) or to some smaller subset of actions which explicitly gain admin rights. So, with UAC, I have prompts, but I think less, because I only have to think when the prompts tell me to.
And if I'm not thinking, just doing - well, am I really being computer savvy?
What can I say, I'm lazy. I think saying yes every now and again requires far fewer cognitive resources than being mindful of each and every thing that I do on my computer, despite the vast differences in trust I allocate to each action based on its source.
My colleague Gerrard Lindsay described the "annoyance" in a way that really caught my eye:
Some annoying things that are still worth it:
Just some food for thought. You can be computer savvy and enable UAC. It won't make you more popular, better looking, or drive a nicer car, but it will help you think less.
UAC: the greatest thing since the gag reflex.
Man, good thing I don't have a job in marketing.
Springboard Live! Real Talk about Windows Vista Deployment
I'll be joining the panel of bloggers discussing real world challenges deploying Windows Vista. If you're going to be at TechEd 2008, join us Thursday, June 12 at 10:00 am!
I received a request to talk about a particular shim. And yes, I received that request over a month ago, so ... sorry about that. Nonetheless, I've managed to scratch out a little niche of time to discuss the shim:
OpenDirectoryAcl
Yep, this does exactly what you would expect it does, modifying the ACL on a directory. I had not documented this shim yet because in a typical enterprise environment, it typically is not the best approach to resolving application compatibility issues.
But, that does not mean that it is never useful, so rather than just ignoring it, I will simply go through the steps I would normally go through to eliminate the need for this shim, and allow my eminently gifted readers to re-use or modify the logic as it suits them.
Can you redirect the file write?
If I can redirect the file write to a less privileged location, then I prefer to do that. By doing so, I don't have to loosen the security profile of the system. Even if I need to share the file, I generally prefer to take writes out of Program Files and instead set something up (ACL'd appropriately) in ProgramData, so I will sometimes redirect even if I am changing directory or file permissions.
Should the application run elevated?
If the purpose of the application is to modify protected resources, it may be a better choice to require elevation rather than to remove the protection on the resources.
Can I modify the ACLs when I repackage?
If I have decided that I need to loosen the ACL. First, I re-read Changing access control on folders vs. files and think again - am I really sure I need to modify the ACL?
Let's say that I have some compelling reason to change permissions on the file or directory. Since most enterprise software is deployed using management software, such as System Center Configuration Manager, rather than simply waiting for user's to self-launch an executable file, then I would approach that by repackaging or transforming the installer (frequently an MSI) rather than shimming a setup.exe. The LockPermissions table in an MSI allows me to set ACLs. (If you're writing the installer using the fabulous WIX tool, then you can use the Permission Element.)
There are simply almost no situations where I find users self-installing setup.exe files. However, in the consumer space, this is extremely common, which is why this shim works well in that scenario and we see this bubbling up as the 11th most commonly used shim in the system shim database.
How OpenDirectoryAcl works
Why do you need to target the setup? Because that's when we apply the ACLs. Specifically, we intercept calls to the CreateDirectory APIs, and if you create a directory that matches the command line, then we put it in the queue to modify that ACL. Then, when we either call the ExitWindowsEx API or exit the process, we apply the ACL changes that were matched. That means you are modifying ACLs on directories when you create them, so you have to target the setup.
So, I think you can see now why I have never once had to use this with an enterprise customer. But just because I haven't doesn't mean you won't.
Configuring OpenDirectoryAcl
If you've gotten this far, well, let's configure this shim. The command line syntax is as such:
-<options> <dir-or-file>|<sddl> [ -<options> <dir-or-file>|<sddl> ...]
The options you can specify are:
You then specify the directory or file you want to modify the ACL for. (Yes, the name of the shim is deceiving, because you can specify a file rather than a directory.) If the file name has spaces, then make sure you enclose the file name in quotes, as spaces are a delimiter for the command line. Also, if you use environment variables.
Finally, you don't need to specify SDDL. By default, you'll receive D:(A;OICI;FA;;;BU)
However, you can specify SDDL if you want. after the directory or file path, simply include a pipe character ( | ) and then include the SDDL you'd like to add.
Ask me about this, or other shims, at TechEd 2008
I have two sessions on Shims set up for TechEd 2008, and I invite you to come and chat with me there. Also, I am in the running to be part of a Windows Vista Bloggers' Panel hosted by Mark Russinovich at TechEd IT Pro week. Come and barrage the panel with your most challenging questions - it should be a great time for all. There is still time to register - head on over to http://www.microsoft.com/events/teched2008/itpro/registration/regprocess.mspx to register.
The new phone books are here! The new phone books are here!
Does my geekiness have no bounds? (Apparently not.) Now I just need to find somebody who has WNDPROC plates...
Regardless, you can't possibly have forgotten (since I am compelled to remind you) that I'm in the running to participate in the Windows Vista Bloggers' Panel hosted by Mark Russinovich at TechEd IT Pro week. There's still time to register! Just visit http://www.microsoft.com/events/teched2008/itpro/registration/regprocess.mspx to sign up to attend. Looking forward to seeing a number of you there - we've got some great new content in store for you!
I had a bit of a bummer morning back at MMS 2008. I woke up early (fortunately the conference was in Pacific and my body was in Central, so it was less torturous than getting up early normally is for me) and went down to get set up nice and early. I decided to add a bunch of extra demos at the last minute, you see, so I figured I could use the time.
Unfortunately, the presenter who was going to have the room after me decided to get there even earlier than I did.
So I got to sit and wait.
With around 1/2 an hour to go, and my new demos completely untried, I started getting set up. After getting all fired up and ready to go, I plugged in to the projector system. If you have ever presented at a Microsoft conference, you know that it's not just a VGA cable, it's also that silly USB cable that they insist you have to have, but never have a good explanation of why you can't live without it. Normally, from what I can tell, it doesn't do anything that I would want.
But that morning, it was a special surprise.
Plugging in the USB cable made the keyboard not work correctly. Neither the external keyboard they provided nor the keyboard sitting happily attached to my Tablet PC. I couldn't type any longer.
Now, fortunately I do have a Tablet PC, and the writing functionality *did* still work. I wasn't hosed after all! But I was adding demos on the fly, and I reverted to typing things out of habit on two separate occasions. Oops. So I fixed it, and did a "mouse and ink only" demo on application compatibility. Overall, I think I recovered pretty well, or at least decently.
But it didn't matter - I got slammed. In the reviews:
"Gee a working keyboard can't be that tough to come by."
Apparently it wasn't enough that I had to slog through demos while somebody else's equipment that horked my box, but then I had to get a bad review because of it.
Which brings me to my point:
Your reviews affect the person who is delivering the session only.
I'm fairly certain that nobody else is digging into my session looking for equipment failures (although they probably do aggregate it). I suspect that KVM is still floating around somewhere and will re-emerge somewhere and bite somebody else. Why? Because I don't have any influence over the equipment. I don't run conferences. I just show up and plug in.
The same is true for food. I've had quite a few conference reviews telling me how awful the lunch was. Except ... I don't make lunch at conferences. In fact, if you aren't handed a microwave meal for lunch, it's extremely unlikely that I made your lunch at all - conference or not. Telling me you didn't enjoy the lunch will not get you a better lunch next time.
Giving me a bad score because of bad food, faulty equipment, inadequate snacks, or lack of ice cream doesn't get you those things, but it can keep me away next time. Conference planners like to keep people who get high scores and dump those who don't. Why? Because they want you to be happy and come to the next conference, and that starts with great presenters.
So, low scores are your way to attempt to vote somebody off of the island. If everyone agrees with you, it just might happen. And you should do that - we want you to tell us if we've wasted your time so we stop doing that!
But that brings me to my next point:
People reading evaluations do not reserve the top score for God.
I've done this one myself - but it works a little different in Conference-Land than I would have thought. I would reserve the top score for "absolute perfection", which of course nobody could ever achieve. But, just in case the greatest presenter in the world has the best session of their lives the day I happened to be in the audience, I'd have that score to let them know.
Conference organizers don't think like that. If you have a 5-point Leikert scale, they expect you to average above a 4. If you don't consistently do that, they start thinking of getting you off of the island. They don't view 5 as reserved for God and 4 as the best a mortal could hope for. They view 5 as an excellent session delivered by a mortal. Top box is expected, not something that should be out of reach almost all of the time.
This doesn't mean that you should go handing out top box scores all of the time. People should always earn their scores. But if you are thinking to yourself, "self, that session rocked so hard - I've never seen a better one - I'm giving that presenter the best a mortal can hope for, an amazing 4 out of 5!" then you don't actually communicate that sentiment. Rather, you communicate "that was OK - better than average, at least. Try harder next time."
For, while evals may seem like a place to vent after a tiring week, they're actually more than that. You can try to vote people off of the island if they are just plain awful. You can try to tell people "I love the session and I'd like to come again, but the next time I do, fix this problem because it was really annoying." Just make sure that you are speaking the same language as the people reading it, so the right people interpret it the right way, and what you get next time will be more likely to be what you want (if you didn't get that in the first place).
Oh, and written comments? Always the best feedback. I love them.
I'm looking forward to your feedback from TechEd 2008!
Oh yeah - I’m gunning to participate in the Windows Vista Bloggers’ Panel hosted by Mark Russinovich at TechEd IT Pro week. For some reason they want me to perseverate in reminding you of this. I cannot explain why - seems a bit odd to me. But I hope you'll join in the panel anyway and fling some really tough questions at the panel. It's not to late to register to attend TechEd - head on over to http://www.microsoft.com/events/teched2008/itpro/registration/regprocess.mspx.
A question came up today:
Are any event logs produced when you run an application with applied shims? I've tried different variations of shims trying to get the desired results with no luck. It's probably UE, but I can't tell if the shims are erroring out because the syntex is incorrect, the file location is wrong, or if the database is even being read. Can you help?
Yes, there are diagnostics built in to the Windows Shim Infrastructure - but you do have to turn them on.
First, you can enable debug output, which will spit things out if things go wrong. You to this by setting:
[HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags]"ShowDebugInfo"=dword:00000009
Now, you can view debug output either in a debugger, or by using DebugView. This is helpful for diagnosing problems with shims.
If you want still more information, you can enable additional log file output via environment variables. You can set them using:
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v SHIM_DEBUG_LEVEL /t REG_SZ /d 9 /freg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v SHIM_FILE_LOG /t REG_SZ /d logfile.txt /f
Now, you'll have output showing up in %appdata%\logfile.txt.
This can be helpful in debugging what the problems are.
I will be digging deep into the Windows Shim Infrastructure during my session CLI458: Mitigating Application Issues Using Shims - Part 2 at TechEd 2008.
And remember:
READY, SET, GO! I’m in the running to be a part of a Windows Vista Bloggers’ Panel hosted by Mark Russinovich at TechEd IT Pro week. This is a great opportunity to get answers to all of your Windows Vista deployment questions and find out what your fellow IT pros are encountering in their deployments. If you haven’t registered for TechEd yet, there’s still time. Just visit http://www.microsoft.com/events/teched2008/itpro/registration/regprocess.mspx
I am just finishing up some prep work on my decks, so I guess it's time to start evangelizing the next big public event I'm fortunate enough to participate in: TechEd 2008 IT Professionals.
I'm delivering one session on project management (I'm looking forward to your feedback here - I'm used to giving hard-core technical sessions!) I'm also delivering not one, but two sessions on Mitigating Application Compatibility Issues using Shims (the second one going deeper than I've ever gone before in a public event). I also have a chalk talk, and I'll be spending some time working in the application compatibility booth. (I'm also cooking up a session on debugging, but I won't get through that in time for June - maybe for TechEd Europe?)
Oh, and I'm campaigning to participate in a Windows Vista Bloggers' Panel hosted by Mark Russinovich. Regardless of who is selected, it should be a fun opportunity to come and nail us with your most challenging Windows Vista deployment questions. If you're attending (there's still time to register!) this should be a great event to stop by!
A comment came up on a recent posting regarding modules, inquiring about processes. Specifically:
Do these included/excluded modules have to be in the same process, or can they include other processes too? (I have an application that calls multiple child applications that all need to be shimed in the same way as the first process)
Ah, that is a subject I appear to have not touched on here.
Shims, you see, apply to the process you specify, and only that process. Layers, however, apply to that process and to child processes. So, if you have a main application that launches child applications, applying the fixes as a layer will help you achieve that (assuming they are always launched by the shimmed parent process).
Note that Compatibility Administrator uses slightly different terminology here. It refers to shims as Compatibility Fixes, and layers as Compatibility Modes.
Layers are also handy as a means of applying a collection of fixes. You can group several fixes together and call them a layer. But the fact that layers apply to child processes is exactly why we include a WinXPSP2VersionLie layer in the system shim database. A collection of one isn't that interesting, but a collection of one that gets the shim applied to child processes? That's very interesting, particularly for self-extracting setups that like to think they are installing on XP.
If the child applications can be launched directly by Explorer, then you'll want to shim them up separately and we can't save you the work by having you just leverage a layer.
Every now and then, I see email sent to a discussion list that includes something like the following:
"Please use Reply to All I am not a member of this discussion group."
And sometimes you see something like this instead:
"Please little-R, I am not a member of this discussion group."
I think you can see where I am going with this. If I send a message and you hit Reply, I get the response. If I send a message and you hit Reply to All, I get a response and so does the group. Unless somebody takes the time to manually remove my name from the To line, I get a response. And people are notoriously lazy, so it's extremely unlikely that they would ever do that.
So, the only information that is actually conveyed by this message is that the author doesn't like your little group enough to actually join it, but they sure would like your help right now.
I received one comment on my recent blog post on copying from the system shim database, which I think is worthy of discussion as I have heard similar questions before:
I have found previously (under Windows XP, haven't attempted under Vista) that some of the built-in shims weren't suitable. I had a custom database for the applications into which I'd copy/paste/modify the system shim database. I don't recall ever seeing this error, so does compiling a modified shim not cause it?
To answer the question directly, I am not sure about Windows XP. However, on Windows Vista, even if I modify the shim, I end up unable to compile the SDB.
But that leads us to two discoveries.
First, the fact that we have shimmed something in the System Shim Database does not mean that it works 100%.
With some applications, we are simply shimming to get it to a particular point in the application. Working with one ISV, our objective was just to get it to hobble through to the auto update component of the application. They didn't care if it was a little bit ugly, so long as it actually got there.
With others, we have simply shimmed the application to fix the application and close a particular bug report that was submitted. If nobody ran the application to resolve that scenario, found that it failed, and submitted the bug to us, we haven't even tried to shim it.
Or, perhaps, we couldn't shim it, because the thing that it does wrong is unfixable using shims.
I have heard some people suggesting that finding the application in the list means that we are vouching for the fact that it works. We work really hard to get it that way, but unfortunately we can't make such a promise.
Second, you can modify the fixes that we have made to applications.
But it's not always easy.
If you have additional things to fix, then you can just add the application (don't copy/paste, because that's broken right now) and add the additional fixes that resolve the scenarios we clearly haven't tested before. We'll pick up both the entries in sysmain and in your custom SDB and apply both sets of shims.
If you need to remove an application fix from sysmain, you can right click on it, and disable that entry. If you need to disable an entry, we'd really love for you to tell us about it, so we can fix things up the right way. An example would be if you needed to add additional command line arguments to a shim. We can't just add the same shim twice or they don't both get picked up. Instead, you'd want to disable ours and add yours.
I hear about a bug now and again with Compatibility Administrator [CompatAdmin]. It always surprises me when I hear about the bug, because you can only hit it if you are trying to do something that there is no point in doing (which is why we never caught it before).
Here's how you reproduce the bug.
In CompatAdmin, expand the System Database, then expand Applications. Pick an application at random, right click, and select copy. Now, go to a custom shim database, and paste this application and its shims. When you go to compile the shim database (which happens when you save it), you get this really weird error:
---------------------------Compatibility Administrator---------------------------There was a problem in executing the compiler. The database could not be created successfullyThe database file might be write-protected.---------------------------OK ---------------------------
Now, the part about the compiler problem is correct - the suggestion that it may be write protection is not. So, we could do better with the error message, and we could also not give it in the first place. So, we have a bug filed against it. But here's the point.
You never need to manually apply shims from the system shim database. They are already there. They are already applied. We have 5,646 application entries sitting there waiting for you to install the application. As soon as we find the matching information, we start shimming - with no action required by you. We haven't just given you a collection of known fixes to discover and re-use, we've just outright fixed them.
Because, hey, when you go to run Barbie Pet Rescue, we don't want you to have to go fumbling around with CompatAdmin. We want to get you rescuing pets as quickly as possible.
A question came up in the comments of one of my posts, and I think the answer is important enough to elevate to more than just another comment (and I didn't even answer completely in that quick response).
When you are configuring a shim and press the "Parameters" button, we've talked about the "Command line" option for several shims, but we've kind of glossed over the "Module name" entry. When we're applying shims, we are modifying the IAT of all statically linked modules, and we also have to intercept calls to GetProcAddress for dynamically linked modules.
Which modules do we need to be sure to include? That's easy - just go one stack frame above the API call you want to intercept.
Which modules aren't included already? Well, that's somewhat more complicated. So, let's just walk through the list to see what might get cut along the way.
First, we automatically exclude anything that sits in system32. So, if you want to have something included that sits in this directory, you have to specifically include it. (That, by the way, is why you have to include msvbvm60.dll for shimming VB6 apps - because the runtime sits in system32, and most calls land in the runtime before they hit the APIs we want to intercept.)
Next, we have a global include and exclude list. Here, we can add back in some modules, or remove some modules from consideration that aren't sitting in system32. This list of modules is not documented anywhere. Conveniently, however, it turns out that there's a little bug right now that prevents the global exclude list from being processed, so the number of additional modules excluded is 0. But we may fix this bug (or we may not, if this causes apps to break because shims are no longer applied - I'm not sure about that right now), so it's good to know that this processing exists. I'll be sure to document the list if that comes to pass.
Then, the shim itself has an include and exclude list. You'll see that if you launch Compatibility Administrator with the (super-secret, undocumented) /x command line switch - here, we include modules to overrule global exclude list and system32 exclusion, or exclude modules that aren't in system32 or the global exclude list (were it being processed) which we want to make sure we don't shim.
Finally, the application of a shim to a specific program has an include and exclude list. You can include a module to overrule any earlier excludes (system32, global, or shim-specific) and exclude a module if there's something we didn't rule out yet where shimming turns out to be bad.
It would be interesting to have the equivalent of Resultant Set of Policy for shim modules, but alas, nothing of the sort exists today. Instead, you generally rely on investigating if a particular module calls the API and either does or doesn't walk through the shim code. But hopefully these rules can shed some light on why a shim may not appear to be wired, and adding in a module can provide a quick fix to resolve the issue.