點選上方 藍字 江湖評談 設為關註/星標
前言
本篇用作技術性研究,一個簡單的演算法。
設想一個問題,一個程式如果它沒有漏洞如何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;
else
returnFALSE;
如果返回false則表示,exe或者dll更改了,此時我們就可以結束程式,不作任何執行,以防止被認為破解。
結尾
以上是校驗的過程,主要的原理即把二進制進行計算,然後得出的結果進行保存,執行的時候再次進行計算,比較兩次計算結果。程式碼取自【加密與解密】一書。整體來說,這種保護性較弱,但可以作為一種手段升級下。
往期精彩回顧