⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 signfile.cpp

📁 Digital Signature key tool
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <wincrypt.h>
#include <tchar.h>
#include <imagehlp.h>
#include "loadauth.h"

#define PROVIDER_KEY_CONTAINER		1
#define PROVIDER_CERT_FILE			2
#define PROVIDER_PFX_FILE			4
#define ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)

void DoMain(TCHAR *pCmdLine);
static void PrintHexDump(DWORD length, PBYTE buffer);
BOOL CAPISign(HANDLE hFile, LPTSTR pszProviderName, DWORD dwFlgas, BYTE **ppbSign, DWORD *pcbSign);
static void WriteDataToFile(PTSTR  pszFilename,PBYTE pbData,DWORD cbData);
BOOL AppendSignToPE(HANDLE hFile,PBYTE pbSignedData, DWORD cbSignedData,PBYTE pbSign, DWORD cbSign);

BYTE bAttrib[MAX_WIN_CERT_SIGN_DATA_LEN];
LPTSTR  pszFileName   = NULL;
LPTSTR  pszPublicKey = NULL;
LPTSTR  pszProviderName = NULL;
LPTSTR	pszPassword = NULL;
LPTSTR  pszSignFile = TEXT("DEFAULT.SIG");
LPTSTR  pbAttrib = NULL;
DWORD   cbAttrib = 0;

BOOL    fAppendToPE = FALSE;
BOOL    fDebugBreak = FALSE;

/*****************************************************************************/
void Usage(void)
{
    printf("\n");
    printf("USAGE: signfile -f<filetosign> [ <options> ]\n");
    printf("\n");
    printf("    -o<out filename>    Dump signature to file.\n");
    printf("    -k<CAPI key container> \n");
    printf("    -c<CAPI cer file> \n");
    printf("    -x<CAPI pfx file> \n");
    printf("    -w<password to decrypt pfx file> \n");
    printf("    -p<output C file to hold CAPI public key>\n");
    printf("    -s<string to sign and embed in signature>\n");
    printf("    -a                  Append signature to PE file\n");
#ifdef DEBUG    
    printf("    -b              Debug break on entry\n");
#endif
    
    printf("\n");
	
    exit(1);
}


/*****************************************************************************/
void _cdecl main()
{

    TCHAR *pCmdLine = GetCommandLine();

	// skip the program name
    while (*pCmdLine != 0 && *pCmdLine != ' ')
        pCmdLine++;
	
    while (' ' == *pCmdLine)
        pCmdLine++;
    DoMain(pCmdLine);
}


