Einzelnen Beitrag anzeigen

Benutzerbild von TKC
TKC

Registriert seit: 21. Apr 2004
Ort: Tuningen
367 Beiträge
 
Delphi XE2 Enterprise
 

prüfen ob eine Datei signiert ist

  Alt 3. Mär 2005, 12:19
Eine Unit um zu prüfen ob eine Datei Trusted ist (ob Zertifikat i.O. ist).

Nach Tagelange Arbeit and diesen schlecht Dokumentierten API Schnittstellen hab ich diese Unit fertiggestellt.

Sie wurde auf NT,2000,XP,2003 von mir getestet.

Ich habe versucht den Code so gut wie möglich zu Dokumentieren .


Delphi-Quellcode:
{-----------------------------------------------------------------------------
Unit Name: uSimpleTrustCheck
Author:    ACE-ppc
Date:      04-Apr-2005
Purpose:  Unit for simple check if a file is Trusted
History:  V1.0: Erste Version
            v1.1: Speicher Leaks beseitigt, WINTRUST_DATA Struktur angepasst
                 
-----------------------------------------------------------------------------}



unit uSimpleTrustCheck;

interface

function CheckFileTrust(const sFilename: string): Boolean;

implementation

uses
  Windows,
  SysUtils;

const
  //Kostanten für die dwUnionChoice in WINTRUST_DATA
  WTD_CHOICE_FILE = 1;
  WTD_CHOICE_CATALOG = 2;

  //Konstanten für dwStateAction
  WTD_STATEACTION_IGNORE = 0;
  WTD_STATEACTION_VERIFY = 1;

  //UI Konstanten für WINTRUST_DATA
  WTD_UI_NONE = 2; //kein UI anzeigen

  //Konstanten zur Prüfung auf zurückgezogene Zertifikate
  WTD_REVOKE_NONE = 0; // keine zusätzliche Prüfun

  //Konstanten für TrustProvider
  WTD_SAFER_FLAG = 256; // für Winxp Sp2 benötigt

  //Wintrust Action GUID´s
  WINTRUST_ACTION_GENERIC_VERIFY_V2: TGUID = '{00AAC56B-CD44-11d0-8CC2-00C04FC295EE}';


type

  CATALOG_INFO = record
    cbStruct: DWORD; // = sizeof(WINTRUST_CATALOG_INFO)
    sCatalogFile: array[0..MAX_PATH] of WCHAR; // Dateiname incl. Pfad zur CAT Datei
  end;
  PCATALOG_INFO = ^CATALOG_INFO;


  WINTRUST_CATALOG_INFO = record
    cbStruct: DWORD; // = sizeof(WINTRUST_CATALOG_INFO)
    dwCatalogVersion: DWORD; // optional
    pcwszCatalogFilePath: LPCWSTR; // benötigt, Dateiname incl. Pfad zur CAT Datei
    pcwszMemberTag: LPCWSTR; // benötigt, tag zum Mitglied im Katalog
    pcwszMemberFilePath: LPCWSTR; // benötigt, Dateiname incl. Pfad
    hMemberFile: THANDLE; // optional
  end;
  PWINTRUST_CATALOG_INFO = ^WINTRUST_CATALOG_INFO;


  WINTRUST_FILE_INFO = record
    cbStruct: DWORD; // = sizeof(WINTRUST_FILE_INFO)
    pcwszFilePath: LPCWSTR; // benötigt, Dateiname incl. Pfad
    pgKnownSubject: PGUID; // optional
    hFile: THANDLE; // optional
  end;
  PWINTRUST_FILE_INFO = ^WINTRUST_FILE_INFO;


  WINTRUST_DATA = packed record
    cbStruct: DWORD; // = sizeof(WINTRUST_DATA)
    pPolicyCallbackData: pointer; // optional - auf 0 setzen
    pSIPClientData: pointer; // optional - auf 0 setzen
    dwUIChoice: DWORD; // benötigt, UI auswahl
    fdwRevocationChecks: DWORD; // benötigt, auf zurückgezogene Zertifikate prüfen (online ben.)
    dwUnionChoice: DWORD; // benötigt, welche Datenstruktur soll verwendet werden
    pWTDINFO: pointer; // Pointer zu einer der Wintrust_X_Info Strukturen
    pFake: pointer; //Fake Pointer - nötig damit der Speicer wieder freigegeben wird
    pFake1: pointer; //Fake Pointer - nötig damit der Speicer wieder freigegeben wird
    pFake2: pointer; //Fake Pointer - nötig damit der Speicer wieder freigegeben wird
    pFake3: pointer; //Fake Pointer - nötig damit der Speicer wieder freigegeben wird
    dwStateAction: DWORD;
    hWVTStateData: THANDLE;
    pwszURLReference: PWChar;
    dwProvFlags: DWORD;
    dwUIContext: DWORD;

  end;
  PWINTRUST_DATA = ^WINTRUST_DATA;

  //Handle und Pointer auf KatalogAdminKontext
  HCatAdmin = THANDLE;
  PHCatAdmin = ^HCatAdmin;


