/** * Converts a file path into a unique registry location for cert storage * * @param filePath The input file path to get a registry path from * @param registryPath A buffer to write the registry path to, must * be of size in WCHARs MAX_PATH + 1 * @return TRUE if successful */ BOOL CalculateRegistryPathFromFilePath(const LPCWSTR filePath, LPWSTR registryPath) { size_t filePathLen = wcslen(filePath); if (!filePathLen) { return FALSE; } // If the file path ends in a slash, ignore that character if (filePath[filePathLen -1] == L'\\' || filePath[filePathLen - 1] == L'/') { filePathLen--; } // Copy in the full path into our own buffer. // Copying in the extra slash is OK because we calculate the hash // based on the filePathLen which excludes the slash. // +2 to account for the possibly trailing slash and the null terminator. WCHAR *lowercasePath = new WCHAR[filePathLen + 2]; memset(lowercasePath, 0, (filePathLen + 2) * sizeof(WCHAR)); wcsncpy(lowercasePath, filePath, filePathLen + 1); _wcslwr(lowercasePath); BYTE *hash; DWORD hashSize = 0; if (!CalculateMD5(reinterpret_cast<const char*>(lowercasePath), filePathLen * 2, &hash, hashSize)) { delete[] lowercasePath; return FALSE; } delete[] lowercasePath; LPCWSTR baseRegPath = L"SOFTWARE\\Mozilla\\" L"MaintenanceService\\"; wcsncpy(registryPath, baseRegPath, MAX_PATH); BinaryDataToHexString(hash, hashSize, registryPath + wcslen(baseRegPath)); delete[] hash; return TRUE; }
bool C3DODisk::FillSignatures(FILE *Handle) { // Calculate the start and end skip sectors. int iStartSkip = (m_iSignatureStart)& 0xFFFFFFF0; int iEndSkip = (m_iSignatureStart)+(s_iSignatureSize / 2048); if ((iEndSkip & 0xF) != 0) { iEndSkip &= 0xFFFFFFF0; iEndSkip += 0x10; } // Seek to the start of the cdrom fseek(Handle, 0, SEEK_SET); BYTE *pSignatures = m_pSignatures; int iSignatures = m_iSectorCount; for (int iLoop = 0; iLoop < iSignatures * 2048; iLoop += 16 * 2048) { BYTE Buffer[16 * 2048]; fread(Buffer, 2048, 16, Handle); int iSector = iLoop / 2048; // Do not calculate MD5 for the disk label, sector 0xE0(?), or the signature sectors. // 0x80E0 is sometimes ignored if (0 == iSector || 0xE0 == iSector || 0x80F0 == iSector || (iSector >= iStartSkip && iSector < iEndSkip)) { memset(pSignatures, 0, 16); } else { CalculateMD5(Buffer, 16 * 2048, pSignatures); } pSignatures += 16; } // Clear out the sector after the signatures memset(pSignatures, 0, 2048); // Advance to the RSA area. pSignatures += 2048 - 64; // Calculate MD5 on the signatures BYTE uSignatureMD5[16]; CalculateMD5(m_pSignatures, m_iSignatureSize - 64, uSignatureMD5); // Convert MD5 to a string char szSignatureMD5[64]; szSignatureMD5[0] = 0; for (int iLoop = 0; iLoop < sizeof(uSignatureMD5); ++iLoop) { char szHexDigits[4]; sprintf(szHexDigits, "%02X", uSignatureMD5[iLoop]); strcat(szSignatureMD5, szHexDigits); } printf("Signatures MD5 value is %s\n\n", szSignatureMD5); // Calcute RSA on the MD5. CalculateRSA(szSignatureMD5, pSignatures); printf("Signatures RDS value is "); for (int iLoop = 0; iLoop < 64; ++iLoop) { printf("%02X", pSignatures[iLoop]); } printf("\n\n"); return true; }
bool C3DODisk::UpdateBannerChecksum(FILE *Handle) { printf("Calculating the banner checksum...\n\n"); int iBannerSize = -1; int iBannerOffset = -1; int iRomTagsSize = (int)m_vRomTags.size(); // Find banner screen for (int iLoop = 0; iLoop < iRomTagsSize; ++iLoop) { if (0x14 == m_vRomTags[iLoop].TagType) { iBannerSize = m_vRomTags[iLoop].Length; iBannerOffset = m_vRomTags[iLoop].Offset * 2048; break; } } if (-1 == iBannerSize) { printf("Unable to find a banner screen rom tag entry\n"); return false; } BYTE *pBannerBuffer = new BYTE[iBannerSize - 64]; if (NULL == pBannerBuffer) { printf("Unable to allocate memory for the banner screen\n"); return false; } fseek(Handle, iBannerOffset, SEEK_SET); fread(pBannerBuffer, 1, iBannerSize - 64, Handle); BYTE uBannerMD5[16]; CalculateMD5(pBannerBuffer, iBannerSize - 64, uBannerMD5); // Banner MD5 value char szBannerMD5[64]; szBannerMD5[0] = 0; for (int iLoop = 0; iLoop < sizeof(uBannerMD5); ++iLoop) { char szHexDigits[4]; sprintf(szHexDigits, "%02X", uBannerMD5[iLoop]); strcat(szBannerMD5, szHexDigits); } printf("Banner MD5 value is %s\n\n", szBannerMD5); // Banner RSA value BYTE uBannerRSA[64]; CalculateRSA(szBannerMD5, uBannerRSA); printf("Banner RDS value is "); for (int iLoop = 0; iLoop < sizeof(uBannerRSA); ++iLoop) { printf("%02X", uBannerRSA[iLoop]); } printf("\n\n"); delete[] pBannerBuffer; printf("Writing the banner checksum...\n\n"); fseek(Handle, iBannerOffset + iBannerSize - 64, SEEK_SET); fwrite(uBannerRSA, 1, 64, Handle); return true; }
bool C3DODisk::CalculateBootChecksum(FILE *Handle) { int iRomTagsSize = (int)m_vRomTags.size(); int iDataSize = s_iDiskLabelSize; printf("\nCollecting data for boot checksum...\n\n"); // Add in the size of the rom tags iDataSize += iRomTagsSize * s_iRomTagSize; // Add in the size of the boot code iDataSize += m_iBootCodeSize; BYTE *pBootCode = new BYTE[iDataSize]; if (NULL == pBootCode) { printf("Unable to allocated enough memory for the boot checksum files\n"); return false; } int iReadOffset = 0; // Read the disk label fseek(Handle, 0, SEEK_SET); fread(&pBootCode[iReadOffset], s_iDiskLabelSize, 1, Handle); iReadOffset += s_iDiskLabelSize; // Read the rom tags fseek(Handle, s_iRomTagOffset, SEEK_SET); fread(&pBootCode[iReadOffset], iRomTagsSize * s_iRomTagSize, 1, Handle); iReadOffset += iRomTagsSize * s_iRomTagSize; // Read boot code fseek(Handle, m_iBootCodeStart * 2048, SEEK_SET); fread(&pBootCode[iReadOffset], m_iBootCodeSize, 1, Handle); iReadOffset += m_iBootCodeSize; assert(iReadOffset == iDataSize); BYTE uBootMD5[16]; CalculateMD5(pBootCode, iDataSize, uBootMD5); // Boot MD5 value char szBootMD5[64]; szBootMD5[0] = 0; for (int iLoop = 0; iLoop < sizeof(uBootMD5); ++iLoop) { char szHexDigits[4]; sprintf(szHexDigits, "%02X", uBootMD5[iLoop]); strcat(szBootMD5, szHexDigits); } printf("Boot MD5 value is %s\n\n", szBootMD5); CalculateRSA(szBootMD5, m_uBootRSA); printf("Boot RDS value is "); for (int iLoop = 0; iLoop < sizeof(m_uBootRSA); ++iLoop) { printf("%02X", m_uBootRSA[iLoop]); } printf("\n\n"); delete[] pBootCode; return true; }
bool C3DODisk::CalculateMiscCodeChecksum(FILE *Handle) { int iRomTagsSize = (int)m_vRomTags.size(); printf("\nCalculating misc_code checksum...\n\n"); int iMiscCodeSize = -1; int iMiscCodeOffset; // Find misc_code for (int iLoop = 0; iLoop < iRomTagsSize; ++iLoop) { if (0x10 == m_vRomTags[iLoop].TagType) { iMiscCodeSize = m_vRomTags[iLoop].Length; iMiscCodeOffset = m_vRomTags[iLoop].Offset * 2048; break; } } if (-1 == iMiscCodeSize) { printf("Unable to find a misc_code rom tag entry\n"); return false; } BYTE *pMiscCode = new BYTE[iMiscCodeSize]; if (NULL == pMiscCode) { printf("Unable to allocated enough memory for the misc_code files\n"); return false; } // Read misc_code fseek(Handle, iMiscCodeOffset, SEEK_SET); fread(pMiscCode, iMiscCodeSize, 1, Handle); BYTE uMiscMD5[16]; CalculateMD5(pMiscCode, iMiscCodeSize - 64, uMiscMD5); // Misc MD5 value char szMiscMD5[64]; szMiscMD5[0] = 0; for (int iLoop = 0; iLoop < sizeof(uMiscMD5); ++iLoop) { char szHexDigits[4]; sprintf(szHexDigits, "%02X", uMiscMD5[iLoop]); strcat(szMiscMD5, szHexDigits); } printf("misc_code MD5 value is %s\n\n", szMiscMD5); BYTE uMiscRSA[64]; CalculateRSA(szMiscMD5, uMiscRSA, true); printf("misc_code RDS value is "); for (int iLoop = 0; iLoop < sizeof(uMiscRSA); ++iLoop) { printf("%02X", uMiscRSA[iLoop]); } printf("\n\n"); delete[] pMiscCode; printf("Writing misc_code checksum...\n\n"); fseek(Handle, iMiscCodeOffset + iMiscCodeSize - 64, SEEK_SET); fwrite(uMiscRSA, 1, 64, Handle); return true; }
bool C3DODisk::CalculateBootCodeChecksum(FILE *Handle) { int iRomTagsSize = (int)m_vRomTags.size(); printf("\nCalculating boot_code checksum...\n\n"); m_iBootCodeSize = -1; // Find boot_code for (int iLoop = 0; iLoop < iRomTagsSize; ++iLoop) { if (0x0D == m_vRomTags[iLoop].TagType) { m_iBootCodeStart = m_vRomTags[iLoop].Offset; m_iBootCodeSize = m_vRomTags[iLoop].Length; break; } } if (-1 == m_iBootCodeSize) { printf("Unable to find a boot_code rom tag entry\n"); return false; } BYTE *pBootCode = new BYTE[m_iBootCodeSize]; if (NULL == pBootCode) { printf("Unable to allocated enough memory for the boot_code files\n"); return false; } // Read boot_code fseek(Handle, m_iBootCodeStart * 2048, SEEK_SET); fread(pBootCode, m_iBootCodeSize, 1, Handle); BYTE uBootMD5[16]; CalculateMD5(pBootCode, m_iBootCodeSize - 64, uBootMD5); // Boot MD5 value char szBootMD5[64]; szBootMD5[0] = 0; for (int iLoop = 0; iLoop < sizeof(uBootMD5); ++iLoop) { char szHexDigits[4]; sprintf(szHexDigits, "%02X", uBootMD5[iLoop]); strcat(szBootMD5, szHexDigits); } printf("boot_code MD5 value is %s\n\n", szBootMD5); CalculateRSA(szBootMD5, m_uBootRSA, true); printf("boot_code RDS value is "); for (int iLoop = 0; iLoop < sizeof(m_uBootRSA); ++iLoop) { printf("%02X", m_uBootRSA[iLoop]); } printf("\n\n"); delete[] pBootCode; printf("Writing boot_code checksum...\n"); fseek(Handle, m_iBootCodeStart * 2048 + m_iBootCodeSize - 64, SEEK_SET); fwrite(m_uBootRSA, 1, 64, Handle); return true; }
// ---------------------------------------------------------------------- // Get file snap shot // ---------------------------------------------------------------------- VOID GetFilesSnap(LPSNAPSHOT lpShot, LPTSTR lpszFullName, LPFILECONTENT lpFatherFC, LPFILECONTENT *lplpCaller) { LPFILECONTENT lpFC; HANDLE hFile; BOOL calculateHash = TRUE; BOOL found = FALSE; // Full dir/file name is already given // Extra local block to reduce stack usage due to recursive calls { LPTSTR lpszFindFileName; lpszFindFileName = NULL; // Get father file data if not already provided (=called from FileShot) // lpFatherFC only equals "C:\" and is called once at start if (NULL == lpFatherFC) { // Check if file is to be GENERIC excluded if ((NULL == lpszFullName) || (((TCHAR)'.' == lpszFullName[0]) // fast exclusion for 99% of the cases && ((0 == _tcscmp(lpszFullName, TEXT("."))) || (0 == _tcscmp(lpszFullName, TEXT("..")))))) { return; } // Create new file content lpFatherFC = MYALLOC0(sizeof(FILECONTENT)); // Set file name length lpFatherFC->cchFileName = _tcslen(lpszFullName); // Copy file name to new buffer for directory search and more lpszFindFileName = MYALLOC((lpFatherFC->cchFileName + 4 + 1) * sizeof(TCHAR)); // +4 for "\*.*" search when directory (later in routine) _tcscpy(lpszFindFileName, lpszFullName); // Special case if root dir of a drive was specified, needs trailing backslash otherwise current dir of that drive is used if ((TCHAR)':' == lpszFindFileName[lpFatherFC->cchFileName - 1]) { lpszFindFileName[lpFatherFC->cchFileName] = (TCHAR)'\\'; lpszFindFileName[lpFatherFC->cchFileName + 1] = (TCHAR)'\0'; } //printf("lpszFullName: %ws\n", lpszFullName); //printf("lpszFindFileName: %ws\n", lpszFindFileName); hFile = FindFirstFile(lpszFullName, &FindData); if (INVALID_HANDLE_VALUE != hFile) { FindClose(hFile); } else { // Workaround for some cases in Windows Vista and later ZeroMemory(&FindData, sizeof(FindData)); hFile = CreateFile(lpszFullName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (INVALID_HANDLE_VALUE != hFile) { BY_HANDLE_FILE_INFORMATION FileInformation; BOOL bResult; bResult = GetFileInformationByHandle(hFile, &FileInformation); if (bResult) { FindData.dwFileAttributes = FileInformation.dwFileAttributes; FindData.ftCreationTime = FileInformation.ftCreationTime; FindData.ftLastAccessTime = FileInformation.ftLastAccessTime; FindData.ftLastWriteTime = FileInformation.ftLastWriteTime; FindData.nFileSizeHigh = FileInformation.nFileSizeHigh; FindData.nFileSizeLow = FileInformation.nFileSizeLow; } else { FindData.dwFileAttributes = GetFileAttributes(lpszFullName); if (INVALID_FILE_ATTRIBUTES == FindData.dwFileAttributes) { FindData.dwFileAttributes = 0; } bResult = GetFileTime(hFile, &FindData.ftCreationTime, &FindData.ftLastAccessTime, &FindData.ftLastWriteTime); if (!bResult) { FindData.ftCreationTime.dwLowDateTime = 0; FindData.ftCreationTime.dwHighDateTime = 0; FindData.ftLastAccessTime.dwLowDateTime = 0; FindData.ftLastAccessTime.dwHighDateTime = 0; FindData.ftLastWriteTime.dwLowDateTime = 0; FindData.ftLastWriteTime.dwHighDateTime = 0; } FindData.nFileSizeLow = GetFileSize(hFile, &FindData.nFileSizeHigh); if (INVALID_FILE_SIZE == FindData.nFileSizeLow) { FindData.nFileSizeHigh = 0; FindData.nFileSizeLow = 0; } } CloseHandle(hFile); } } // Remove previously added backslash (if any) lpszFindFileName[lpFatherFC->cchFileName] = (TCHAR)'\0'; // Copy pointer to current file into caller's pointer if (NULL != lplpCaller) { *lplpCaller = lpFatherFC; } // Increase dir/file count if (ISFILE(FindData.dwFileAttributes)) { lpShot->stCounts.cFiles++; } else { lpShot->stCounts.cDirs++; } // Copy file name lpFatherFC->lpszFileName = MYALLOC((lpFatherFC->cchFileName + 1) * sizeof(TCHAR)); _tcscpy(lpFatherFC->lpszFileName, lpszFullName); // Copy file data lpFatherFC->nWriteDateTimeLow = FindData.ftLastWriteTime.dwLowDateTime; lpFatherFC->nWriteDateTimeHigh = FindData.ftLastWriteTime.dwHighDateTime; lpFatherFC->nAccessDateTimeLow = FindData.ftLastWriteTime.dwLowDateTime; lpFatherFC->nAccessDateTimeHigh = FindData.ftLastWriteTime.dwHighDateTime; lpFatherFC->nFileSizeLow = FindData.nFileSizeLow; lpFatherFC->nFileSizeHigh = FindData.nFileSizeHigh; lpFatherFC->nFileAttributes = FindData.dwFileAttributes; // Set "lpFirstSubFC" pointer for storing the first child's pointer lplpCaller = &lpFatherFC->lpFirstSubFC; } // If father is a file, then leave (=special case when called from FileShot) if (ISFILE(lpFatherFC->nFileAttributes)) { if (NULL != lpszFindFileName) { MYFREE(lpszFindFileName); } return; } // Process all entries of directory // a) Create search pattern and start search if (NULL == lpszFindFileName) { lpszFindFileName = lpszFullName; } _tcscat(lpszFindFileName, TEXT("\\*.*")); hFile = FindFirstFile(lpszFindFileName, &FindData); if (lpszFindFileName != lpszFullName) { MYFREE(lpszFindFileName); } } // End of extra local block if (INVALID_HANDLE_VALUE == hFile) { // error: nothing in dir, no access, etc. //printf(">>> ERROR: fileshot.c: getFileSnap: INVALID_HANDLE_VALUE: %ws\n", lpszFullName); return; } // b) process entry then find next do { lpszFullName = NULL; //BOOL calculateHash = TRUE; //BOOL found = FALSE; // Check if file is to be GENERIC excluded (dot dirs) if ((NULL == FindData.cFileName) || (((TCHAR)'.' == FindData.cFileName[0]) // fast exclusion for 99% of the cases && ((0 == _tcscmp(FindData.cFileName, TEXT("."))) || (0 == _tcscmp(FindData.cFileName, TEXT("..")))))) { continue; // ignore this entry and continue with next file } // Create new file content lpFC = MYALLOC0(sizeof(FILECONTENT)); // Set father of current key lpFC->lpFatherFC = lpFatherFC; // Set file name length lpFC->cchFileName = _tcslen(FindData.cFileName); // Allocate memory copy file name to FILECONTENT lpFC->lpszFileName = MYALLOC0((lpFC->cchFileName + 1) * sizeof(TCHAR)); _tcscpy(lpFC->lpszFileName, FindData.cFileName); // Static blacklist for directories if (ISDIR(FindData.dwFileAttributes)) { if (performStaticBlacklisting) { LPTSTR lpszFullPath; lpszFullPath = GetWholeFileName(lpFC, 4); found = TrieSearchPath(blacklistDIRS->children, lpszFullPath); if (found) { lpShot->stCounts.cFilesBlacklist++; MYFREE(lpszFullPath); FreeAllFileContents(lpFC); // Increase value count for display purposes lpShot->stCounts.cDirsBlacklist++; // Ignore this entry and continue with next brother value continue; } else { MYFREE(lpszFullPath); } } } // Check if the file system entry is a symbolic link // If so, skip as it actually resides somewhere else on the file system! if (ISSYM(FindData.dwFileAttributes)) { if (ISFILE(FindData.dwFileAttributes)) { lpShot->stCounts.cFilesBlacklist++; } else { lpShot->stCounts.cDirsBlacklist++; } continue; } // Blacklisting implementation for files if (ISFILE(FindData.dwFileAttributes)) { if (dwBlacklist == 1) { // First snapshot, therefore populate the Trie (Prefix Tree) // Get the full file path LPTSTR lpszFullPath; lpszFullPath = GetWholeFileName(lpFC, 4); // Add full path to file blacklist prefix tree, then free path TrieAdd(&blacklistFILES, lpszFullPath); MYFREE(lpszFullPath); // Increase value count for display purposes lpShot->stCounts.cFiles++; // Ignore this entry and continue with next brother value //continue; } else if (dwBlacklist == 2) { // Not the first snapshot, so either: // 1) If blacklisting enabled: Ignore file if its in the blacklist // 2) If hashing enabled (and not blacklisting): Mark file as not to be hashed LPTSTR lpszFullPath; lpszFullPath = GetWholeFileName(lpFC, 4); found = TrieSearchPath(blacklistFILES->children, lpszFullPath); if (found) { if (performDynamicBlacklisting) { MYFREE(lpszFullPath); FreeAllFileContents(lpFC); // Increase value count for display purposes lpShot->stCounts.cFilesBlacklist++; // Ignore this entry and continue with next brother value continue; } if (performSHA1Hashing || performMD5Hashing) { lpShot->stCounts.cFiles++; MYFREE(lpszFullPath); calculateHash = FALSE; } } else { MYFREE(lpszFullPath); } } } // Copy pointer to current file into caller's pointer if (NULL != lplpCaller) { *lplpCaller = lpFC; } // Increase dir/file count if (ISFILE(FindData.dwFileAttributes)) { lpShot->stCounts.cFiles++; } else { lpShot->stCounts.cDirs++; } // Copy file data lpFC->nWriteDateTimeLow = FindData.ftLastWriteTime.dwLowDateTime; lpFC->nWriteDateTimeHigh = FindData.ftLastWriteTime.dwHighDateTime; lpFC->nAccessDateTimeLow = FindData.ftLastWriteTime.dwLowDateTime; lpFC->nAccessDateTimeHigh = FindData.ftLastWriteTime.dwHighDateTime; lpFC->nFileSizeLow = FindData.nFileSizeLow; lpFC->nFileSizeHigh = FindData.nFileSizeHigh; lpFC->nFileAttributes = FindData.dwFileAttributes; // Calculate file hash (computationally intensive!) // This should only be executed in the following scenarios: // 1) If the file system entry is a data file // 2) If the data file is not blacklisted (previously known) if (ISFILE(FindData.dwFileAttributes)) { if (dwBlacklist == 2 && calculateHash) { if (performSHA1Hashing) { lpFC->cchSHA1 = 40; lpFC->lpszSHA1 = MYALLOC((lpFC->cchSHA1 + 1) * sizeof(TCHAR)); _tcscpy(lpFC->lpszSHA1, CalculateSHA1(GetWholeFileName(lpFC, 4))); } if (performMD5Hashing) { lpFC->cchMD5 = 32; lpFC->lpszMD5 = MYALLOC((lpFC->cchMD5 + 1) * sizeof(TCHAR)); _tcscpy(lpFC->lpszMD5, CalculateMD5(GetWholeFileName(lpFC, 4))); } if (performMD5BlockHashing) { LPMD5BLOCK theMD5Block = CalculateMD5Blocks(GetWholeFileName(lpFC, 4), dwHashBlockSize); lpFC->lpMD5Block = MYALLOC0(sizeof(MD5BLOCK)); lpFC->lpMD5Block = theMD5Block; } } } // Print file system shot status if ((dwBlacklist == 2 && performDynamicBlacklisting) || (performStaticBlacklisting)) { printf(" > Dirs: %d Files: %d Blacklisted Dirs: %d Blacklisted Files: %d\r", lpShot->stCounts.cDirs, lpShot->stCounts.cFiles, lpShot->stCounts.cDirsBlacklist, lpShot->stCounts.cFilesBlacklist); } else { printf(" > Dirs: %d Files: %d\r", lpShot->stCounts.cDirs, lpShot->stCounts.cFiles); } // ATTENTION!!! FindData will be INVALID from this point on, due to recursive calls // If the entry is a directory, then do a recursive call for it // Pass this entry as father and "lpFirstSubFC" pointer for storing the first child's pointer if (ISDIR(lpFC->nFileAttributes)) { if (NULL == lpszFullName) { lpszFullName = GetWholeFileName(lpFC, 4); // +4 for "\*.*" search (in recursive call) } GetFilesSnap(lpShot, lpszFullName, lpFC, &lpFC->lpFirstSubFC); } if (NULL != lpszFullName) { MYFREE(lpszFullName); } // Set "lpBrotherFC" pointer for storing the next brother's pointer lplpCaller = &lpFC->lpBrotherFC; } while (FindNextFile(hFile, &FindData)); FindClose(hFile); }
CVersionInfo::CVersionInfo() { // Getting the check-sum only once on start-up _openholdem_MD5 = CalculateMD5(PathOfExecutable()); }