Colección de citas famosas - Slogan de motivación - Cómo verificar si la firma digital de un archivo PE es correcta en C#

Cómo verificar si la firma digital de un archivo PE es correcta en C#

Al igual que una gran cantidad de artículos en Internet que analizan cómo crear firmas digitales y verificar firmas digitales, este artículo utiliza la propia API de Microsoft para verificar la validez de las firmas digitales de archivos PE, utilizando el lenguaje C#.

Podemos hacer clic derecho directamente para verificar la validez de la firma digital de un archivo PE en el sistema Windows, como se muestra a continuación:

Esto nos recuerda que Microsoft debe tener la suya propia. Firma digital para archivos PE El método de verificación de firma es buscar información y determinar que proviene de la función WinVerifyTrust en el archivo dll que se muestra en la siguiente figura.

El prototipo de llamada de esta función en C# es el siguiente:

C#

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

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

Para el uso de esta función, puede ver las instrucciones en MSDN.

(2) Construir la estructura de datos que se utilizará

Según los materiales oficiales de Microsoft, debemos preparar varias estructuras de datos antes de usar esta función:

usar Sistema ;

usando System.Runtime.InteropServices;

espacio de nombres VerifyDigitalSignature

{

enumación pública AllocMethod

{

HGlobal,

CoTaskMem

}

enumeración pública UnionChoice

{

Archivo = 1,

Catálogo,

Blob,

Firmante,

Cert

}

enumeración pública UiChoice

{

Todos = 1,

NoUI,

NoBad,

NoGood

}

enum público RevocationCheckFlags

{

Ninguno = 0,

WholeChain

}

Enumación pública StateAction

{

Ignorar = 0,

Verificar,

Cerrar,

AutoCache,

AutoCacheFlush

}

enumación pública TrustProviderFlags

{

UseIE4Trust = 1,

NoIE4Chain = 2,

NoPolicyUsage = 4,

RevocationCheckNone = 16,

RevocationCheckEndCert = 32,

RevocationCheckChain = 64,

RecovationCheckChainExcludeRoot = 128,

Más seguro = 256,

HashOnly = 512,

UseDefaultOSVerCheck = 1024,

LifetimeSigning = 2048

}

enumación pública UIContext

{

Ejecutar = 0,

Instalar

}

#region Clase UnmanagedPointer

clase interna sellada UnmangedPointer: IDisposable

{

IntPtr m_ptr privado;

AllocMethod m_meth privado;

Puntero no administrado interno (IntPtr ptr, método AllocMethod)

{

m_meth = método;

m_ptr

= ptr;

}

~UnmanagedPointer()

{

Dispose( false );

}

#region IDisposable Members

private void Dispose( bool disposing )

{

if ( m_ptr != IntPtr.Zero )

{

if ( m_meth == AllocMethod.HGlobal )

{

Marshal.FreeHGlobal( m_ptr );

}

si no ( m_meth == AllocMethod.CoTaskMem )

{

Marshal.FreeCoTaskMem( m_ptr );

}

m_ptr = IntPtr.Zero;

}

if (eliminar)

{

GC.SuppressFinalize (esto);

}

}

public void Dispose()

{

Dispose( verdadero );

}

#endregion

operador implícito estático público IntPtr( UnmanagedPointer ptr )

{

return ptr.m_ptr;

}

}

#endregion

estructura interna WINTRUST_FILE_INFO: IDisposable

{

público WINTRUST_FILE_INFO( nombre de archivo de cadena, asunto de Guid )

{

cbStruct = (uint)Marshal.SizeOf( tipo de( WINTRUST_FILE_INFO ) );

pcwszFilePath = fileName;

if ( asunto != Guid.Empty )

{

pgKnownSubject = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( Guid ) ) );

Marshal.StructureToPtr( sujeto, pgKnownSubject, verdadero );

}

else

{

pgKnownSubject = IntPtr.Zero;

}

hFile = IntPtr.Zero;

}

public uint cbStruct;

[MarshalAs( UnmanagedType.LPTStr )]

cadena pública pcwszFilePath;

IntPt público

r hFile;

public IntPtr pgKnownSubject;

#region IMiembros desechables

public void Dispose()

{

Dispose( true );

}

private void Dispose( bool disposing )

{

if ( pgKnownSubject != IntPtr .Zero )

{

Marshal.DestroyStructure( this.pgKnownSubject, typeof( Guid ) );

Marshal.FreeHGlobal( this.pgKnownSubject );

p>

}

}

