///////////////////////////////////////////////////////////////////////////// // FILE : client.cxx // // DESCRIPTION : Crypto API interface // // AUTHOR : // // HISTORY : // // Mar 8 1996 larrys New // // dbarlow // // // // Copyright (C) 1996 Microsoft Corporation All Rights Reserved // ///////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include "des.h" #include "modes.h" // SIG in file #define SIG_RESOURCE_NAME "#666" // MAC in file #define MAC_RESOURCE_NAME "#667" static DWORD dwMACInFileVersion = 0x100; BYTE rgbDESKey[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}; // 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; } } } /* void QuickTest() { BYTE rgbTmp[DES_BLOCKLEN]; DWORD cbTmp = 0; BYTE rgbMAC[DES_BLOCKLEN] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef }; DESTable DESKeyTable; DWORD i; BYTE rgbData[] = { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20, 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x00, 0x00, 0x00, 0x00 }; memset(&DESKeyTable, 0, sizeof(DESKeyTable)); memset(rgbTmp, 0, sizeof(rgbTmp)); // init the key table deskey(&DESKeyTable, rgbDESKey); MACBytes(&DESKeyTable, rgbData, sizeof(rgbData), rgbTmp, &cbTmp, rgbMAC, TRUE); printf("MAC - "); for (i = 0; i < DES_BLOCKLEN; i++) { printf("%02X", rgbMAC[i]); } printf("\n"); } */ // 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 MACTheFileNoSig( IN LPCSTR pszImage, IN DWORD cbImage, IN DWORD dwMACVersion, IN DWORD dwCRCOffset, OUT BYTE *pbMAC ) { HMODULE hInst = 0; MEMORY_BASIC_INFORMATION MemInfo; BYTE *pbStart; BYTE rgbMAC[DES_BLOCKLEN]; BYTE rgbZeroMAC[DES_BLOCKLEN + sizeof(DWORD) * 2]; BYTE *pbPostCRC; // pointer to just after CRC DWORD cbCRCToMAC; // number of bytes from CRC to sig DWORD cbPostMAC; // size - (already hashed + signature size) BYTE *pbPostMAC; DWORD dwZeroCRC = 0; DWORD dwBytesRead = 0; OFSTRUCT ImageInfoBuf; HFILE hFile = HFILE_ERROR; HANDLE hMapping = NULL; DESTable DESKeyTable; BYTE rgbTmp[DES_BLOCKLEN]; DWORD cbTmp = 0; BYTE *pbRsrcMAC = NULL; DWORD cbRsrcMAC; 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 = 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; // create a zero byte MAC memset(rgbZeroMAC, 0, sizeof(rgbZeroMAC)); if (!GetResourcePtr(hInst, MAC_RESOURCE_NAME, &pbRsrcMAC, &cbRsrcMAC)) { printf("Couldn't find MAC placeholder\n"); goto Ret; } pbPostCRC = pbStart + dwCRCOffset + sizeof(DWORD); cbCRCToMAC = (DWORD)(pbRsrcMAC - pbPostCRC); pbPostMAC = pbRsrcMAC + (DES_BLOCKLEN + sizeof(DWORD) * 2); cbPostMAC = (cbImage - (DWORD)(pbPostMAC - pbStart)); // copy the resource MAC if (DES_BLOCKLEN != (cbRsrcMAC - (sizeof(DWORD) * 2))) { goto Ret; } // 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 MAC resource if (!MACBytesOfFile((HANDLE)IntToPtr(hFile), cbCRCToMAC, &DESKeyTable, rgbTmp, &cbTmp, rgbMAC, FALSE)) { goto Ret; } // pretend image has zeroed MAC MACBytes(&DESKeyTable, (BYTE*)rgbZeroMAC, cbRsrcMAC, rgbTmp, &cbTmp, rgbMAC, FALSE); if (!SetFilePointer((HANDLE)IntToPtr(hFile), cbRsrcMAC, NULL, FILE_CURRENT)) { goto Ret; } // MAC after the resource if (!MACBytesOfFile((HANDLE)IntToPtr(hFile), cbPostMAC, &DESKeyTable, rgbTmp, &cbTmp, rgbMAC, TRUE)) { goto Ret; } memcpy(pbMAC, rgbMAC, DES_BLOCKLEN); fRet = TRUE; Ret: if (pbRsrcMAC) FreeResource(pbRsrcMAC); if(hInst) UnmapViewOfFile(hInst); if(hMapping) CloseHandle(hMapping); if (HFILE_ERROR != hFile) _lclose(hFile); 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 = NULL; DWORD cbRsrcMAC; BYTE *pbRsrcSig = NULL; 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 = 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_NAME, &pbRsrcMAC, &cbRsrcMAC)) goto Ret; // the MAC resource if (!GetResourcePtr(hInst, SIG_RESOURCE_NAME, &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 (pbRsrcMAC) FreeResource(pbRsrcMAC); if (pbRsrcSig) FreeResource(pbRsrcSig); if(hInst) UnmapViewOfFile(hInst); if(hMapping) CloseHandle(hMapping); if (HFILE_ERROR != hFile) _lclose(hFile); 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; } // 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 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_NAME, &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 ShowHelp() { printf("CryptoAPI Internal CSP MACing Utility\n"); printf("maccsp