Current location - Quotes Website - Signature design - How does C# verify whether the digital signature of PE file is correct?
How does C# verify whether the digital signature of PE file is correct?
Similar to a lot of articles on the Internet discussing how to make and verify digital signatures, this paper uses Microsoft's own API to verify the validity of digital signatures of PE files, and the language used is C#.

We can directly right-click to check the validity of the digital signature of PE file under windows system, as shown in the following figure:

This reminds us that Microsoft must have its own verification method for the digital signature of PE files. After searching for information, make sure it comes from the WinVerifyTrust function in the dll file shown below.

The calling prototype of this function in C# is as follows:

C#

[DllImport("wintrust.dll ",PreserveSig = true,SetLastError = false)]

private static extern uint WinVerifyTrust(IntPtr hWnd,IntPtr pgActionID,IntPtr pWinTrustData);

About the use of this function, you can see the explanation on MSDN.

(2) Establish the data structure to be used.

According to Microsoft official data, before using this function, we should prepare several data structures:

Use the system;

Use the system. Runtime . InteropServices

Namespace verification digital signature

{

Public enumeration allocm method

{

H global,

CoTaskMem

}

Public enumeration UnionChoice

{

File = 1,

Directory,

Spots,

Signed by:

A sure thing

}

Public enumeration UiChoice

{

All = 1,

Nou,

Nobad,

It doesn't taste good

}

Public enumeration RevocationCheckFlags

{

None = 0,

The whole chain

}

Common enumeration status operation

{

Ignore = 0,

Verification,

Close,

Automatic caching,

Automatic cache refresh

}

Public enumeration TrustProviderFlags

{

UseIE4Trust = 1,

NoIE4Chain = 2,

NoPolicyUsage = 4,

RevocationCheckNone = 16,

RevocationCheckEndCert = 32,

RevocationCheckChain = 64,

RecovationCheckChainExcludeRoot = 128,

Safer = 256,

HashOnly = 5 12,

UseDefaultOSVerCheck = 1024,

Life cycle logo = 2048

}

Public enumeration UIContext

{

Execution = 0,

fix

}

# Area does not manage pointer classes.

Internal sealing class UnmanagedPointer: IDisposable

{

private IntPtr m _ ptr

Private AllocMethod m _ meth

Internal UnmanagedPointer( IntPtr ptr, AllocMethod)

{

M_meth = method;

m _ ptr = ptr

}

~UnmanagedPointer()

{

Dispose (false);

}

# zone IDisposable member

Private invalid disposal (Boolean disposal)

{

if ( m_ptr! = IntPtr。 Zero)

{

if ( m_meth == AllocMethod。 HGlobal)

{

Bailiff. freeh global(m _ ptr);

}

else if ( m_meth == AllocMethod。 CoTaskMem)

{

Bailiff. FreeCoTaskMem(m _ ptr);

}

m_ptr = IntPtr。 Zero;

}

If (processing)

{

GC。 suppress finalize(this);

}

}

Public void Dispose ()

{

Dispose (true);

}

# End area

Public static implicit operator IntPtr( UnmanagedPointer ptr)

{

Returns ptr.m _ ptr

}

}

# End area

Internal structure WINTRUST_FILE_INFO: IDisposable

{

Public WINTRUST_FILE_INFO (string file name, Guid subject)

{

cbStruct = (uint)Marshal。 SizeOf(type of(WINTRUST _ FILE _ INFO));

pcwszFilePath = fileName

If (theme! = Guid。 Empty)

{

pgKnownSubject = Marshal。 AllocHGlobal (marshaled. SizeOf(type of(Guid)));

Bailiff. StructureToPtr( subject,pgKnownSubject,true);

}

other

{

pgKnownSubject = IntPtr。 Zero;

}

hFile = IntPtr。 Zero;

}

Public unit structure;

[MarshalAs( UnmanagedType。 LPTStr )]

Public string pcwszFilePath

Public IntPtr hFile

public IntPtr pgKnownSubject

# Region id Disposable Member

Public void Dispose ()

{

Dispose (true);

}

Private invalid disposal (Boolean disposal)

{

if(pgknownssubject! = IntPtr。 Zero)

{

Bailiff. destroy structure(this . pgknownsubject,type of(Guid));

Bailiff. freeh global(this . pgknownsubject);

}

}

# End area

}

[StructLayout( LayoutKind。 Continuous)]

Internal structure WINTRUST_DATA: IDisposable

{

Public wintrust _ data (wintrust _ file _ infofileinfo)

{

this.cbStruct = (uint)Marshal。 SizeOf(type of(WINTRUST _ DATA));

pInfoStruct = Marshal。 AllocHGlobal (marshaled. SizeOf(type of(WINTRUST _ FILE _ INFO)));

Bailiff. StructureToPtr( fileInfo,pInfoStruct,true);

this.dwUnionChoice = UnionChoice。 Documents;

pPolicyCallbackData = IntPtr。 Zero;

pSIPCallbackData = IntPtr。 Zero;

dwUIChoice = UiChoice。 NoUI

fdwRevocationChecks = RevocationCheckFlags。 None;

dwStateAction = StateAction。 Ignore;

hWVTStateData = IntPtr。 Zero;

pwszURLReference = IntPtr。 Zero;

dwProvFlags = TrustProviderFlags。 Safer;

dwUIContext = UIContext。 Execution;

}

Public unit structure;

public IntPtr pPolicyCallbackData;

public IntPtr pSIPCallbackData

Public UiChoice dwUIChoice

public RevocationCheckFlags fdwRevocationChecks;

Public UnionChoice dwUnionChoice

public IntPtr pInfoStruct

Public StateAction dwStateAction

public IntPtr hWVTStateData

private IntPtr pwszURLReference

public TrustProviderFlags dwProvFlags;

Public UIContext dwUIContext

# Region id Disposable Member

Public void Dispose ()

{

Dispose (true);

}

Private invalid disposal (Boolean disposal)

{

if ( dwUnionChoice == UnionChoice。 File)

{

//WINTRUST _ FILE _ INFO INFO = new WINTRUST _ FILE _ INFO();

//sealed. PtrToStructure(pInfoStruct,info);

//info。 dispose();

Bailiff. DestroyStructure( pInfoStruct,type of(WINTRUST _ FILE _ INFO));

}

Bailiff. freeh global(pInfoStruct);

}

# End area

}

}

