|
|
/////////////////////////////////////////////////////////////////////////////
// FILE : client.cxx //
// DESCRIPTION : Crypto API interface //
// AUTHOR : //
// HISTORY : //
// Mar 8 1996 larrys New //
// dbarlow //
// //
// Copyright (C) 1996 Microsoft Corporation All Rights Reserved //
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include "mainrpc.h" // header file generated by the MIDL compiler
#include <imagehlp.h>
#include "des.h"
#include "modes.h"
#include "skrpc.h"
extern "C" { #include "md5.h"
};
// designatred resource for in file signatures
#define CRYPT_SIG_RESOURCE_NUMBER "#666"
// MAC in file
#define MAC_RESOURCE_NUMBER "#667"
static DWORD dwMACInFileVersion = 0x100;
BYTE rgbDESKey[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
BOOL HashTheFile( LPCSTR pszFile, DWORD dwCRCOffset, BYTE *pbHash, DWORD *pcbHash, DWORD cbImage );
DWORD GetCRCOffset( LPCSTR szFile, DWORD cbImage, DWORD *pdwCRCOffset );
static DWORD dwSigInFileVersion = 0x100;
DWORD SetCryptSignatureResource( LPCSTR szFile, DWORD dwSigVersion, DWORD dwCRCOffset, PBYTE pbNewSig, DWORD cbNewSig, DWORD cbImage );
void ShowHelp(); BOOL DumpFile(LPCTSTR szFile, const BYTE *pb, UINT cb); void CallServer(void);
BYTE pbSignature[256]; BYTE pbDigest[80]; DWORD cbDigestLen = sizeof(pbDigest); DWORD cbSignatureLen = sizeof(pbSignature);
// The function MACs the given bytes.
void MACBytes( IN DESTable *pDESKeyTable, IN BYTE *pbData, IN DWORD cbData, IN OUT BYTE *pbTmp, IN OUT DWORD *pcbTmp, IN OUT BYTE *pbMAC, IN BOOL fFinal ) { DWORD cb = cbData; DWORD cbMACed = 0;
while (cb) { if ((cb + *pcbTmp) < DES_BLOCKLEN) { memcpy(pbTmp + *pcbTmp, pbData + cbMACed, cb); *pcbTmp += cb; break; } else { memcpy(pbTmp + *pcbTmp, pbData + cbMACed, DES_BLOCKLEN - *pcbTmp); CBC(des, DES_BLOCKLEN, pbMAC, pbTmp, pDESKeyTable, ENCRYPT, pbMAC); cbMACed = cbMACed + (DES_BLOCKLEN - *pcbTmp); cb = cb - (DES_BLOCKLEN - *pcbTmp); *pcbTmp = 0; } } }
// Given hInst, allocs and returns pointers to MAC pulled from
// resource
BOOL GetResourcePtr( IN HMODULE hInst, IN LPSTR pszRsrcName, OUT BYTE **ppbRsrcMAC, OUT DWORD *pcbRsrcMAC ) { HRSRC hRsrc; BOOL fRet = FALSE;
// Nab resource handle for our signature
if (NULL == (hRsrc = FindResourceA(hInst, pszRsrcName, RT_RCDATA))) goto Ret;
// get a pointer to the actual signature data
if (NULL == (*ppbRsrcMAC = (PBYTE)LoadResource(hInst, hRsrc))) goto Ret;
// determine the size of the resource
if (0 == (*pcbRsrcMAC = SizeofResource(hInst, hRsrc))) goto Ret;
fRet = TRUE; Ret: return fRet; }
#define CSP_TO_BE_MACED_CHUNK 4096
// Given hFile, reads the specified number of bytes (cbToBeMACed) from the file
// and MACs these bytes. The function does this in chunks.
BOOL MACBytesOfFile( IN HANDLE hFile, IN DWORD cbToBeMACed, IN DESTable *pDESKeyTable, IN BYTE *pbTmp, IN DWORD *pcbTmp, IN BYTE *pbMAC, IN BYTE fFinal ) { BYTE rgbChunk[CSP_TO_BE_MACED_CHUNK]; DWORD cbRemaining = cbToBeMACed; DWORD cbToRead; DWORD dwBytesRead; BOOL fRet = FALSE;
//
// loop over the file for the specified number of bytes
// updating the hash as we go.
//
while (cbRemaining > 0) { if (cbRemaining < CSP_TO_BE_MACED_CHUNK) cbToRead = cbRemaining; else cbToRead = CSP_TO_BE_MACED_CHUNK;
if(!ReadFile(hFile, rgbChunk, cbToRead, &dwBytesRead, NULL)) goto Ret; if (dwBytesRead != cbToRead) goto Ret;
MACBytes(pDESKeyTable, rgbChunk, dwBytesRead, pbTmp, pcbTmp, pbMAC, fFinal); cbRemaining -= cbToRead; }
fRet = TRUE; Ret: return fRet; }
BOOL MACTheFileWithSig( LPCSTR pszImage, DWORD cbImage, IN DWORD dwMACVersion, IN DWORD dwCRCOffset, OUT BYTE *pbMAC ) { HMODULE hInst = 0; MEMORY_BASIC_INFORMATION MemInfo; BYTE *pbRsrcMAC; DWORD cbRsrcMAC; BYTE *pbRsrcSig; DWORD cbRsrcSig; BYTE *pbStart; BYTE rgbMAC[DES_BLOCKLEN]; BYTE rgbZeroMAC[DES_BLOCKLEN + sizeof(DWORD) * 2]; BYTE rgbZeroSig[144]; BYTE *pbPostCRC; // pointer to just after CRC
DWORD cbCRCToRsrc1; // number of bytes from CRC to first rsrc
DWORD cbRsrc1ToRsrc2; // number of bytes from first rsrc to second
DWORD cbPostRsrc; // size - (already hashed + signature size)
BYTE *pbRsrc1ToRsrc2; BYTE *pbPostRsrc; BYTE *pbZeroRsrc1; BYTE *pbZeroRsrc2; DWORD cbZeroRsrc1; DWORD cbZeroRsrc2; DWORD dwZeroCRC = 0; DWORD dwBytesRead = 0; OFSTRUCT ImageInfoBuf; HFILE hFile = HFILE_ERROR; HANDLE hMapping = NULL; DESTable DESKeyTable; BYTE rgbTmp[DES_BLOCKLEN]; DWORD cbTmp = 0; BOOL fRet = FALSE;
memset(&MemInfo, 0, sizeof(MemInfo)); memset(rgbMAC, 0, sizeof(rgbMAC)); memset(rgbTmp, 0, sizeof(rgbTmp));
// Load the file
if (HFILE_ERROR == (hFile = OpenFile(pszImage, &ImageInfoBuf, OF_READ))) { goto Ret; }
hMapping = CreateFileMapping((HANDLE)IntToPtr(hFile), NULL, PAGE_READONLY, 0, 0, NULL); if(hMapping == NULL) { goto Ret; }
hInst = (HMODULE)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); if(hInst == NULL) { goto Ret; } pbStart = (BYTE*)hInst;
// Convert pointer to HMODULE, using the same scheme as
// LoadLibrary (windows\base\client\module.c).
*((ULONG_PTR*)&hInst) |= 0x00000001;
// the MAC resource
if (!GetResourcePtr(hInst, MAC_RESOURCE_NUMBER, &pbRsrcMAC, &cbRsrcMAC)) goto Ret;
// the MAC resource
if (!GetResourcePtr(hInst, CRYPT_SIG_RESOURCE_NUMBER, &pbRsrcSig, &cbRsrcSig)) goto Ret;
if (cbRsrcMAC < (sizeof(DWORD) * 2)) goto Ret;
// create a zero byte MAC
memset(rgbZeroMAC, 0, sizeof(rgbZeroMAC));
// create a zero byte Sig
memset(rgbZeroSig, 0, sizeof(rgbZeroSig));
// set up the pointers
pbPostCRC = pbStart + dwCRCOffset + sizeof(DWORD); if (pbRsrcSig > pbRsrcMAC) // MAC is first Rsrc
{ cbCRCToRsrc1 = (DWORD)(pbRsrcMAC - pbPostCRC); pbRsrc1ToRsrc2 = pbRsrcMAC + cbRsrcMAC; cbRsrc1ToRsrc2 = (DWORD)(pbRsrcSig - pbRsrc1ToRsrc2); pbPostRsrc = pbRsrcSig + cbRsrcSig; cbPostRsrc = (cbImage - (DWORD)(pbPostRsrc - pbStart));
// zero pointers
pbZeroRsrc1 = rgbZeroMAC; cbZeroRsrc1 = cbRsrcMAC; pbZeroRsrc2 = rgbZeroSig; cbZeroRsrc2 = cbRsrcSig; } else // Sig is first Rsrc
{ cbCRCToRsrc1 = (DWORD)(pbRsrcSig - pbPostCRC); pbRsrc1ToRsrc2 = pbRsrcSig + cbRsrcSig; cbRsrc1ToRsrc2 = (DWORD)(pbRsrcMAC - pbRsrc1ToRsrc2); pbPostRsrc = pbRsrcMAC + cbRsrcMAC; cbPostRsrc = (cbImage - (DWORD)(pbPostRsrc - pbStart));
// zero pointers
pbZeroRsrc1 = rgbZeroSig; cbZeroRsrc1 = cbRsrcSig; pbZeroRsrc2 = rgbZeroMAC; cbZeroRsrc2 = cbRsrcMAC; }
// init the key table
deskey(&DESKeyTable, rgbDESKey);
// MAC up to the CRC
if (!MACBytesOfFile((HANDLE)IntToPtr(hFile), dwCRCOffset, &DESKeyTable, rgbTmp, &cbTmp, rgbMAC, FALSE)) { goto Ret; }
// pretend CRC is zeroed
MACBytes(&DESKeyTable, (BYTE*)&dwZeroCRC, sizeof(DWORD), rgbTmp, &cbTmp, rgbMAC, FALSE); if (!SetFilePointer((HANDLE)IntToPtr(hFile), sizeof(DWORD), NULL, FILE_CURRENT)) { goto Ret; }
// MAC from CRC to first resource
if (!MACBytesOfFile((HANDLE)IntToPtr(hFile), cbCRCToRsrc1, &DESKeyTable, rgbTmp, &cbTmp, rgbMAC, FALSE)) { goto Ret; }
// pretend image has zeroed first resource
MACBytes(&DESKeyTable, (BYTE*)pbZeroRsrc1, cbZeroRsrc1, rgbTmp, &cbTmp, rgbMAC, FALSE); if (!SetFilePointer((HANDLE)IntToPtr(hFile), cbZeroRsrc1, NULL, FILE_CURRENT)) { goto Ret; }
// MAC from first resource to second
if (!MACBytesOfFile((HANDLE)IntToPtr(hFile), cbRsrc1ToRsrc2, &DESKeyTable, rgbTmp, &cbTmp, rgbMAC, FALSE)) { goto Ret; }
// pretend image has zeroed second Resource
MACBytes(&DESKeyTable, (BYTE*)pbZeroRsrc2, cbZeroRsrc2, rgbTmp, &cbTmp, rgbMAC, FALSE); if (!SetFilePointer((HANDLE)IntToPtr(hFile), cbZeroRsrc2, NULL, FILE_CURRENT)) { goto Ret; }
// MAC after the resource
if (!MACBytesOfFile((HANDLE)IntToPtr(hFile), cbPostRsrc, &DESKeyTable, rgbTmp, &cbTmp, rgbMAC, TRUE)) { goto Ret; }
memcpy(pbMAC, rgbMAC, DES_BLOCKLEN);
fRet = TRUE; Ret: if(hInst) UnmapViewOfFile(hInst); if(hMapping) CloseHandle(hMapping); if (HFILE_ERROR != hFile) _lclose(hFile);
return fRet; }
// SetCryptMACResource
//
// slams MAC resource in file with the new MAC
//
DWORD SetCryptMACResource( IN LPCSTR szFile, IN DWORD dwMACVersion, IN DWORD dwCRCOffset, IN PBYTE pbNewMAC, IN DWORD cbImage ) { DWORD dwErr = 0x1;
HANDLE hFileProv = NULL; HMODULE hInst = NULL;
PBYTE pbFilePtr = NULL; DWORD cbImageSize, cbMACOffset;
PBYTE pbMAC; DWORD cbMAC;
MEMORY_BASIC_INFORMATION MemInfo; BYTE *pbStart;
DWORD OldCheckSum; DWORD NewCheckSum; PIMAGE_NT_HEADERS pImageNTHdrs;
HANDLE hFileMap = NULL;
memset(&MemInfo, 0, sizeof(MemInfo));
// Load the file as a datafile
if (NULL == (hInst = LoadLibraryEx(szFile, NULL, LOAD_LIBRARY_AS_DATAFILE))) { printf("Couldn't load file\n"); goto Ret; } if (!GetResourcePtr(hInst, MAC_RESOURCE_NUMBER, &pbMAC, &cbMAC)) { printf("Couldn't find MAC placeholder\n"); goto Ret; }
// get image start address
VirtualQuery(hInst, &MemInfo, sizeof(MemInfo)); pbStart = (BYTE*)MemInfo.BaseAddress;
FreeLibrary(hInst); hInst = NULL;
cbMACOffset = (DWORD)(pbMAC - pbStart);
if (cbMAC != (DES_BLOCKLEN + sizeof(DWORD) * 2)) { printf("Attempt to replace %d zeros with new MAC!\n", cbMAC); goto Ret; }
if (INVALID_HANDLE_VALUE == (hFileProv = CreateFile(szFile, GENERIC_READ | GENERIC_WRITE, 0, // don't share
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0))) { printf("Couldn't CreateFile: 0x%x\n", GetLastError()); goto Ret; }
if (NULL == (hFileMap = CreateFileMapping( hFileProv, NULL, PAGE_READWRITE, 0, 0, NULL))) { printf("Couldn't map file\n"); goto Ret; }
if (NULL == (pbFilePtr = (PBYTE)MapViewOfFile( hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0))) { printf("Couldn't create view\n"); goto Ret; }
// copy version, CRC offset and new sig
CopyMemory(pbFilePtr+cbMACOffset, &dwMACVersion, sizeof(dwMACVersion)); cbMACOffset += sizeof(dwMACVersion); CopyMemory(pbFilePtr+cbMACOffset, &dwCRCOffset, sizeof(dwCRCOffset)); cbMACOffset += sizeof(dwCRCOffset); CopyMemory(pbFilePtr+cbMACOffset, pbNewMAC, DES_BLOCKLEN);
// compute a new checksum
if (NULL == (pImageNTHdrs = CheckSumMappedFile(pbFilePtr, cbImage, &OldCheckSum, &NewCheckSum))) goto Ret;
CopyMemory(&pImageNTHdrs->OptionalHeader.CheckSum, &NewCheckSum, sizeof(DWORD));
if (NULL == (pImageNTHdrs = CheckSumMappedFile(pbFilePtr, cbImage, &OldCheckSum, &NewCheckSum))) goto Ret;
if (OldCheckSum != NewCheckSum) goto Ret;
dwErr = ERROR_SUCCESS; Ret: if (pbFilePtr) UnmapViewOfFile(pbFilePtr);
if (hFileMap) CloseHandle(hFileMap);
if (hInst) FreeLibrary(hInst);
if (hFileProv) CloseHandle(hFileProv);
return dwErr; }
void MacCSP( LPCSTR pszInFile ) { DWORD cbImage; DWORD dwCRCOffset; HANDLE hFileProv = INVALID_HANDLE_VALUE; BYTE rgbMAC[DES_BLOCKLEN]; HMODULE hInst = NULL;
PBYTE pbFilePtr = NULL; DWORD cbImageSize, cbMACOffset;
PBYTE pbMAC; DWORD cbMAC;
memset(rgbMAC, 0, sizeof(rgbMAC));
// check if the MAC resource is in the CSP and exit if not
// Load the file as a datafile
if (NULL == (hInst = LoadLibraryEx(pszInFile, NULL, LOAD_LIBRARY_AS_DATAFILE))) { printf("Couldn't load file\n"); goto Ret; } if (!GetResourcePtr(hInst, MAC_RESOURCE_NUMBER, &pbMAC, &cbMAC)) { goto Ret; } FreeLibrary(hInst); hInst = NULL;
// get the file size
if ((hFileProv = CreateFile(pszInFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) == INVALID_HANDLE_VALUE) { printf("CSP specified was not found!\n"); goto Ret; }
if (0xffffffff == (cbImage = GetFileSize(hFileProv, NULL))) { printf("CSP specified was not found!\n"); goto Ret; }
CloseHandle(hFileProv); hFileProv = NULL;
if (0 != GetCRCOffset(pszInFile, cbImage, &dwCRCOffset)) { printf("Unable to get CRC!\n"); goto Ret; }
// calculate the MAC
if (!MACTheFileWithSig(pszInFile, cbImage, dwMACInFileVersion, dwCRCOffset, rgbMAC)) { printf("MAC failed!\n"); goto Ret; }
//
// Place the MAC into the resource in the file
//
if (ERROR_SUCCESS != SetCryptMACResource(pszInFile, dwMACInFileVersion, dwCRCOffset, rgbMAC, cbImage)) { printf("Unable to set the MAC into the file resource!\n"); goto Ret; } Ret: if (hInst) { FreeLibrary(hInst); }
if (INVALID_HANDLE_VALUE != hFileProv) { CloseHandle(hFileProv); }
return; }
/*++
main:
This is the main entry point of the application.
Arguments:
argc - Count of arguments argv - array of arguments
Return Value:
0 - Success 1 - Error
Author:
Doug Barlow (dbarlow) 1/25/1996
--*/ extern "C" void __cdecl main( int argc, char *argv[]) { DWORD exStatus = 1; DWORD index; LPCTSTR szBinFile = NULL; LPCTSTR szInFile = NULL; BOOL fOutput = FALSE; int status; DWORD ThreadId; HANDLE hThread;
// RPC Specific variables.
RPC_STATUS rpcStatus; unsigned char * pszUuid = NULL; char * pszProtocolSequence = "ncacn_np"; unsigned char * pszNetworkAddress = (LPBYTE)"\\\\enigma.ntdev.microsoft.com"; char * pszEndpoint = "\\pipe\\sign"; unsigned char * pszOptions = NULL; unsigned char * pszStringBinding = NULL; DWORD dwrt; DWORD i; DWORD cbImage; DWORD dwCRCOffset; HANDLE hFileProv = 0;
//
// Parse the command line.
//
if ((argc != 2) || (argv[1][0] == '?')) { ShowHelp(); exStatus = 0; goto ErrorExit; }
szInFile = &argv[1][0];
//
// Command consistency checks.
//
if (NULL == szInFile) { printf("No input file specified.\n"); goto ErrorExit; }
MacCSP(szInFile);
// get the file size
if ((hFileProv = CreateFile(szInFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) == INVALID_HANDLE_VALUE) { printf("CSP specified was not found!\n"); goto ErrorExit; }
if (0xffffffff == (cbImage = GetFileSize(hFileProv, NULL))) { printf("CSP specified was not found!\n"); goto ErrorExit; }
CloseHandle(hFileProv); hFileProv = NULL;
if (ERROR_SUCCESS != GetCRCOffset(szInFile, cbImage, &dwCRCOffset)) { printf("Unable to get the CRC offset on the file!\n"); goto ErrorExit; }
//
// Compute the hash.
//
if (!HashTheFile(szInFile, dwCRCOffset, pbDigest, &cbDigestLen, cbImage)) { printf("Unable to hash the file!\n"); goto ErrorExit; }
//
// Get the signature.
//
// Try to make rpc connection
rpcStatus = RpcStringBindingCompose(pszUuid, (unsigned char *) pszProtocolSequence, pszNetworkAddress, (unsigned char *) pszEndpoint, pszOptions, &pszStringBinding);
#ifdef DEBUG
printf("RpcStringBindingCompose returned 0x%x\n", rpcStatus); printf("pszStringBinding = %s\n", pszStringBinding); #endif
if (0 != rpcStatus) { printf("Failed to compose binding string for target RPC server.\n"); goto ErrorExit; }
/* Set the binding handle that will */ /* be used to bind to the server */ rpcStatus = RpcBindingFromStringBinding(pszStringBinding, &hello_IfHandle);
#ifdef DEBUG
printf("RpcBindingFromStringBinding returned 0x%x\n", rpcStatus); #endif
if (0 != rpcStatus) { printf("Failed to bind to target RPC server.\n"); goto ErrorExit; }
if ((hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) CallServer, NULL, 0, &ThreadId)) == NULL) { printf("Call to CreateThread failed\n"); goto ErrorExit; }
printf("Sending request to be signed, will wait 5 minutes\n"); for (i = 0; i < 20; i++) { printf("Waited %d seconds\n", i*30); dwrt = WaitForSingleObject(hThread, 15000); if (dwrt == WAIT_OBJECT_0) { break; } }
if (i == 20) { printf("Call to Server timed out\n"); goto ErrorExit; }
GetExitCodeThread(hThread, &dwrt);
if (dwrt) { goto ErrorExit; }
//
// Place the signature into the resource in the file
//
if (ERROR_SUCCESS != SetCryptSignatureResource(szInFile, dwSigInFileVersion, dwCRCOffset, pbSignature, cbSignatureLen, cbImage)) { printf("Unable to set the signature into the file resource!\n"); goto ErrorExit; }
//
// Clean up and return.
//
exStatus = 0;
ErrorExit: exit(exStatus);
}
void CallServer(void) { RpcTryExcept { cbSignatureLen = sizeof(pbSignature); if (GenSignature(pbDigest, &cbSignatureLen, pbSignature)) { printf("GenSignature returned an error \n"); ExitThread(TRUE); } } RpcExcept(1) { printf("RPC error -- exception code is 0x%X\n", RpcExceptionCode()); ExitThread(RpcExceptionCode()); } RpcEndExcept
ExitThread(FALSE);
}
// Given hInst, allocs and returns pointers to signature pulled from
// resource
BOOL GetCryptSigResourcePtr( HMODULE hInst, BYTE **ppbRsrcSig, DWORD *pcbRsrcSig ) { HRSRC hRsrc; BOOL fRet = FALSE;
// Nab resource handle for our signature
if (NULL == (hRsrc = FindResource(hInst, CRYPT_SIG_RESOURCE_NUMBER, RT_RCDATA))) goto Ret;
// get a pointer to the actual signature data
if (NULL == (*ppbRsrcSig = (PBYTE)LoadResource(hInst, hRsrc))) goto Ret;
// determine the size of the resource
if (0 == (*pcbRsrcSig = SizeofResource(hInst, hRsrc))) goto Ret;
fRet = TRUE; Ret: return fRet; }
// Given hInst, hashes over the file skipping, hashing zero bytes where the
// resource is
BOOL HashTheFile( LPCSTR pszFile, DWORD dwCRCOffset, BYTE *pbHash, DWORD *pcbHash, DWORD cbImage ) { MEMORY_BASIC_INFORMATION MemInfo; BYTE *pbRsrcSig; DWORD cbRsrcSig; BYTE *pbStart; BYTE *pbZeroSig = NULL; MD5_CTX MD5Hash; DWORD dwZeroCRC = 0; DWORD cbPreCRC; // start of CRC
DWORD cbCRCToSig; // end of CRC to start of sig
BYTE *pbPostCRC; // just after CRC
DWORD cbPostSig; // size - (already hashed + signature size)
BYTE *pbPostSig; HMODULE hInst = 0; BOOL fRet = FALSE;
memset(&MD5Hash, 0, sizeof(MD5Hash)); memset(&MemInfo, 0, sizeof(MemInfo));
// Load the file as a datafile
if (NULL == (hInst = LoadLibraryEx(pszFile, NULL, LOAD_LIBRARY_AS_DATAFILE))) goto Ret;
// get image start address
VirtualQuery(hInst, &MemInfo, sizeof(MemInfo)); pbStart = (BYTE*)MemInfo.BaseAddress;
// the resources signature
if (!GetCryptSigResourcePtr(hInst, &pbRsrcSig, &cbRsrcSig)) goto Ret;
// create a zero byte signature
if (NULL == (pbZeroSig = (BYTE*)LocalAlloc(LMEM_ZEROINIT, cbRsrcSig))) goto Ret;
// want to hash the version and the CRC offset
CopyMemory(pbZeroSig, &dwSigInFileVersion, sizeof(dwSigInFileVersion)); CopyMemory(pbZeroSig + sizeof(dwSigInFileVersion), &dwCRCOffset, sizeof(dwCRCOffset));
// hash over the relevant data
{ pbPostCRC = pbStart + dwCRCOffset + sizeof(dwZeroCRC); cbCRCToSig = (DWORD)(pbRsrcSig - pbPostCRC); pbPostSig = pbRsrcSig + cbRsrcSig; cbPostSig = (cbImage - (DWORD)(pbPostSig - pbStart));
MD5Init(&MD5Hash);
MD5Update(&MD5Hash, pbStart, dwCRCOffset);
// pretend CRC is zeroed
MD5Update(&MD5Hash, (BYTE*)&dwZeroCRC, sizeof(dwZeroCRC));
// pretend image has zeroed sig
MD5Update(&MD5Hash, pbPostCRC, cbCRCToSig);
// pretend image has zeroed sig
MD5Update(&MD5Hash, pbZeroSig, cbRsrcSig);
MD5Update(&MD5Hash, pbPostSig, cbPostSig);
// Finish the hash
MD5Final(&MD5Hash);
*pcbHash = MD5DIGESTLEN; memcpy(pbHash, MD5Hash.digest, MD5DIGESTLEN); }
fRet = TRUE; Ret: if (hInst) FreeLibrary(hInst); if (pbZeroSig) LocalFree(pbZeroSig); return fRet; }
DWORD GetCRCOffset( LPCSTR szFile, DWORD cbImage, DWORD *pdwCRCOffset ) { DWORD dwErr = 0x1;
HANDLE hFileProv = NULL; PBYTE pbFilePtr = NULL; DWORD OldCheckSum; DWORD NewCheckSum; PIMAGE_NT_HEADERS pImageNTHdrs;
HANDLE hFileMap = NULL;
if (INVALID_HANDLE_VALUE == (hFileProv = CreateFile(szFile, GENERIC_READ | GENERIC_WRITE, 0, // don't share
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0))) { printf("Couldn't CreateFile: 0x%x\n", GetLastError()); goto Ret; }
if (NULL == (hFileMap = CreateFileMapping( hFileProv, NULL, PAGE_READWRITE, 0, 0, NULL))) { printf("Couldn't map file\n"); goto Ret; }
if (NULL == (pbFilePtr = (PBYTE)MapViewOfFile( hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0))) { printf("Couldn't create view\n"); goto Ret; }
// compute a new checksum
if (NULL == (pImageNTHdrs = CheckSumMappedFile(pbFilePtr, cbImage, &OldCheckSum, &NewCheckSum))) goto Ret;
*pdwCRCOffset = (DWORD)((BYTE*)&pImageNTHdrs->OptionalHeader.CheckSum - pbFilePtr); dwErr = ERROR_SUCCESS; Ret: if (pbFilePtr) UnmapViewOfFile(pbFilePtr);
if (hFileMap) CloseHandle(hFileMap);
if (hFileProv) CloseHandle(hFileProv);
return dwErr; }
// SetCryptSignatureResource
//
// slams signature resource in file with the new signature
//
// szFile is file to modify
// pbNewSig is new signature
// cbNewSig is new signature length
DWORD SetCryptSignatureResource( LPCSTR szFile, DWORD dwSigVersion, DWORD dwCRCOffset, PBYTE pbNewSig, DWORD cbNewSig, DWORD cbImage ) { DWORD dwErr = 0x1;
HANDLE hFileProv = NULL; HMODULE hInst = NULL;
PBYTE pbFilePtr = NULL; DWORD cbImageSize, cbSigOffset;
PBYTE pbSig; DWORD cbSig;
MEMORY_BASIC_INFORMATION MemInfo; BYTE *pbStart;
DWORD OldCheckSum; DWORD NewCheckSum; PIMAGE_NT_HEADERS pImageNTHdrs;
HANDLE hFileMap = NULL;
memset(&MemInfo, 0, sizeof(MemInfo));
// Load the file as a datafile
if (NULL == (hInst = LoadLibraryEx(szFile, NULL, LOAD_LIBRARY_AS_DATAFILE))) { printf("Couldn't load file\n"); goto Ret; } if (!GetCryptSigResourcePtr(hInst, &pbSig, &cbSig)) { printf("Couldn't find signature placeholder\n"); goto Ret; }
// get image start address
VirtualQuery(hInst, &MemInfo, sizeof(MemInfo)); pbStart = (BYTE*)MemInfo.BaseAddress;
FreeLibrary(hInst); hInst = NULL;
cbSigOffset = (DWORD)(pbSig - pbStart);
if (cbSig < (cbNewSig + (sizeof(DWORD) * 2))) { printf("Attempt to replace %d zeros with %d byte signature!\n", cbSig, cbNewSig); goto Ret; }
if (INVALID_HANDLE_VALUE == (hFileProv = CreateFile(szFile, GENERIC_READ | GENERIC_WRITE, 0, // don't share
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0))) { printf("Couldn't CreateFile: 0x%x\n", GetLastError()); goto Ret; }
if (NULL == (hFileMap = CreateFileMapping( hFileProv, NULL, PAGE_READWRITE, 0, 0, NULL))) { printf("Couldn't map file\n"); goto Ret; }
if (NULL == (pbFilePtr = (PBYTE)MapViewOfFile( hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0))) { printf("Couldn't create view\n"); goto Ret; }
// copy version, CRC offset and new sig
CopyMemory(pbFilePtr+cbSigOffset, &dwSigVersion, sizeof(dwSigVersion)); cbSigOffset += sizeof(dwSigVersion); CopyMemory(pbFilePtr+cbSigOffset, &dwCRCOffset, sizeof(dwCRCOffset)); cbSigOffset += sizeof(dwCRCOffset); CopyMemory(pbFilePtr+cbSigOffset, pbNewSig, cbNewSig); if (cbSig > (cbNewSig + (sizeof(DWORD) * 2))) { ZeroMemory(pbFilePtr+cbSigOffset+cbNewSig, cbSig - (cbNewSig + (sizeof(DWORD) * 2))); }
// compute a new checksum
if (NULL == (pImageNTHdrs = CheckSumMappedFile(pbFilePtr, cbImage, &OldCheckSum, &NewCheckSum))) goto Ret;
CopyMemory(&pImageNTHdrs->OptionalHeader.CheckSum, &NewCheckSum, sizeof(DWORD));
if (NULL == (pImageNTHdrs = CheckSumMappedFile(pbFilePtr, cbImage, &OldCheckSum, &NewCheckSum))) goto Ret;
if (OldCheckSum != NewCheckSum) goto Ret;
dwErr = ERROR_SUCCESS; Ret: if (pbFilePtr) UnmapViewOfFile(pbFilePtr);
if (hFileMap) CloseHandle(hFileMap);
if (hInst) FreeLibrary(hInst);
if (hFileProv) CloseHandle(hFileProv);
return dwErr; }
/*++
ShowHelp:
This routine displays a short help message to the given output stream.
Arguments:
ostr - The output stream to receive the help message.
Return Value:
None
Author:
Doug Barlow (dbarlow) 7/21/1995
--*/
void ShowHelp() { printf("CryptoAPI Internal CSP Signing Utility\n"); printf("signcsp <filename>\n"); }
/* MIDL allocate and free */
void __RPC_FAR * __RPC_API midl_user_allocate(size_t len) { return(malloc(len)); }
void __RPC_API midl_user_free(void __RPC_FAR * ptr) { free(ptr); }
|