wordpress   发布时间:2022-04-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了windows – 从Delphi中以编程方式检查数字签名大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

概述

我需要一个Delphi中的函数来验证外部EXE或DLL的数字签名。在我的特定应用程序中,我偶尔会调用其他进程,但为了安全起见,我想确保这些可执行文件是在我们的组织运行之前创建的。 我已经看到了Microsoft’s example in C,但是如果别人已经有了,我不想浪费时间将其转换为Delphi。 我更喜欢第三方图书馆的代码段或代码示例。谢谢。 干得好: // IsCodeSigned, wh
我需要一个Delphi中的函数来验证外部EXE或DLL的数字签名。在我的特定应用程序中,我偶尔会调用其他进程,但为了安全起见,我想确保这些可执行文件是在我们的组织运行之前创建的。

我已经看到了Microsoft’s example in C,但是如果别人已经有了,我不想浪费时间将其转换为Delphi。

我更喜欢第三方图书馆的代码段或代码示例。谢谢。

干得好:
// IsCodeSigned,which verifies that the exe hasn't been modified,uses
// WinVerifyTrust,so it's NT only.  IsCompanySigningCertificate works on Win9x,// but it only checks that the signing certificate hasn't been replaced,which
// keeps someone from re-signing a modified executable.

// Imagehlp.dll
const
  CERT_SECTION_TYPE_ANY = $FF;      // Any Certificate type

function ImageEnumerateCertificates(FileHandle: THandle; TypeFilter: WORD;
  out CertificateCount: DWORD; InDicies: PDWORD; IndexCount: Integer): BOOL; stdcall; external 'Imagehlp.dll';
function ImageGetCertificateHeader(FileHandle: THandle; CertificateIndex: Integer;
  var CertificateHeader: TWinCertificatE): BOOL; stdcall; external 'Imagehlp.dll';
function ImageGetCertificateData(FileHandle: THandle; CertificateIndex: Integer;
  Certificate: PWinCertificate; var requiredLength: DWORD): BOOL; stdcall; external 'Imagehlp.dll';

// Crypt32.dll
const
  CERt_name_SIMPLE_DISPLAY_TYPE = 4;
  PKCS_7_ASN_ENCODING = $00010000;
  X509_ASN_ENCODING = $00000001;

type
  PCCERT_COntexT = type Pointer;
  HCRYPTPROV_LEGACY = type Pointer;
  PFN_CRYPT_GET_SIGNER_CERTIFICATE = type Pointer;

  CRYPT_VERIFY_messaGE_PARA = record
    cbSize: DWORD;
    dwMsgAndCertEncodingType: DWORD;
    hCryptProv: HCRYPTPROV_LEGACY;
    pfnGetSignerCertificate: PFN_CRYPT_GET_SIGNER_CERTIFICATE;
    pvGetArg: Pointer;
  end;

function CryptVerifymessageSignature(const pVerifyPara: CRYPT_VERIFY_messaGE_PARA;
  dwSignerIndex: DWORD; pbSignedBlob: PByte; cbSignedBlob: DWORD; pbDecoded: PBYTE;
  pcbDecoded: PDWORD; ppSignerCert: PCCERT_COntexT): BOOL; stdcall; external 'Crypt32.dll';
function CertGetNameStringA(pCertContext: PCCERT_COntexT; dwType: DWORD; dwFlags: DWORD; pvTypePara: Pointer;
  pszNameString: PAnsiChar; cchNameString: DWORD): DWORD; stdcall; external 'Crypt32.dll';
function CertFreeCertificateContext(pCertContext: PCCERT_COntexT): BOOL; stdcall; external 'Crypt32.dll';
function CertCreateCertificateContext(dwCertEncodingType: DWORD;
  pbCertEncoded: PBYTE; cbCertEncoded: DWORD): PCCERT_COntexT; stdcall; external 'Crypt32.dll';

// WinTrust.dll
const
  WINTRUST_ACTION_GENERIC_VERIFY_V2: TGUID = '{00AAC56B-CD44-11d0-8CC2-00C04FC295EE}';
  WTD_CHOICE_FILE = 1;
  WTD_REVOKE_NONE = 0;
  WTD_UI_NONE = 2;

type
  PWinTrustFileInfo = ^TWinTrustFileInfo;
  TWinTrustFileInfo = record
    cbStruct: DWORD;                    // = sizeof(WINTRUST_FILE_INFO)
    pcwszFilePath: PWideChar;           // required,file name to be verified
    hFile: THandle;                     // optional,open handle to pcwszFilePath
    pgKNownSubject: PGUID;              // optional: fill if the subject type is kNown
  end;

  PWinTrustData = ^TWinTrustData;
  TWinTrustData = record
    cbStruct: DWORD;
    pPolicyCallBACkData: Pointer;
    pSIPClientData: Pointer;
    dwUIChoice: DWORD;
    fdwRevocationchecks: DWORD;
    dwUnionChoice: DWORD;
    pFile: PWinTrustFileInfo;
    dwStateAction: DWORD;
    hWVTStateData: THandle;
    pwszURLReference: PWideChar;
    dwProvFlags: DWORD;
    dwUIContext: DWORD;
  end;

