티스토리 뷰

개발/WIN32-MFC

[ WIN ] 코드사인 검증

-=HaeJuK=- 2024. 4. 22. 16:27
반응형
#pragma once

#include <windows.h>
#include <wintrust.h>
#include <softpub.h>
#include <wincrypt.h>
#include <iostream>
#pragma comment(lib,"wintrust")

class cVerifyCodeSign
{
    DECLARE_NO_SELF_CLASS( nxcVerifyCodeSign );

public:
    static bool IsVeirfyCodeSigned( const std::wstring& _ssFilePathName ) 
    {
        WINTRUST_FILE_INFO FileData;
        memset( &FileData, 0, sizeof( FileData ) );
        FileData.cbStruct = sizeof( WINTRUST_FILE_INFO );
        FileData.pcwszFilePath = _ssFilePathName.c_str();

        GUID WVTPolicyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2;
        WINTRUST_DATA WinTrustData;

        memset( &WinTrustData, 0, sizeof( WinTrustData ) );
        WinTrustData.cbStruct = sizeof( WinTrustData );
        WinTrustData.pPolicyCallbackData = NULL;
        WinTrustData.pSIPClientData = NULL;
        WinTrustData.dwUIChoice = WTD_UI_NONE;
        WinTrustData.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;  // 체인 전체의 폐지 상태를 검사합니다.
        WinTrustData.dwUnionChoice = WTD_CHOICE_FILE;
        WinTrustData.dwStateAction = WTD_STATEACTION_VERIFY;
        WinTrustData.hWVTStateData = NULL;
        WinTrustData.pwszURLReference = NULL;
        WinTrustData.dwProvFlags = WTD_SAFER_FLAG | WTD_USE_DEFAULT_OSVER_CHECK; // OS 버전 체크를 기본 설정으로 사용합니다.
        WinTrustData.dwUIContext = WTD_UICONTEXT_EXECUTE;
        WinTrustData.pFile = &FileData;

        LONG status = WinVerifyTrust( NULL, &WVTPolicyGUID, &WinTrustData );
        WinTrustData.dwStateAction = WTD_STATEACTION_CLOSE;

        WinVerifyTrust( NULL, &WVTPolicyGUID, &WinTrustData );

        return status == ERROR_SUCCESS;
    }

    static std::wstring GetSignerName( const std::wstring& _ssFilePathName )
    {
        HCERTSTORE hStore = NULL;
        HCRYPTMSG hMsg = NULL;
        PCCERT_CONTEXT pCertContext = NULL;
        std::wstring ssSignerNameW = L"Unknown";

        DWORD dwEncoding= 0x00, dwContentType = 0x00, dwFormatType = 0x00;
        if( !CryptQueryObject( CERT_QUERY_OBJECT_FILE, _ssFilePathName.c_str(), CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, CERT_QUERY_FORMAT_FLAG_BINARY, 0,
            &dwEncoding, &dwContentType, &dwFormatType, &hStore, &hMsg, (const void**) & pCertContext) )
        {
            return ssSignerNameW;
        }

        DWORD dwSignerInfo;
        PCMSG_SIGNER_INFO pSignerInfo;
        if( !CryptMsgGetParam( hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwSignerInfo ) ) 
        {
            CryptMsgClose( hMsg );
            CertCloseStore( hStore, 0 );
            return ssSignerNameW;
        }

        pSignerInfo = (PCMSG_SIGNER_INFO)malloc( dwSignerInfo );
        if( !CryptMsgGetParam( hMsg, CMSG_SIGNER_INFO_PARAM, 0, pSignerInfo, &dwSignerInfo ) ) 
        {
            free( pSignerInfo );
            CryptMsgClose( hMsg );
            CertCloseStore( hStore, 0 );
            return ssSignerNameW;
        }

        CERT_INFO CertInfo;
        CertInfo.Issuer = pSignerInfo->Issuer;
        CertInfo.SerialNumber = pSignerInfo->SerialNumber;
        pCertContext = CertFindCertificateInStore( hStore, X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_CERT, &CertInfo, NULL );
        if( pCertContext )
        {
            DWORD dwData;
            dwData = CertGetNameStringW( pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0 );
            wchar_t* nameBuffer = new wchar_t[dwData];
            if( CertGetNameStringW( pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, nameBuffer, dwData ) ) {
                ssSignerNameW = nameBuffer;
            }
            delete[] nameBuffer;
        }

        free( pSignerInfo );
        CryptMsgClose( hMsg );
        CertCloseStore( hStore, 0 );
        if( pCertContext ) 
        {
            CertFreeCertificateContext( pCertContext );
        }

        return ssSignerNameW;
    }
};

 

int Test() 
{
    std::wstring path = L"C:\\Path\\To\\YourSignedFile.exe";
    if( cVerifyCodeSign::IsVeirfyCodeSigned( path ) ) {
        std::wcout << L"The file is digitally signed." << std::endl;
        std::wstring signerName = cVerifyCodeSign::GetSignerName( path );
        std::wcout << L"Signer: " << signerName << std::endl;
    }
    else
    {
        std::wcout << L"The file is not digitally signed or the signature could not be verified." << std::endl;
    }
    return 0;
}​
반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함