void
DoMain(TCHAR *pCmdLine)
{
    INT iOption;
    PTCHAR pszOption, pszEndOption;
    PUCHAR pbSign = NULL;
    DWORD cbSign;
    BOOL fRet;
    HANDLE hFile;
	DWORD dwFlags;
	
    //
    // Parse the command line.
    //
    
    if(*pCmdLine == 0)
    {
        Usage();
    }
	
    while(*pCmdLine) 
    {
        
        if(*pCmdLine == '/') *pCmdLine = '-';
		
        if(*pCmdLine != '-') 
        {
            _tprintf(TEXT("**** Invalid argument \"%s\"\n"), pCmdLine);
            Usage();
        }
		
        iOption = pCmdLine[1];
        pszOption = pCmdLine+2;
        while (*pCmdLine != ' ' && *pCmdLine != 0)
            pCmdLine++;
        pszEndOption = pCmdLine;
        // advance to next option
        while (*pCmdLine == ' ')
            pCmdLine++;
		
        *pszEndOption = 0;    // null terminate the option
		
        switch(iOption) 
        {
			
        case 'f':
            pszFileName = pszOption;
            break;
			
        case 'k':
            pszProviderName = pszOption;
			dwFlags = PROVIDER_KEY_CONTAINER;
            break;

		case 'c':
			pszProviderName = pszOption;
			dwFlags = PROVIDER_CERT_FILE;
			break;

		case 'x':
			pszProviderName = pszOption;
			dwFlags = PROVIDER_PFX_FILE;
			break;

		case 'w':
			pszPassword = pszOption;
			break;
            
        case 'o':
            pszSignFile = pszOption;
            break;
			
        case 'b':
            fDebugBreak = TRUE;
            break;
			
        case 's':
            lstrcpyn((PTCHAR)bAttrib,pszOption,sizeof(bAttrib)/sizeof(TCHAR));
            pbAttrib = (LPTSTR)&bAttrib[0];
            cbAttrib = (lstrlen(pbAttrib)+1)*sizeof(TCHAR);
            // needs to be zero padded to a DWORD boundary
            {
                DWORD cbPadded;
                cbPadded = (cbAttrib+3) & ~3;
                while (cbAttrib < cbPadded)
                    pbAttrib[cbAttrib++] = 0;
            }
            break;
            
        case 'a':
            fAppendToPE = TRUE;
            break;
        case 'p':
            pszPublicKey = pszOption;
            break;
        default:
            printf("**** Invalid option \"%c\"\n", iOption);
            Usage();
        }
    }
	
#ifdef DEBUG
    if (fDebugBreak)
        DebugBreak();
#endif
	
    if (!pszFileName )
    {
        Usage();
    }
    hFile = CreateFile(pszFileName, GENERIC_READ | (fAppendToPE ? GENERIC_WRITE : 0),
		0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
    if(hFile == INVALID_HANDLE_VALUE)
    {
        _tprintf(TEXT("**** Error opening file '%s'\n"), pszFileName);
        exit(1);
    }
	
    fRet = CAPISign(hFile, pszProviderName, dwFlags, &pbSign, &cbSign);
    if (fRet)
    {
#ifdef DEBUG
        _tprintf(TEXT("Signature:\n"));
        PrintHexDump(cbSign, pbSign);
#endif
        if (pszSignFile)
        {
            WriteDataToFile(pszSignFile, pbSign, cbSign);
        }
        if (fAppendToPE)
        {
            fRet = AppendSignToPE(hFile, (LPBYTE)pbAttrib, cbAttrib,  pbSign, cbSign);
            if (!fRet)
            {
                _tprintf(TEXT("*** Error appending Sign to PE file\n"));
            }
        }
    }
    else
    {
        _tprintf(TEXT("*** Error signing hash\n"));
    }
    if (pbSign)
        LocalFree(pbSign);
    CloseHandle(hFile);
	
    exit (fRet ? 0 : 1);
}

static UCHAR zerobytes[8] = {0};

BOOL
ComputeHashPE(HANDLE hFile, DIGEST_FUNCTION pDF, DIGEST_HANDLE hD)
{
    BOOL fRet = FALSE;
    HANDLE hMappedFile;
    PUCHAR pImage, pb1, pb2;
    PIMAGE_DOS_HEADER pDosHeader;
    PIMAGE_NT_HEADERS pFileHeaders;
    DWORD cbSize = GetFileSize(hFile,NULL);
    
	
    hMappedFile = CreateFileMapping(
		hFile,
		NULL,
		PAGE_READONLY ,
		0,
		0,
		NULL
		);
    if ( !hMappedFile ) {
        return FALSE;
    }
	
    pImage = (PUCHAR) MapViewOfFile(
		hMappedFile,
		FILE_MAP_READ,
		0,
		0,
		0
		);
	
    CloseHandle(hMappedFile);
    pDosHeader = (PIMAGE_DOS_HEADER) pImage;
    
    if (pDosHeader->e_magic == IMAGE_DOS_SIGNATURE) 
    {
        pFileHeaders = (PIMAGE_NT_HEADERS)(pImage + pDosHeader->e_lfanew);
		
        if (
            // If IMAGE_NT_HEADERS would extend past the end of file...
            (PBYTE)pFileHeaders + sizeof(IMAGE_NT_HEADERS) > pImage + cbSize
            ||
            // ..or if it would begin in, or before the IMAGE_DOS_HEADER...
            (PBYTE)pFileHeaders < pImage + sizeof(IMAGE_DOS_HEADER)
            ||
            pFileHeaders->Signature != IMAGE_NT_SIGNATURE )
            
        {
            // ...then e_lfanew is not as expected.
            // or this is not a PE file
            goto Exit;
        }
		
        // No optional header indicates an object or a different kind of PE file
		
        if ( pFileHeaders->FileHeader.SizeOfOptionalHeader != IMAGE_SIZEOF_NT_OPTIONAL_HEADER )
        {
            goto Exit;
        }
    }
    pb1 = pImage;
    pb2 = (PUCHAR)&pFileHeaders->OptionalHeader.CheckSum;
    (*pDF)(hD, pb1, pb2-pb1);
    pb1 = pb2+sizeof(pFileHeaders->OptionalHeader.CheckSum);
    pb2 = (PUCHAR)&pFileHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY];
    (*pDF)(hD, pb1, pb2-pb1);
    pb1 = pb2 + sizeof(IMAGE_DATA_DIRECTORY);
    if (((PIMAGE_DATA_DIRECTORY)pb2)->VirtualAddress && ((PIMAGE_DATA_DIRECTORY)pb2)->Size)
    {    
        pb2 = pImage + ((PIMAGE_DATA_DIRECTORY)pb2)->VirtualAddress;
    }
    else
    {
        pb2 = pImage + cbSize;
    }
    (*pDF)(hD, pb1, pb2-pb1);
    // done hashing the file
    // now just need to account for the fact that padding bytes are added on
    // to the file if its not a multiple of 8 bytes, before appending the signature
    if (cbSize & 7)
    {
		(*pDF)(hD, zerobytes, 8 - (cbSize & 7));
    }
    fRet =  TRUE;
    
Exit:
    UnmapViewOfFile(pImage);
    return fRet;
	
}

