CRC校验完整性

文摘   2024-06-03 15:20   湖北  

点击上方蓝字 江湖评谈设为关注/星标




前言

本篇用作技术性研究,一个简单的算法。

设想一个问题,一个程序如果它没有漏洞如何hook(攻击)它呢?答案很简单,人为制造漏洞。比如常用的指令性的更改(je指令更改为jne等属此类)。但是这样就会造成了程序(exe或者dll)里二进制的不一致性,防范这种hook方法,就是检验程序二进制的完整性,CRC算法就是这种校验的体现。

CRC算法

我们可以把程序进行如下CRC算法Result

DWORD CRC32(BYTE* ptr, DWORD Size){
DWORD crcTable[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; else crcTmp1 >>= 1; }
crcTable[i] = crcTmp1; } DWORD crcTmp2 = 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 )  return TRUE;else  return FALSE;

如果返回false则表示,exe或者dll更改了,此时我们就可以退出程序,不作任何运行,以防止被认为破解。

结尾

以上是校验的过程,主要的原理即把二进制进行计算,然后得出的结果进行保存,运行的时候再次进行计算,比较两次计算结果。代码取自《加密与解密》一书。整体来说,这种保护性较弱,但可以作为一种手段升级下。

往期精彩回顾

.NET9异常(CLR)原理(顶阶技术


江湖评谈
记录,分享,自由。
 最新文章