📄 signfile.cpp
字号:
//
// 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 + -