static BOOL WINAPI
CryptDigestFunction(DIGEST_HANDLE refdata, PBYTE pData, DWORD dwLength)
{
    return CryptHashData((HCRYPTHASH) refdata, pData, dwLength, 0);
}

/********************************************************/
BOOL DumpPublicKey(HCRYPTPROV hProv, LPTSTR pszPubKeyFile)
{
    HCRYPTKEY hKey;
    PBYTE pKeyBlob;
    LPTSTR pOutputBuf;
    int i,j;
    DWORD dwBlobLen;
    
    
    if (!CryptGetUserKey(hProv, AT_SIGNATURE, &hKey))
    {
        return FALSE;
    }
	// Export the public key
	// Determine the size of the key blob and allocate memory.
	if(!CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen)) {
		_tprintf(TEXT("Error %x computing blob length!\n"), GetLastError());
        CryptDestroyKey(hKey);
        return FALSE;
	}
	pKeyBlob = (LPBYTE)LocalAlloc(0, dwBlobLen);
	
	if(!CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, pKeyBlob, &dwBlobLen)) {
		_tprintf(TEXT("Error %x exporting blob!\n"), GetLastError());
		
		LocalFree(pKeyBlob);
		CryptDestroyKey(hKey);
		return FALSE;
	}
	pOutputBuf = (LPTSTR)LocalAlloc(0, dwBlobLen*6 + 512);
	i = sprintf(pOutputBuf,"/* This file contains the signature public key blob */\n\n");
	i += sprintf(pOutputBuf+i, "const unsigned char g_bSignPublicKeyBlob[] = {");
    for (j=0;j< (int)dwBlobLen-1;j++)
    {
		if (j%16 == 0)
			i += sprintf(pOutputBuf+i,"\n    ");
		i += sprintf(pOutputBuf+i,"0x%02x,",pKeyBlob[j]);
	}
	i += sprintf(pOutputBuf+i,"0x%02x\n};\n",pKeyBlob[j]);
	
	WriteDataToFile(pszPubKeyFile, (LPBYTE)pOutputBuf, i);
	LocalFree(pOutputBuf);
	LocalFree(pKeyBlob);
	CryptDestroyKey(hKey);
	return TRUE;
	
}

BOOL MyPFXIsPFXBlob(CRYPT_DATA_BLOB* pPFX)
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -