[VB6] Digital signature verifier (Authenticode and WHQL)
------------------ How to start?
Just add module 'modDigiSign.bas' to your project and look in 'Examples of using' below.
------------------
Hi,
I would like to present digital signature checker for executables and other file formats containing the code.
Purpose:
It is a well-tested module that allows you to verify things like:
- is signature legitimate (without need of internet connection)
- is driver's WHQL signature legitimate
- is signature belongs to Microsoft
- is signature embedded or external (signed by catalog)
- is signature present (by checking PE structure)
It can show info about certificates:
- validity date (begin / end period)
- issued by
- issued to (signer name)
- issued to (signer email)
Info about signature includes:
- short and extended description of verify results
- hash algoritms of signature digest and certificate's signature
- number of signatures
- timestamp (time of signing)
Demo project also contains code to check:
- is file PE EXE formatted
- is file SFC / WPF protected
Creates a report in CSV format.
Compatibility:
OS: Windows 10 / 8.1 / 8 / 7 / Vista / XP / 2000, both x32 and x64 bit, include 64-bit executables and 64-bit folders.
Hash algorithms of signature / digest: MD5, SHA1, SHA256.
Unicode aware.
Uses CryptoAPI, no other dependencies.
Requirements:
- If you are using File System Redirector in your program, make sure that it is NOT 'turned OFF' before calling functions of this module.
It is very important! If you cannot guarantee it, to ensure compatibility, you can call my wrapper "ToggleWow64FSRedirection (true / false)" from this module instead of your function.
- Do not use any sort of IDE emulations like 'compatiblity with XP' while running via IDE. It can take a negative effect on result of verifying.
License:
You can use modDigiSign.bas in your projects for free.
Full or partial re-publication of this info, attached article (including translation), projects and sources is prohibited without the direct permission of the author (me).
Examples of using:
General syntax:
Code:
Dim SignResult As SignResult_TYPE
SignVerify [File to check], [Flags], [out_SignResult]
1. Check is signature legitimate:
Code:
Dim SignResult As SignResult_TYPE
Debug.? "SignedAndVerified ? " & SignVerify("c:\path\File_to_test.exe", 0, SignResult)
Also, look in exampes / flags / tools description in posts below.
Public Enum FLAGS_SignVerify
SV_CheckRevocation = 1 ' check whole trust chain for certificate revocation ( require internet connection )
SV_DisableCatalogVerify = 2 ' do not use checking by security catalogue ( check internal signature only )
SV_isDriver = 4 ' verify WHQL signature of driver
SV_CacheDoNotLoad = 8 ' do not read last cached result
SV_CacheDoNotSave = 16 ' do not save results of verification to cache (memory savings)
SV_CacheFree = 32 ' free memory, used by cache subsystem
SV_AllowSelfSigned = 64 ' self-signed certificates should be considered as legitimate
SV_AllowExpired = 128 ' allow signatures with expired date of certificate
SV_CheckEmbeddedPresence = 256 ' always check presence of internal signature ( even if verification performed by catalogue )
SV_CheckSecondarySignature = 512 ' (this flag automatically set SV_DisableCatalogVerify flag)
SV_NoFileSizeLimit = 1024 ' check file with any size ( default limit = 100 MB. )
End Enum
Additional info:
1. Trust chain
Module allows you to iterate all certificates in the chain. SHA256 hash has extracted from the root certificate. All another info - from the final certificate. If you need info from the intermediate certificate, you can do it yourself: all pointers to certifiactes stored in Signature(0).Certificate() array in function GetSignerInfo().
2. Certificate revocation checking (SV_CheckRevocation flag)
I specifically made that verify processing doesn't require internet access. So, program will work fast and will not hang. Certificate revocation will not be performed. If you need one, set flag SV_CheckHoleChain. Be carefull, this checking can took up to 5-30 seconds or even hang program if system has problems with internet connection (multi-threading is recommended).
Actually, this kind of checking needs in very rare cases, like if you want to ensure that certificate wasn't revoked due to its theft with using in malware purposes.
3. Cache (SV_CacheDoNotSave and SV_CacheDoNotLoad flags)
By default, result of checking has stored using Scripting.Dictionary. If you check the same file twice, function will return the same (last) result. To disallow caching, specify the flag SV_CacheDoNotSave. To disable reading from the cache once, specify the flag SV_CacheDoNotLoad.
3.1. Conditional constant #UseSimpleCatCheck.
Allows to use additional level of caching. It works so: if signature of some file is successfully verified by security catalog, all hashed from this catalog has been saved in cache. When next verification made, firstly, hash of new file has check by cache. If it comply, WinVerifyTrust function is not used, because security catalog's signature that contains this hash has been already verified earlier.
4. Checking is root certificate issued by Microsoft.
Performes by comparision hash of first certificate in the trust chain with the list of well-known certificate hashes that contains public Microsoft keys (collected from different OS by me).
There is also an official way to check Microsoft signature: use CertVerifyCertificateChainPolicy() function by passing CERT_CHAIN_POLICY_MICROSOFT_ROOT flag to.
Advantage of my way is: unlike other utilities, I can check is internal signature of file belongs to Microsoft (using base) even if file taken from the different version of OS. However, files signed by catalog cannot be verified in the same way. So, the most reliable way is to perform a checking on user's side where file taken from.
=============================== Applications and sources:
1. Project 'Batch Digital Signature Verifier' (GUI)
2. Project 'Certificate Enumerator' (enumerating of names and hashes of certificates in root storage)
3. Project 'RemoveSign' (to remove digital signature).
4. Project SignVerify (most simple example of using verifier core (modDigiSign.bas module):
4.1. _DigiSign.vbp - immediate window demo
4.2. _DigiSign(Console_с).vbp - console program
Docs:
1. My article (in Russian)
2. OIDs (Object identifiers) (used in signature attributes)
Re: [VB6] Digital signature verifier (Authenticode and WHQL)
Actually, all projects presented above is a part of my article (written in Russian).
Look here: https://safezone.cc/threads/29650/ or in attached docs.
If you are interested in this topic I can try to translate some parts (as it's very huge and hard for me), but in case you are really want.
I'm also gladly answer any question regarding this theme.
Some very-very cut part of translation I done before, I'll post below (just at least to make you understand the difference between internal and external signatures):
Introduction.
There are many places over internet where you can find info about how digital signature verification work. No need to double.
I just tell you a few things that, maybe, can be difficult to find and also a very basic info.
1.4
First of all, "Authenticode" mean that this certificate intended to sign file that contains code (not documents, emails e.t.c.).
1.1.
What is mean legitimate?
It's so-called signature class 3, in another words: this signature should be issued by authority whose certificate is located in storage of trusted root certificates.
You can see these using snap-in certmgr.msc.
Signature verification has executed by WINTRUST_ACTION_GENERIC_VERIFY_V2 policy flag passed to WinVerifyTrust() function. This policy require:
1) The certificate used to sign the file chains up to a root certificate located in the trusted root certificate store. This implies that the identity of the publisher has been verified by a certification authority.
2) The end entity certificate has sufficient permission to sign code, as indicated by the presence of a code signing EKU or no EKU (Enhanced Key Usage).
1.7.
There are 2 kinds of signing (by physical location of signature):
- Embedded signature.
You can check its presence by my function IsInternalSignPresent().
It is located in SecurityDir structure of Data_Directories of Optional_PE_Header.
More detail info available in official specification: http://download.microsoft.com/downlo...ticode_pe.docx
- Signing by external cat-file.
It's mean binary file is not modified during process of signing. Instead, file hash has been stored in one of cat-files (called 'security catalog') located in: c:\Windows\System32\CatRoot\
Many Microsoft files and some 3-rd party device drivers signed in this way.
On other machine such file may not be authenticated because its hash will not appear in the cat-file.
Let's look on such signature closer using Sysinternals SigCheck:
Code:
C:\Users\tfcor>sigcheck -i c:\windows\write.exe | more
Sigcheck v2.51 - File version and signature viewer
Copyright (C) 2004-2016 Mark Russinovich
Sysinternals - www.sysinternals.com
c:\windows\write.exe:
Verified: Signed
Link date: 4:28 16.07.2016
Signing date: 11:45 16.07.2016
Catalog: C:\WINDOWS\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\Microsoft-Windows-Client-Features-Package-AutoMerged-shell~31bf3856ad364e35~amd64~~10.0.14393.0.cat
You can see that signature is external, because catalog file was specified. Also, if you click properties of this PE EXE file, you cannot see tab 'digital signature', that mean the file has no internal signature.
Now, if you look at the properties of the same .cat file by double clicking the mouse, you'll can see the same PE256 hash (so called 'Authenticode hash') as 'write.exe' file is:
Code:
C:\Users\tfcor>sigcheck -h c:\windows\write.exe
Sigcheck v2.51 - File version and signature viewer
Copyright (C) 2004-2016 Mark Russinovich
Sysinternals - www.sysinternals.com
c:\windows\write.exe:
Verified: Signed
Signing date: 11:45 16.07.2016
Publisher: Microsoft Windows
Company: Microsoft Corporation
Description: Windows Write
Product: Microsoftю Windowsю Operating System
Prod version: 10.0.14393.0
File version: 10.0.14393.0 (rs1_release.160715-1616)
MachineType: 64-bit
MD5: E87C6A38E61A712C48025A6AD54C1113
SHA1: C21DC47D57437909F9CAC14E786C77E9F3E78E56
PESHA1: E92EBEEA9C65ACD0E114A01A1BE33ACE1CBB1374
PE256: 13658F7C5124017F3D2FCB062BC9D326639578210EAB58C7C8DF9A603E5AC463
SHA256: 7E3485F5EDD48FFCE37B0B0B735CD97F5AB514AA8DC4D6BC16CC4C40FB3FB570
IMP: 6CCC14AA5F1A410F31748D8AD9F362FD
To calculate PE hash manually you can use MapFileAndCheckSum() function.
This hash calculated on the basis of all sections of executable, excluding PE EXE hash field and sections 'Certificate table', 'Attribute certificate table'. Details available in specification: http://download.microsoft.com/downlo...ticode_pe.docx
All cat-files is digitally signed too.
Re: [VB6] Digital signature verifier (Authenticode and WHQL)
Is anybody here can help me to refresh memories about debugging in WinDbg or any?
I need to look at some values in nested structures of WinVerifyTrust call of another program to found what value cause my realization return err. in Win7 SP0.
I just forgot how to map memory address to human readable structure, so I don't need to dig in raw memory.
Re: [VB6] Digital signature verifier (Authenticode and WHQL)
Just to let you know there are lot of changes since 2017. Latest VB6 version and changelog are always here. Recently updated to handle driver signatures correctly.
Note: that, InitVerifyDigiSign() should be called first, before using any function.
If you want a ready tool with csv report, you can use embedded one in above HiJackThis+ project, just run it => menu Tools => Files => Digital Signature Checker.
Also, I made stripped version on C++, and on C#, which able to support:
- x64 and x32 applications (incl. WOW)
- internal signature check
- Microsoft security catalogue check
- SHA1 and SHA256 signature hashes (note: XP/Vista cannot check SHA256)
- OS Windows XP/Vista/7/8/8.1/10/11 x32, x64
Last edited by Dragokas; Jul 6th, 2023 at 05:55 AM.