Tuesday, June 4, 2013

Loading in the environment they call Safe Mode!

Sometime back I had a requirement of loading a driver in Safe Mode. Most of us who have been dealing with drivers know that if your driver is not a boot driver, Windows does not load it in Safe mode. Infact Microsoft generally discourages third party drivers from loading in safe mode and hence a lot of boot time drivers detect the booting of Windows in Safe Mode in DriverEntry and return a failure code.
So, who would want to really load in Safe Mode? Well, certain Anti-Malware related drivers for instance are good candidates for running in such an environment.
Before we actually go into details, it is worth mentioning that all this is just about creating the required registry entries to whitelist the driver and telling Windows that it is fine to load it.
Assuming that our driver's service name is MySMDrv and the binary names are MySMDrvx86.sys and MySMDrvx64.sys on x86 and x64 platform.
 
Let's take it step by step:
Where is the service entry created?
The service entry for all the drivers gets created under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services. In our case, it would be
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MySMDrv.
It is important to note that CurrentControlSet is just a link to another key (as an example ControlSet001). So, HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MySMDrv will actually be a link to HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\MySMDrv.
This becomes clear if you notice the registry path that comes as the second parameter in DriverEntry.
What decides what CurrentControlSet points to?
Depending on the environment that Windows has booted into, CurrentControlSet can point to ControlSet001, ControlSet002 and so on. This is indicated by ValueName "Current" of "HKEY_LOCAL_MACHINE\SYSTEM\Select". For instance, value of 1 for "Current" indicates that CurrentControlSet points to ControlSet001.
Installing in Safe Mode
If your driver is not a boot-time driver, you most likely will have to install it from within the Safe Mode to make loadable. So, once you are in safe mode, install your driver such that it creates the required registry entries. Assuming that ControlSet001 represents normal boot, ControlSet002 will most likely represent the Safe Mode boot environment. Again, this information must be extracted on the fly using the registry key mentioned above.
Trying to load a driver that is not whitelisted
If you try to load a non-whitelister driver in Safe Mode, you will receive either error ERROR_NOT_SAFEBOOT_SERVICE or ERROR_NOT_SAFE_MODE_DRIVER.
Whitelisting the driver and getting it to load
Whitelisting is all about making the required registry entry somewhere under
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SafeBoot. CurrentControlSet ofcourse needs to be translated into the correct path. You will notice that there are some more subkeys under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SafeBoot- Minimal and Network. They in turn represent the specific SafeMode boot type. This is where the entry really needs to go.
Let's look at the entries required for whitelisting:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SafeBoot\Minimal\MySMDrv
    with the default (unnamed) value name set to "Driver"
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SafeBoot\Network\MySMDrv
    with the default (unnamed) value name set to "Driver"
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SafeBoot\Minimal\MySMDrv.sys
    with the default (unnamed) value name set to "Driver"
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SafeBoot\Network\MySMDrv.sys
    with the default (unnamed) value name set to "Driver"
 
Look at the last two entries. They don't really make sense. Our driver name is MySMDrvx86.sys and MySMDrvx64.sys on x86 and x64 respectively. However, this is precisisely what is needed to get it to work and something that I had trouble with initially; but found out eventually!
It is also worth mentioning that if your driver name is MySMDrv.sys (that is same as Service name plus the .sys extension), you just need to create the MySMDrv.sys entry (atleast this seems to be from looking at the existing registry entries). However, it is safe to create both entries and just be sure that it would work!
 
Last but not the least, the above has been tested on Windows 8 too and works just fine.
 
Oh yeah, don't forget to sign your driver. ;)