Solved

WHQL driver signing check

Posted on 2002-07-03
15
1,433 Views
Last Modified: 2012-08-14
WHQL driver signing ensure that a particular driver has been certified for use with Windows 2000 or Windows XP.
How can I check if a file (.sys,.exe,.dll) is WHQL-signed with Delphi? I need the source of a function like IsFileWHQLsigned('explorer.exe').
(Explorer.exe has no Authenticode signature, but the file is WHQL-signed. Check this with sigverif.exe.)
0
Comment
Question by:Kann
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 6
15 Comments
 

Author Comment

by:Kann
ID: 7126475
Read this hint about "WHQL driver signing":
The confusion here is that we are talking about two TOTALLY DIFFERENT types of signatures: code signing (i.e., Authenticode) vs. WHQL driver signing. The first one, code signing, is used to authenticate the author of an executable.  The second is to ensure that a particular driver has been certified for use with Windows 2000 or
Windows XP.
0
 
LVL 8

Accepted Solution

by:
TOndrej earned 500 total points
ID: 7126542
It's not clear whether you want to check an already installed file or an external file before installation.

http://support.microsoft.com/default.aspx?scid=kb;EN-US;q224404
http://www.microsoft.com/windows2000/en/datacenter/help/default.asp?url=/windows2000/en/datacenter/help/code_signing.htm

There are utilities to check already installed files, like sfc and sigverif.

It seems that WHQL signature is a standard Authenticode signature of a .cat file that comes with the driver. This .cat file was specified in the .inf file during installation.

sigverif imports WinVerifyTrust API from wintrust.dll and that supports my theory (WinVerifyTrust uses the standard CryptoAPI functions). I guess you need to call WinVerifyTrust, passing it the catalog file (.cat).

Sorry I don't have more details.
0
 
LVL 8

Expert Comment

by:TOndrej
ID: 7126559
I've just found out that you can use the crypttest2 utility from your previous question on .cat files in %SystemRoot%\CatRoot\... subdirectories.
The question is how to determine which .cat file is associated with a particular driver file (.sys, .dll)...
I have no idea about this.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 8

Expert Comment

by:TOndrej
ID: 7126568
Do a Google on 'WinVerifyTrust', you'll find interesting info, e.g.
http://www.winntmag.com/Articles/Index.cfm?ArticleID=7088&pg=1
0
 

Author Comment

by:Kann
ID: 7126726
Hello TOndrej,

I want to check an already installed file.

> The question is how to determine which .cat file is associated with a particular driver file (.sys, .dll)...

Yes, that is the question. I study sigverif.exe, which checks if a file is WHQL-signed. Sigverif.exe use this API:

MSCAT32.dll
           6     CryptCATAdminReleaseContext
          15     CryptCATCatalogInfoFromContext
           4     CryptCATAdminEnumCatalogFromHash
           1     CryptCATAdminAcquireContext
           5     CryptCATAdminReleaseCatalogContext
          33     IsCatalogFile
           3     CryptCATAdminCalcHashFromFileHandle
WINTRUST.dll
         107     WinVerifyTrust

Perhaps this can help you?
0
 
LVL 8

Expert Comment

by:TOndrej
ID: 7127036
Sorry, I couldn't find any documentation on mscat32.dll and its functions.
0
 
LVL 8

Expert Comment

by:TOndrej
ID: 7127108
(My understanding of MSDN is that) if you just want to check if the file is in the WHQL-approved list then you can use SfcIsFileProtected API.
For the complete list of WHQL-approved files, you can use SfcGetNextProtectedFile API.

Here is a quick sample that demonstrates how to use these APIs:

program crypttest3;

{$APPTYPE CONSOLE}

uses
  SysUtils, Windows;

type
  PProtectedFileData = ^TProtectedFileData;
  TProtectedFileData = packed record
    FileName: array[0..MAX_PATH + 1] of WideChar;
    FileNumber: DWORD;
  end;

const
  BoolStrs: array[Boolean] of string = ('No', 'Yes');

var
  SFC: THandle = 0;
  SfcGetNextProtectedFile: function(RpcHandle: THandle; var ProtFileData: TProtectedFileData): BOOL; stdcall = nil;
  SfcIsFileProtected: function(RpcHandle: THandle; ProtFileName: PWideChar): BOOL; stdcall = nil;

  ProtFileData: TProtectedFileData;
