Had a discussion
a while ago with my colleague Johan Arwidmark where he told me that he
sometimes installs MDT just to be able to verify the integrity of driver to
make sure the drivers are signed and the inf files hasn't been tampered with.
This is also one of the few things that you miss out on if you use the “total driver
control” method in ConfigMgr and create normal packages for drivers instead of
importing them.
I always
like a good challenge, so I thought why not do this with a PowerShell script
instead that can be run without any dependency to MDT.
If you just
want the script, you can get it here:
Invoke-VerifyDriver.ps1
But if you
want a deep dive please read on 😊
The first
problem was that the inf files themselves are not embedded with a signature so
how can you verify that they are signed and not tampered with?
Using the
signtool.exe from Microsoft we can see that the .cat file is signed, but
checking the .inf file it says it does not have a signature.
So when I
ran the signtool I had not tampered against the inf file it still says not
signed (because there is no embedded signature, doh).
But I did
do it before I ran my script. So if comparing signtool output to the output of the script
below we can see that my script says “IsSigned”
= False.
So how does
MDT and ConfigMgr (and the script) verify inf files then? Well after some
digging around in the Microsoft docs I found a class called SetupVerifyInfFile and this seems to be the class
the MDT is using. For this to work in PowerShell I had to call it as a CSharp
typedefinition and figure out the correct syntax.
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetupVerifyInfFile(string infName, IntPtr AltPlatformInfo, ref INF_SIGNER_INFO InfSignerInfo);
Another
issue was how to know which driver class a specific driver belonged to. In the
INF files the is an attribute called ClassGUID and these are defined here System-Defined Device Setup Classes
Available to Vendors.
But I really didn’t want to hard code this into the script and have to maintain
them so I also found this class called SetupDiClassNameFromGuid that translates the guid from the OS
instead.
[DllImport("setupapi.dll", EntryPoint = "SetupDiClassNameFromGuidW", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool SetupDiClassNameFromGuid(
ref Guid theGuid, StringBuilder returnBuffer, uint returnBufferSize, out uint requiredSize);
The final
challenge was to create a hash of all the files in the folder matching the hash
from the MDT. There is no built-in method for creating a hash of a folder and
all its content so you must create a hash of each individual file and then
create a new hash of all those hashes combined. The trick here was to not hash
the array of individual hashes but rather joining them in one long string and
remove any line breaks or carriage returns and then hash that sting. Once I did
this, I got a hash matching the one that MDT produced.
So if you care
about security, don’t like to troubleshoot drivers when they fail during an
installation because they are not properly signed and you don’t want to install
MDT just to verify drivers, feel free to use my script!
/Mattias
Benninge
Principal Engineer @ 2Pint Software
@matbg X /
Twitter