5.2 磁盘CRC32完整性检测

打印 上一主题 下一主题

主题 931|帖子 931|积分 2793

CRC校验技术是用于检测数据传输或存储过程中是否出现了错误的一种方法,校验算法可以通过计算应用与数据的循环冗余校验(CRC)检验值来检测任何数据损坏。通过运用本校验技术我们可以实现对特定内存区域以及磁盘文件进行完整性检测,并以此来判定特定程序内存是否发生了变化,如果发生变化则拒绝执行,通过此种方法来保护内存或磁盘文件不会被非法篡改。总之,内存和磁盘中的校验技术都是用于确保数据和程序的完整性和安全性的重要技术。
磁盘CRC(循环冗余校验)用于检测磁盘数据的完整性,一般而言某些木马专杀工具同样会用到磁盘CRC特征校验技术,该技术的实现原理与内存验证原理完全一致,针对磁盘的验证同样很简单,但此处我们需要将计算到的CRC32值存储到PE文件自身中,通常我们可以存储到PE文件的前一个DWORD的位置上,程序运行后对比这个值,来判断程序是否被打过补丁,如果打过直接结束掉。
  1. // 检查磁盘完整性
  2. BOOL CalculateDiskCRC32()
  3. {
  4.     char szFileName[MAX_PATH] = { 0 };
  5.     char *pBuffer;
  6.     DWORD pNumberOfBytesRead;
  7.     int FileSize = 0;
  8.     // 获取自身文件,并打开文件
  9.     GetModuleFileName(0, szFileName, MAX_PATH);
  10.     HANDLE hFile = CreateFile(szFileName, GENERIC_READ, 1, 0, 3, FILE_ATTRIBUTE_NORMAL, 0);
  11.     if (hFile == INVALID_HANDLE_VALUE)
  12.     {
  13.         return TRUE;
  14.     }
  15.     // 取文件长度
  16.     FileSize = GetFileSize(hFile, 0);
  17.     pBuffer = new char[FileSize];
  18.     // 读取文件到内存
  19.     ReadFile(hFile, pBuffer, FileSize, &pNumberOfBytesRead, 0);
  20.     CloseHandle(hFile);
  21.     PIMAGE_DOS_HEADER pDosHeader = NULL;
  22.     PIMAGE_NT_HEADERS32 pNtHeader = NULL;
  23.     pDosHeader = (PIMAGE_DOS_HEADER)pBuffer;
  24.     // 获取到NT头
  25.     pNtHeader = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader + pDosHeader->e_lfanew);
  26.     // 定位到PE文件头前4字节处
  27.     DWORD OriginalCRC32 = *(DWORD *)((DWORD)pNtHeader - 4);
  28.     printf("[*] 读出节表值 = %x \n", OriginalCRC32);
  29.     // 我们只需要计算PE结构的CRC32值,不需要计算DOS头
  30.     FileSize = FileSize - DWORD(pDosHeader->e_lfanew);
  31.     DWORD CheckCRC32 = CRC32((BYTE*)(pBuffer + pDosHeader->e_lfanew), FileSize);
  32.     printf("[+] 计算CRC32 = %x \n", CheckCRC32);
  33.     if (CheckCRC32 == OriginalCRC32)
  34.     {
  35.         return FALSE;
  36.     }
  37.     else
  38.     {
  39.         return TRUE;
  40.     }
  41.     return TRUE;
  42. }
  43. int main(int argc, char* argv[])
  44. {
  45.     BOOL ref = CalculateDiskCRC32();
  46.     if (ref == TRUE)
  47.     {
  48.         printf("[-] 程序已被修改 \n");
  49.     }
  50.     else
  51.     {
  52.         printf("[+] 程序正常 \n");
  53.     }
  54.     system("pause");
  55.     return 0;
  56. }
复制代码
首先读者运行上述程序,则程序会输出当前的CRC32值be63ac8b我们记下这个HASH值,如下图所示;

并将此值替换到如下图中的黄色位置,当程序运行后会读取该区域内的数据,并与动态计算的CRC32值进行计算,最终判断是否被修改,如下图所示;

通过CRC32数据对比并遍历磁盘文件,我们可以实现一个简单的特征定位查杀程序,用于专门定位某些特殊的程序,如下是修改后的代码片段;
  1. // 计算文件CRC过程
  2. BOOL CalcCRC32(char *FilePath)
  3. {
  4.     // 打开文件
  5.     HANDLE hFile = CreateFile(FilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  6.     if (hFile == INVALID_HANDLE_VALUE)
  7.     {
  8.         return FALSE;
  9.     }
  10.     // 获取文件大小
  11.     DWORD dwSize = GetFileSize(hFile, NULL);
  12.     if (dwSize == 0xFFFFFFFF)
  13.     {
  14.         return FALSE;
  15.     }
  16.     // 分配内存
  17.     BYTE *pFile = (BYTE*)malloc(dwSize);
  18.     if (pFile == NULL)
  19.     {
  20.         return FALSE;
  21.     }
  22.     // 读取内存
  23.     DWORD dwNum = 0;
  24.     ReadFile(hFile, pFile, dwSize, &dwNum, NULL);
  25.     // 计算CRC32
  26.     DWORD dwCRC32 = CRC32(pFile, dwSize);
  27.     if (pFile != NULL)
  28.     {
  29.         free(pFile);
  30.         pFile = NULL;
  31.     }
  32.     CloseHandle(hFile);
  33.     return dwCRC32;
  34. }
  35. int main(int argc, char* argv[])
  36. {
  37.     WIN32_FIND_DATA stFindFile;
  38.     HANDLE hFindFile;
  39.     char *szFilter = "*.exe";      // 筛选所有的.exe结尾的文件
  40.     char szFindFile[MAX_PATH];     // 保存欲检测程序的路径
  41.     char szSearch[MAX_PATH];       // 保存完整的筛选路径
  42.     int ret = 0;                   // 搜索状态返回值
  43.     lstrcpy(szFindFile, "D:\");   // 搜索D盘目录下的所有exe结尾的文件
  44.     lstrcpy(szSearch, "D:\");
  45.     lstrcat(szSearch, szFilter);
  46.     DWORD dwTmpCRC32;
  47.     hFindFile = FindFirstFile(szSearch, &stFindFile);
  48.     if (hFindFile != INVALID_HANDLE_VALUE)
  49.     {
  50.         do
  51.         {
  52.             lstrcat(szFindFile, stFindFile.cFileName);
  53.             dwTmpCRC32 = CalcCRC32(szFindFile);
  54.             // 比较判断
  55.             if (dwTmpCRC32 == 0xbe63ac8b)
  56.             {
  57.                 printf("[*] CRC32 = %x 发现病毒 %s \n", dwTmpCRC32, szFindFile);
  58.             }
  59.             else
  60.             {
  61.                 printf("[-] CRC32 = %x 正常程序 %s \n", dwTmpCRC32, szFindFile);
  62.             }
  63.             // 删除程序名称只保留"C:"
  64.             szFindFile[3] = '\0';
  65.             ret = FindNextFile(hFindFile, &stFindFile);
  66.         } while (ret != 0);
  67.     }
  68.     FindClose(hFindFile);
  69.     system("pause");
  70.     return 0;
  71. }
复制代码
运行程序输出效果如下图所示;

本文作者: 王瑞
本文链接: https://www.lyshark.com/post/7a9a55f0.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

麻花痒

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表