#endregion

}

[StructLayout( LayoutKind.Sequential ) ]

estructura interna WINTRUST_DATA: IDisposable

{

WINTRUST_DATA público (WINTRUST_FILE_INFO fileInfo)

{

esto .cbStruct = (uint) Marshal.SizeOf( typeof( WINTRUST_DATA ) );

pInfoStruct = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( WINTRUST_FILE_INFO ) )

Marshal.StructureToPtr ( fileInfo, pInfoStruct, true );

this.dwUnionChoice = UnionChoice.File;

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.Execute;

}

público uint cbStruct;

público IntPtr pPolicyCallbackData;

público IntPtr pSIPCallbackData;

público UiChoice dwUIChoice;

público Bandera de verificación de revocación

s fdwRevocationChecks;

public UnionChoice dwUnionChoice;

público IntPtr pInfoStruct;

público StateAction dwStateAction;

público IntPtr hWVTStateData;

privado IntPtr pwszURLReference;

público TrustProviderFlags dwProvFlags;

público UIContext dwUIContext;

#región IDisposable Members

público vacío Dispose()

{

Dispose( true );

}

private void Dispose( bool disposing )

{

if ( dwUnionChoice == UnionChoice.File )

{

//WINTRUST_FILE_INFO info = new WINTRUST_FILE_INFO();

//Marshal.PtrToStructure(pInfoStruct, info);

//info.Dispose();

Marshal.DestroyStructure(pInfoStruct, typeof(WINTRUST_FILE_INFO));

}

Marshal.FreeHGlobal( pInfoStruct );

}

#endregion

}

}

(3) Construya nuestra clase de verificación

Shell

usando System;

usando System.Collections.Generic;

p>

usando System.Runtime.InteropServices;

usando Microsoft.Win32;

espacio de nombres VerifyDigitalSignature

{

Autenticación de clase pública

{

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

uint externo estático privado WinVerifyTrust ( IntPtr hWnd, IntPtr pgActionID, IntPtr pWinTrustData );

Listlt estático privado; GetTrustGuid()

{

//HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ Criptografía\Proveedores\ Confianza\Inicialización\

<

p>Listlt;Guidgt; trustGuids = new Listlt;Guidgt;();

RegistryKey hklm = Registry.LocalMachine;

Inicialización de RegisterKey = hklm.OpenSubKey( @"SOFTWARE\Microsoft\ Cryptography\Providers\Trust\Initialization" );

cadena[] guidNames = inicialización.GetSubKeyNames();

foreach ( cadena guidName en guidNames )

{

trustGuids.Add( new Guid( guidName )

}

return trustGuids

}

public static uint CSWinVerifyTrust( string fileName )

{

resultado de uint = 1516356;

prueba

{

Listlt; Guidgt; trustGuids = GetTrustGuid();

foreach (Guid guid en trustGuids)

{

Guid wintrust_action_generic_verify_v2 = guid;

WINTRUST_FILE_INFO fileInfo = new WINTRUST_FILE_INFO( fileName, Guid.Empty);

WINTRUST_DATA data = new WINTRUST_DATA( fileInfo);

UnmanagedPointer guidPtr = new UnmanagedPointer( Marshal.AllocHGlobal( Marshal .SizeOf( typeof( Guid ) ) ), AllocMethod.HGlobal

UnmanagedPointer wvtDataPtr = nuevo UnmanagedPointer( Marshal.AllocHGlobal( Marshal.SizeOf( typeof( WINTRUST_DATA ) ) ), AllocMethod.HGlobal ); p>

IntPtr pGuid = guidPtr;

IntPtr pData = wvtDataPtr;

Marshal.StructureToPtr(wintrust_action_generic_verify_v2, pGuid, true);

Marshal .StructureToPtr (datos, pData, verdadero);

resultado = WinVerifyTrust(IntPtr.Zero, pGuid, pData);

if (resultado == 0)

{

romper;

}

}

}

captura (excepción ex)

{

lanzar nueva excepción ("Error de verificación de firma digital", por ejemplo);

}

devolver resultado;

}

}

}

Tenga en cuenta que hay muchos valores de retorno de WinVerifyTrust. 0 significa que todos los indicadores de la firma digital. son normales Otros Discutiremos el código en la siguiente sección.