Code signing of files verification

How do I check whether a binary file (exe or dll) is code signed by a certain company?

Could someone please point me in the right direction as I have searched a fair amount and am yet to have
laid my hands upon a working example..
robbiegroveAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Mark BradyPrincipal Data EngineerCommented:
I found the following on EE......

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
code_signing.htm" target="_blank" onclick="return openNew(this.href);">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).

Elvin
robbiegroveAuthor Commented:
I want to check an already installed file..
Mark BradyPrincipal Data EngineerCommented:
Well did you read the articles(links) above ?
Introduction to R

R is considered the predominant language for data scientist and statisticians. Learn how to use R for your own data science projects.

robbiegroveAuthor Commented:
The above links were VERY BASIC overview of the fact that Microsoft signs its own binaries?
I'm after something that allows me to check whether ANY file I specify is signed by my company..
robbiegroveAuthor Commented:
Just to specify if it wasn't obvious this needs to be done programmatically in Delphi..
peterwhenryCommented:
You can check an EXE file using the CryptQueryObject API. This function returns a BLOB containing OID
encoded information about the certificate that was used to sign the file. Sadly you can't easily get the
complete information here but it does return the friendly name and the version. This is a unique identification
of a certificate.

If you don't have a signed EXE then you can download the PCL and PDF viewer from http://www.pclviewer.com

You need the JEDI units and a copy of CERTMGR will help you understand the process

program signcheck;
// demo checking an EXE for a signature
{$APPTYPE CONSOLE}

uses
  SysUtils,
  JwaWinCrypt in 'JwaWinCrypt.pas',  // download from http://delphi-jedi.org
  Windows;


procedure RDNDecode(s:string);
// Relative Distinguished Name
// This is not an exhaustive or rigorous or fast decode
// See the excellent http://luca.ntop.org/Teaching/Appunti/asn1.html
  function fetch:byte;
  begin
    if s<>'' then result:=ord(s[1]) else result:=ord('?');
    delete(s,1,1);
  end;
var
  l:byte;
  oid:string;
  i:integer;
begin
  repeat
    l:=fetch;
    case l of
      $30: // it's a sequence
      begin
        l:=fetch;
        // writeln('sequence of ',l,'. bytes ',length(s),' available');
      end;
      $31: //  set of values
      begin
        l:=fetch;
        // writeln('set of ',l,'. values');
      end;
      $13: // Printable string
      begin
        for i:=1 to fetch do write(char(fetch));
        writeln;
      end;
      $6:  // an OID (object identifier)
      begin
        oid:='';
        l:=fetch;
        write('OID ');
        for i:=1 to l do
        if i=1 then
        begin
          l:=fetch;
          oid:=inttostr(l div 40)+'.'+inttostr(l mod 40);
        end else
        begin
          l:=fetch;
          oid:=oid+'.'+inttostr(l)
        end;
        write(OID,'=');
        if OID=szOID_COUNTRY_NAME then writeln('COUNTRY NAME')
          else if OID=szOID_ORGANIZATION_NAME then writeln('ORGANIZATION_NAME')
          else if OID=szOID_COMMON_NAME then writeln('COMMON NAME')
          else writeln('UNKNOWN');
      end;

      else
      begin
        writeln('Unknown tag $',format('%2.2x',[ord(l)]));
        break;
      end;
    end;
  until s='';
end;

var
  SignerInfo: PCmsgSignerInfo;
  CertInfo: TCertInfo;
  Msg:HCRYPTMSG;
  StoreHandle:HCERTSTORE;
  Filepath:WideString;
  CT:Dword;
  DataSize: Cardinal = 0;

  s:string;
  i:integer;
begin // signcheck program
  try
    FilePath:='c:\program files\redtitan\software\escapee.exe'; // ParamStr(1);
    if not fileexists(FilePath)
      then raise Exception.Create('File '+FilePath+'not found');
    CT:=0;
    if not CryptQueryObject(CERT_QUERY_OBJECT_FILE, @FilePath[1], CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
      CERT_QUERY_FORMAT_FLAG_BINARY, 0, nil, @CT, nil, @StoreHandle, @Msg, nil)
      then raise Exception.Create('?File not codesigned ');

    try
      if CT<>CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED then
        raise Exception.Create('Content type '+inttostr(CT)+' unsupported');

      // check signer info size requirement
      if not CryptMsgGetParam(Msg,CMSG_SIGNER_INFO_PARAM,0,nil,DataSize)
        then  raise Exception.Create('?File access denied') ;

      Getmem(SignerInfo,DataSize);
      try
        CryptMsgGetParam(Msg, CMSG_SIGNER_INFO_PARAM, 0, SignerInfo, DataSize);
        writeln(Filepath,' is signed as follows');
        setlength(s,SignerInfo^.SerialNumber.cbData);
        move(SignerInfo^.SerialNumber.pbData^,s[1],length(s));
        write('Version ');
        for i:=length(s) downto 1 do write(format('%x ',[ord(s[i])]));
        writeln;

        setlength(s,SignerInfo^.Issuer.cbData);
        move(SignerInfo^.Issuer.pbData^,s[1],SignerInfo^.Issuer.cbData);
        RDNDecode(s);
// You could plug the Signer info into a CertInfo structure and locate the certificate in a store
// CertFindCertificateInStore(Store, X509_ASN_ENCODING or PKCS_7_ASN_ENCODING,
//  0,CERT_FIND_SUBJECT_CERT, @CertInfo, nil);
       finally
         FreeMem(SignerInfo);
      end;
    finally
      CertCloseStore(StoreHandle, 0);
      CryptMsgClose(Msg);
    end;
  except
    on E: Exception do
      ShowException(E, ExceptAddr);
  end;
  readln;
end.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.