當前位置: 妍妍網 > 碼農

CRC校驗完整性

2024-06-04碼農

點選上方 藍字 江湖評談 設為關註/星標




前言

本篇用作技術性研究,一個簡單的演算法。

設想一個問題,一個程式如果它沒有漏洞如何hook(攻擊)它呢?答案很簡單,人為制造漏洞。比如常用的指令性的更改(je指令更改為jne等屬此類)。但是這樣就會造成了程式(exe或者dll)裏二進制的不一致性,防範這種hook方法,就是檢驗程式二進制的完整性,CRC演算法就是這種校驗的體現。

CRC演算法

我們可以把程式進行如下CRC演算法Result

DWORD CRC32(BYTE* ptr, DWORD Size){DWORDcrcTable[256], crcTmp1;for(int i = 0; i < 256; i++){crcTmp1 = i;for(int j = 8; j > 0; j--){if(crcTmp1 & 1) crcTmp1 = (crcTmp1 >> 1) ^ 0xEDB88320L;elsecrcTmp1 >>= 1;}crcTable[i] = crcTmp1;}DWORDcrcTmp2 = 0xFFFFFFFF;while(Size--){crcTmp2 = ((crcTmp2 >> 8) & 0x00FFFFFF) ^ crcTable[(crcTmp2 ^ (*ptr)) & 0xFF];ptr++;}return(crcTmp2 ^ 0xFFFFFFFF);}

ptr參數是二進制檔需要crc校驗的起始地址,Size則是校驗的二進制字節數。如果想要校驗一個exe或者DLL的Result數值,那麽我們可以如下:

GetOpenFileName(&ofn);hFile = CreateFile( szFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,NULL);fileSize = GetFileSize(hFile, &szTemp);pDosHeader = (PIMAGE_DOS_HEADER)pBuffer;pNtHeader = (PIMAGE_NT_HEADERS64)((DWORD)pDosHeader + pDosHeader->e_lfanew);fileSize = fileSize - DWORD(pDosHeader->e_lfanew);szCRC32 = CRC32((BYTE*)(pBuffer + pDosHeader->e_lfanew), fileSize);DWORD Writeadd = DWORD(pDosHeader->e_lfanew - 4);SetFilePointer(hFile, Writeadd, NULL, FILE_BEGIN);if (!WriteFile(hFile, &szCRC32, 4, &szTemp, NULL)){ CloseHandle(hFile);}

當程式開始執行的時候,我們可以校驗ptr到size中間的crc result,進行一個判斷:

pBuffer = new TCHAR [fileSize]; ReadFile(hFile,pBuffer, fileSize, &NumberOfBytesRW, NULL);CloseHandle(hFile); pDosHeader=(PIMAGE_DOS_HEADER)pBuffer;pNtHeader=(PIMAGE_NT_HEADERS32)((DWORD)pDosHeader+pDosHeader->e_lfanew); fileSize=fileSize-DWORD(pDosHeader->e_lfanew);if (CRC32((BYTE*)(pBuffer+pDosHeader->e_lfanew),fileSize) == OriginalCRC32 )returnTRUE;elsereturnFALSE;

如果返回false則表示,exe或者dll更改了,此時我們就可以結束程式,不作任何執行,以防止被認為破解。

結尾

以上是校驗的過程,主要的原理即把二進制進行計算,然後得出的結果進行保存,執行的時候再次進行計算,比較兩次計算結果。程式碼取自【加密與解密】一書。整體來說,這種保護性較弱,但可以作為一種手段升級下。

往期精彩回顧