begin
  try
    // include OS checks here; exit if not running Win98, Win2K or newer
    SFC := LoadLibrary('sfc.dll');
    if SFC = 0 then
      raise Exception.Create('Cannot load SFC.DLL');
    try
      @SfcGetNextProtectedFile := GetProcAddress(SFC, 'SfcGetNextProtectedFile');
      if @SfcGetNextProtectedFile = nil then
        raise Exception.Create('Cannot find SfcGetNextProtectedFile');
      @SfcIsFileProtected := GetProcAddress(SFC, 'SfcIsFileProtected');
      if @SfcIsFileProtected = nil then
        raise Exception.Create('Cannot find SfcIsFileProtected');

      FillChar(ProtFileData, SizeOf(TProtectedFileData), 0);
      while SfcGetNextProtectedFile(0, ProtFileData) do
      begin
        Writeln(ProtFileData.FileName, ': ', BoolStrs[SfcIsFileProtected(ProtFileData.FileName)]);
        Inc(ProtFileData.FileNumber);
      end;
    finally
      FreeLibrary(SFC);
    end;
  except
    on E: Exception do
      ShowException(E, ExceptAddr);
  end;
end.

If you're after retrieving the actual driver signature then sorry, I'm stuck... sigverif seems to use a lot of undocumented functions. :-(
Some of the stuff is described in the links I posted.
Good luck, anyway.

HTH
TOndrej
0
 

Author Comment

by:Kann
ID: 7127204
Not every signed driver is also write-protected. (But the most signed driver seems to be write-protected.)
I will get you the point, because you have done a good work. Perhaps you can answer the following question (this will solve the problem 100%):

I found in the links you posted:
<<After obtaining the file hash, SfcValidateFileSignature uses another CryptoAPI to obtain a reference to the catalog file that contains the hashed file's digital signature.>>
Do you have an idea which CryptoAPI obtain a reference to the catalog file?

Thank you very much!
0
 
LVL 8

Expert Comment

by:TOndrej
ID: 7127325
> Do you have an idea which CryptoAPI obtain a reference to the catalog file?

Sorry, no idea. I think it's using the CryptCATxxx functions exported in mscat32.dll but I couldn't find any info about them anywhere in the MSDN. Even Google didn't help, either.

I suggest you keep your points. I cannot help you with the problem.
0
 

Author Comment

by:Kann
ID: 7127409
I will give you the point - perhaps I need your help again ;-)

(If you found somethink interestig about this topic feel free to email me: kann@sharepower.virtualave.net)
0
 
LVL 8

Expert Comment

by:TOndrej
ID: 7127426
OK but no promises. <g>
0
 

Author Comment

by:Kann
ID: 7129502
Here comes the points.

If you have some Delphi source how to use:
  WIN_SPUB_ACTION_NT_ACTIVATE_IMAGE
  WINTRUST_ACTION_GENERIC_VERIFY_V2
I would be happy if you show this me. (Sorry for my bad English.)
0
 
LVL 8

Expert Comment

by:TOndrej
ID: 7129566
They look like C constant declarations, they're probably declared in one of the header (.h) files in MS Platform SDK. What do you mean, how to use them?

Thanks for the undeserved points.
0
 

Author Comment

by:Kann
ID: 7130147
The function WinVerifyTrust() used this constants. Perhaps do you have a piece of source code how to use this?
0
 
LVL 8

Expert Comment

by:TOndrej
ID: 7132110
I have MS Platform SDK of November 2001 and I've found the following:

WINTRUST_ACTION_GENERIC_VERIFY_V2 is declared in SoftPub.h
WIN_SPUB_ACTION_NT_ACTIVATE_IMAGE is declared in WinTrust.h

The Pascal translations are:

const
(*
#define     WIN_SPUB_ACTION_NT_ACTIVATE_IMAGE                    \
            { 0x8bc96b00,                                        \
              0x8da1,                                            \
              0x11cf,                                            \
              {0x87, 0x36, 0x00, 0xaa, 0x00, 0xa4, 0x85, 0xeb}   \
            }
*)
  WIN_SPUB_ACTION_NT_ACTIVATE_IMAGE: TGUID = '{8BC96B00-8DA1-11CF-8736-00AA00A485EB}';

(*
//////////////////////////////////////////////////////////////////////////////
//
// WINTRUST_ACTION_GENERIC_VERIFY_V2 Guid  (Authenticode)
//----------------------------------------------------------------------------
//  Assigned to the pgActionID parameter of WinVerifyTrust to verify the
//  authenticity of a file/object using the Microsoft Authenticode
//  Policy Provider,
//
//          {00AAC56B-CD44-11d0-8CC2-00C04FC295EE}
//
#define WINTRUST_ACTION_GENERIC_VERIFY_V2                       \
            { 0xaac56b,                                         \
              0xcd44,                                           \
              0x11d0,                                           \
              { 0x8c, 0xc2, 0x0, 0xc0, 0x4f, 0xc2, 0x95, 0xee } \
            }
*)
  WINTRUST_ACTION_GENERIC_VERIFY_V2: TGUID = '{00AAC56B-CD44-11d0-8CC2-00C04FC295EE}';

HTH
TOndrej
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

737 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question