function WinVerifyTrust(hwnd: HWND; const ActionID: TGUID; ActionData: Pointer): Longint; stdcall; external wintrust;

{-----------------------------------------------}

function IsCodeSigned(const Filename: String): Boolean;
var 
  file_info: TWinTrustFileInfo;
  trust_data: TWinTrustData;
begin
  // Verify that the exe is signed and the checksum matches
  FillChar(file_info,SizeOf(file_info),0);
  file_info.cbStruct := sizeof(file_info);
  file_info.pcwszFilePath := PWideChar(WideString(FileName));
  FillChar(trust_data,SizeOf(trust_data),0);
  trust_data.cbStruct := sizeof(trust_data);
  trust_data.dwUIChoice := WTD_UI_NONE;
  trust_data.fdwRevocationchecks := WTD_REVOKE_NONE;
  trust_data.dwUnionChoice := WTD_CHOICE_FILE;
  trust_data.pFile := @file_info;
  Result := WinVerifyTrust(INVALID_HANDLE_VALUE,WINTRUST_ACTION_GENERIC_VERIFY_V2,@trust_data) = ERROR_succesS
end;

{-----------------------------------------------}

function IsCompanySigningCertificate(const Filename,CompanyName :string): Boolean;
var
  hExe: HMODULE;
  Cert: PWinCertificate;
  CertContext: PCCERT_COntexT;
  CertCount: DWORD;
  CertName: AnsiString;
  CertNameLen: DWORD;
  VerifyParams: CRYPT_VERIFY_messaGE_PARA;
begin
  // Returns TRUE if the SubjectName on the certificate used to sign the exe is
  // "Company Name".  Should prevent a cracker from modifying the file and
  // re-signing it with their own certificate.
  //
  // Microsoft has an example that does this using CryptQueryObject and
  // CertFindCertificateInStore instead of CryptVerifymessageSignature,but
  // CryptQueryObject is NT-only.  Using CertCreateCertificateContext doesn't work
  // either,though I don't kNow why.
  Result := false;
  // Verify that the exe was signed by our private key
  hExe := CreateFile(PChar(FileName),GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTinG,FILE_ATTRIBUTE_NORMAL or FILE_FLAG_RANDOM_ACCESS,0);
  if hExe = INVALID_HANDLE_VALUE then
    Exit;
  try
    // There should only be one certificate associated with the exe
    if (not ImageEnumerateCertificates(hExe,CERT_SECTION_TYPE_ANY,CertCount,0)) or
       (CertCount <> 1) then
      Exit;
    // Read the certificate header so we can get the size needed for the full cert
    GetMem(Cert,SizeOf(TWinCertificatE) + 3); // ImageGetCertificateHeader writes an DWORD at bCertificate for some reason
    try
      Cert.dwLength := 0;
      Cert.wRevision := WIN_CERT_REVISION_1_0;
      if not ImageGetCertificateHeader(hExe,Cert^) then
        Exit;
      // Read the full certificate
      ReallOCMem(Cert,SizeOf(TWinCertificatE) + Cert.dwLength);
      if not ImageGetCertificateData(hExe,Cert,Cert.dwLength) then
        Exit;
      // Get the certificate context.  CryptVerifymessageSignature has the
      // side effect of creaTing a context for the signing certificate.
      FillChar(VerifyParams,SizeOf(VerifyParams),0);
      VerifyParams.cbSize := SizeOf(VerifyParams);
      VerifyParams.dwMsgAndCertEncodingType := X509_ASN_ENCODING or PKCS_7_ASN_ENCODING;
      if not CryptVerifymessageSignature(VerifyParams,@Cert.bCertificate,Cert.dwLength,@CertContext) then
        Exit;
      try
        // Extract and compare the certificate's subject names.  Don't
        // compare the entire certificate or the public key as those will
        // change when the certificate is renewed.
        CertNameLen := CertGetNameStringA(CertContext,CERt_name_SIMPLE_DISPLAY_TYPE,0);
        SetLength(CertName,CertNameLen - 1);
        CertGetNameStringA(CertContext,PAnsiChar(CertName),CertNameLen);
        if CertName <> CompanyName then 
          Exit;
      finally
        CertFreeCertificateContext(CertContext)
      end;
    finally
      FreeMem(Cert);
    end;
  finally
    CloseHandle(hExE);
  end;
  Result := True;
end;

大佬总结

以上是大佬教程为你收集整理的windows – 从Delphi中以编程方式检查数字签名全部内容,希望文章能够帮你解决windows – 从Delphi中以编程方式检查数字签名所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。