var
  hLibWintrust : THANDLE;

  //dynamische Dll Aufrufe - keine Statische einbindung möglich
  CryptCATAdminAcquireContext : function(PHCatAdmin: PHCatAdmin; pgSubsystem: PGUID; dwFlags: DWORD): BOOL; stdcall;
  CryptCATAdminReleaseContext : function(HCatAdmin: HCatAdmin; dwFlags: DWORD): BOOL; stdcall;
  CryptCATAdminCalcHashFromFileHandle: function(hFile: THANDLE; pHashSize: PDWORD; pbHash: PByteArray; dwFlags: DWORD): BOOL; stdcall;
  CryptCATAdminEnumCatalogFromHash: function(HCatAdmin: HCatAdmin; pbHash: PByteArray; pHashSize: DWORD; dwFlags: DWORD; phPrevCatInfo: PHandle): THANDLE; stdcall;
  CryptCATCatalogInfoFromContext: function(hCatInfo: THANDLE; psCatInfo: PCATALOG_INFO; dwFlags: DWORD): BOOL; stdcall;
  CryptCATAdminReleaseCatalogContext: function(HCatAdmin: HCatAdmin; hCatInfo: THANDLE; dwFlags: DWORD): BOOL; stdcall;
  WinVerifyTrust : function(hwnd: THANDLE; pgActionID: PGUID; pWintrustData: PWINTRUST_DATA): Longint; stdcall;





{-----------------------------------------------------------------------------
  Funcktion:  CheckFileTrust
  Date:        02-Mrz-2005
  Arguments:  const sFilename: string
  Result:      Boolean
  Description: Prüft ob die angegebene Datei Trusted ist
-----------------------------------------------------------------------------}

function CheckFileTrust(const sFilename: string): Boolean;
var
  //Byte Array und Counter
  aByteHash : array[0..255] of Byte;
  iByteCount : Integer;

  hCatAdminContext : HCatAdmin;
  WTrustData : WINTRUST_DATA;
  WTDCatalogInfo : WINTRUST_CATALOG_INFO;
  WTDFileInfo : WINTRUST_FILE_INFO;
  CatalogInfo : CATALOG_INFO;

  hFile : THANDLE;
  hCatalogContext : THANDLE;

  swFilename : WideString;
  swMemberTag : WideString;

  ilRet : Longint;
  x : Integer;