(3) Build our verification class

shell

Use the system;

Use the system. Assemble. Generics;

Use the system. Runtime . InteropServices

Use Microsoft. Win32

Namespace verification digital signature

{

Public class authentication

{

[DllImport( "wintrust.dll ",PreserveSig = true,SetLastError = false )]

private static extern uint WinVerifyTrust(IntPtr hWnd,IntPtr pgActionID,IntPtr pWinTrustData);

Private static list & ltGuid & gtGetTrustGuid ()

{

//HKEY _ LOCAL _ MACHINE \ SOFTWARE \ Microsoft \ Cryptography \ Providers \ Trust \ initial ization \

List & ltGuid & gttrustGuids = new list & ltGuid & gt ();

RegistryKey hklm = registry. Local machine;

RegistryKey initialization = hklm. open subkey(@ " SOFTWARE \ Microsoft \ Cryptography \ Providers \ Trust \ initial ization));

String[] guidNames = initialization. GetSubKeyNames();

Foreach (string guidName in guidnames)

{

trustGuids。 Add (new guid (guid name));

}

Return to trustGuids

}

Public static uint CSWinVerifyTrust (string file name)

{

Uint result =1516356;

attempt

{

List & lt guid & gt trustguides = gettrustguid ();

Foreach (Guid guid is in trustGuids)

{

guid wintrust _ action _ generic _ verify _ v2 = guid;

Wintrust _ file _ info fileinfo = newwintrust _ file _ info (file name, Guid. Empty);

WINTRUST _ DATA DATA = new WINTRUST _ DATA(fileInfo);

UnmanagedPointer guidPtr = new UnmanagedPointer( Marshal. AllocHGlobal (marshaled. SizeOf( typeof( Guid))、AllocMethod。 h global);

UnmanagedPointer wvtDataPtr = new UnmanagedPointer( Marshal. AllocHGlobal (marshaled. SizeOf( typeof( WINTRUST_DATA))、AllocMethod。 h global);

IntPtr pGuid = guidPtr

IntPtr pData = wvtDataPtr

Bailiff. structure toptr(wintrust _ action _ generic _ verify _ v2,pGuid,true);

Bailiff. StructureToPtr( data,pData,true);

result = WinVerifyTrust( IntPtr。 Zero,pGuid,pData);

If (result == 0)

{

Break;

}

}

}

Catch (exception ex)

{

Throws a new exception ("VerifyDigitalSignature error." ,ex);

}

Return the result;

}

}

}

Note that there are many return values of WinVerifyTrust, where 0 indicates that all indicators of digital signature are normal. We will discuss other codes in the next section.