begin

  //Standard Result setzen
  Result := False;

  //Sicherheitsabfrage ob Datei existiert
  if FileExists(sFilename) = False then Exit;

  //String in Widestring wandeln
  swFilename := sFilename;


  ZeroMemory(@CatalogInfo, SizeOf(CatalogInfo));
  ZeroMemory(@WTDFileInfo, SizeOf(WTDFileInfo));
  ZeroMemory(@WTDCatalogInfo, SizeOf(WTDCatalogInfo));
  ZeroMemory(@WTrustData, SizeOf(WTrustData));


  //Catalog Admin Kontext öffnen und falls nicht möglich Prozedur verlassen
  if CryptCATAdminAcquireContext(@hCatAdminContext, nil, 0) = False then Exit;


  //Filehandle auf die zu prüfende Datei holen
  hFile := CreateFile(PChar(string(sFilename)), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

  //Wenn das Handle nicht erhalten wurde Prozedur verlassen
  if hFile = INVALID_HANDLE_VALUE then Exit;


  //iaBytescount nach größe des Arrays setzen
  iByteCount := SizeOf(aByteHash);

  //ByteArray mit Hash füllen lassen und die Größe in iByteCount bekommen
  CryptCATAdminCalcHashFromFileHandle(hFile, @iByteCount, @aByteHash, 0);

  // MemberTag brechnen (vom ByteArray auf HEX)
  for x := 0 to iByteCount - 1 do
  begin
    swMemberTag := swMemberTag + IntToHex(aByteHash[x], 2);
  end;

  //FileHandle schließen - wird nicht mehr gebraucht
  CloseHandle(hFile);


  //Erste Prüfung erfolgt mit WINTRUST_DATA.dwUnionChoice := WTD_CHOICE_CATALOG;
  //also muss WINTRUST_CATALOG_INFO gefüllt werden
  //
  //Handle auf den Katalog Kontext holen
  hCatalogContext := CryptCATAdminEnumCatalogFromHash(hCatAdminContext, @aByteHash, iByteCount, 0, nil);

  //Wenn das Handle 0 ist muss die Prüfung mit der
  //WINTRUST_DATA.dwUnionChoice := WTD_CHOICE_FILE; Struktur durchgeführt werden
  if hCatalogContext = 0 then
  begin
    //CatalogContext = 0 also
    //
    //WINTRUST_FILE_INFO Struktur initialisieren und füllen
    WTDFileInfo.cbStruct := SizeOf(WTDFileInfo);
    WTDFileInfo.pcwszFilePath := PWideChar(swFilename);
    WTDFileInfo.pgKnownSubject := nil;
    WTDFileInfo.hFile := 0;

    //WINTRUST_DATA Struktur initialisieren und füllen
    WTrustData.cbStruct := SizeOf(WTrustData);
    WTrustData.dwUnionChoice := WTD_CHOICE_FILE; //WINTRUST_FILE_INFO Struktur wählen
    WTrustData.pWTDINFO := @WTDFileInfo; //Pointer zu WINTRUST_FILE_INFO
    WTrustData.dwUIChoice := WTD_UI_NONE;
    WTrustData.fdwRevocationChecks := WTD_REVOKE_NONE;
    WTrustData.dwStateAction := WTD_STATEACTION_IGNORE;
    WTrustData.dwProvFlags := WTD_SAFER_FLAG; //UI bei XP SP2 unterbinden
    WTrustData.hWVTStateData := 0;
    WTrustData.pwszURLReference := nil;
  end
  else
  begin
    //CatalogContext <> 0 also CATALOG_INFO benutzen
    //
    //CATALOG_INFO Struktur füllen
    CryptCATCatalogInfoFromContext(hCatalogContext, @CatalogInfo, 0);

    //WINTRUST_CATALOG_INFO Struktur initialisieren und füllen
    WTDCatalogInfo.cbStruct := SizeOf(WTDCatalogInfo);
    WTDCatalogInfo.pcwszCatalogFilePath := CatalogInfo.sCatalogFile;
    WTDCatalogInfo.pcwszMemberFilePath := PWideChar(swFilename);
    WTDCatalogInfo.pcwszMemberTag := PWideChar(swMemberTag);

    //WINTRUST_DATA Struktur initialisieren und füllen
    WTrustData.cbStruct := SizeOf(WTrustData);
    WTrustData.dwUnionChoice := WTD_CHOICE_CATALOG; //WINTRUST_CATALOG_INFO Struktur wählen
    WTrustData.pWTDINFO := @WTDCatalogInfo; //Pointer zu WINTRUST_CATALOG_INFO
    WTrustData.dwUIChoice := WTD_UI_NONE;
    WTrustData.fdwRevocationChecks := WTD_REVOKE_NONE;
    WTrustData.pPolicyCallbackData := nil;
    WTrustData.pSIPClientData := nil;
    WTrustData.dwStateAction := WTD_STATEACTION_VERIFY;
    WTrustData.dwProvFlags := 0; //WTD_SAFER_FLAG; //UI bei XP SP2 unterbinden
    WTrustData.hWVTStateData := 0;
    WTrustData.pwszURLReference := nil;
  end;

  //WinVerifyTrust aufrufen um die Prüfung durchzuführen
  ilRet := WinVerifyTrust(INVALID_HANDLE_VALUE, @WINTRUST_ACTION_GENERIC_VERIFY_V2, @WTrustData);

  //Wenn Erg. 0 ist dann ist das File Trusted - alle anderen Werte sind Fehlercodes
  if ilRet = 0 then
  begin
    Result := True
  end
  else
    Result := False;

  //Handle zum Catalogfile schließen
  CryptCATAdminReleaseCatalogContext(hCatAdminContext, hCatalogContext, 0);

  //Catalog Admin Kontext schließen
  CryptCATAdminReleaseContext(hCatAdminContext, 0);
end;



initialization
  //Dynamisches laden der Dll und deren Funktionen
  hLibWintrust := LoadLibrary('wintrust.dll');
  if hLibWintrust >= 32 then { success }
  begin
    CryptCATAdminAcquireContext := GetProcAddress(hLibWintrust, 'CryptCATAdminAcquireContext');
    CryptCATAdminReleaseContext := GetProcAddress(hLibWintrust, 'CryptCATAdminReleaseContext');
    CryptCATAdminCalcHashFromFileHandle := GetProcAddress(hLibWintrust, 'CryptCATAdminCalcHashFromFileHandle');
    CryptCATAdminEnumCatalogFromHash := GetProcAddress(hLibWintrust, 'CryptCATAdminEnumCatalogFromHash');
    CryptCATCatalogInfoFromContext := GetProcAddress(hLibWintrust, 'CryptCATCatalogInfoFromContext');
    CryptCATAdminReleaseCatalogContext := GetProcAddress(hLibWintrust, 'CryptCATAdminReleaseCatalogContext');
    WinVerifyTrust := GetProcAddress(hLibWintrust, 'WinVerifyTrust');
  end;

finalization
  FreeLibrary(hLibWintrust);
end.
[edit=Matze]Neuere Version upgedated. Mfg, Matze[/edit]
[edit=Matze]Code formatiert. Mfg, Matze[/edit]
  Mit Zitat antworten Zitat