5.2 磁盘CRC32完整性检测

news2024/11/26 7:37:03

CRC校验技术是用于检测数据传输或存储过程中是否出现了错误的一种方法,校验算法可以通过计算应用与数据的循环冗余校验(CRC)检验值来检测任何数据损坏。通过运用本校验技术我们可以实现对特定内存区域以及磁盘文件进行完整性检测,并以此来判定特定程序内存是否发生了变化,如果发生变化则拒绝执行,通过此种方法来保护内存或磁盘文件不会被非法篡改。总之,内存和磁盘中的校验技术都是用于确保数据和程序的完整性和安全性的重要技术。

磁盘CRC(循环冗余校验)用于检测磁盘数据的完整性,一般而言某些木马专杀工具同样会用到磁盘CRC特征校验技术,该技术的实现原理与内存验证原理完全一致,针对磁盘的验证同样很简单,但此处我们需要将计算到的CRC32值存储到PE文件自身中,通常我们可以存储到PE文件的前一个DWORD的位置上,程序运行后对比这个值,来判断程序是否被打过补丁,如果打过直接结束掉。

// 检查磁盘完整性
BOOL CalculateDiskCRC32()
{
    char szFileName[MAX_PATH] = { 0 };

    char *pBuffer;
    DWORD pNumberOfBytesRead;
    int FileSize = 0;

    // 获取自身文件,并打开文件
    GetModuleFileName(0, szFileName, MAX_PATH);
    HANDLE hFile = CreateFile(szFileName, GENERIC_READ, 1, 0, 3, FILE_ATTRIBUTE_NORMAL, 0);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        return TRUE;
    }

    // 取文件长度
    FileSize = GetFileSize(hFile, 0);
    pBuffer = new char[FileSize];

    // 读取文件到内存
    ReadFile(hFile, pBuffer, FileSize, &pNumberOfBytesRead, 0);
    CloseHandle(hFile);

    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS32 pNtHeader = NULL;

    pDosHeader = (PIMAGE_DOS_HEADER)pBuffer;

    // 获取到NT头
    pNtHeader = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader + pDosHeader->e_lfanew);

    // 定位到PE文件头前4字节处
    DWORD OriginalCRC32 = *(DWORD *)((DWORD)pNtHeader - 4);
    printf("[*] 读出节表值 = %x \n", OriginalCRC32);

    // 我们只需要计算PE结构的CRC32值,不需要计算DOS头
    FileSize = FileSize - DWORD(pDosHeader->e_lfanew);
    DWORD CheckCRC32 = CRC32((BYTE*)(pBuffer + pDosHeader->e_lfanew), FileSize);
    printf("[+] 计算CRC32 = %x \n", CheckCRC32);

    if (CheckCRC32 == OriginalCRC32)
    {
        return FALSE;
    }
    else
    {
        return TRUE;
    }
    return TRUE;
}

int main(int argc, char* argv[])
{
    BOOL ref = CalculateDiskCRC32();
    if (ref == TRUE)
    {
        printf("[-] 程序已被修改 \n");
    }
    else
    {
        printf("[+] 程序正常 \n");
    }

    system("pause");
    return 0;
}

首先读者运行上述程序,则程序会输出当前的CRC32值be63ac8b我们记下这个HASH值,如下图所示;

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

通过CRC32数据对比并遍历磁盘文件,我们可以实现一个简单的特征定位查杀程序,用于专门定位某些特殊的程序,如下是修改后的代码片段;

// 计算文件CRC过程
BOOL CalcCRC32(char *FilePath)
{
    // 打开文件
    HANDLE hFile = CreateFile(FilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        return FALSE;
    }

    // 获取文件大小
    DWORD dwSize = GetFileSize(hFile, NULL);
    if (dwSize == 0xFFFFFFFF)
    {
        return FALSE;
    }

    // 分配内存
    BYTE *pFile = (BYTE*)malloc(dwSize);
    if (pFile == NULL)
    {
        return FALSE;
    }

    // 读取内存
    DWORD dwNum = 0;
    ReadFile(hFile, pFile, dwSize, &dwNum, NULL);

    // 计算CRC32
    DWORD dwCRC32 = CRC32(pFile, dwSize);
    if (pFile != NULL)
    {
        free(pFile);
        pFile = NULL;
    }

    CloseHandle(hFile);
    return dwCRC32;
}

int main(int argc, char* argv[])
{
    WIN32_FIND_DATA stFindFile;
    HANDLE hFindFile;
    char *szFilter = "*.exe";      // 筛选所有的.exe结尾的文件
    char szFindFile[MAX_PATH];     // 保存欲检测程序的路径
    char szSearch[MAX_PATH];       // 保存完整的筛选路径
    int ret = 0;                   // 搜索状态返回值

    lstrcpy(szFindFile, "D:\\");   // 搜索D盘目录下的所有exe结尾的文件
    lstrcpy(szSearch, "D:\\");
    lstrcat(szSearch, szFilter);
    DWORD dwTmpCRC32;

    hFindFile = FindFirstFile(szSearch, &stFindFile);
    if (hFindFile != INVALID_HANDLE_VALUE)
    {
        do
        {
            lstrcat(szFindFile, stFindFile.cFileName);
            dwTmpCRC32 = CalcCRC32(szFindFile);

            // 比较判断
            if (dwTmpCRC32 == 0xbe63ac8b)
            {
                printf("[*] CRC32 = %x 发现病毒 %s \n", dwTmpCRC32, szFindFile);
            }
            else
            {
                printf("[-] CRC32 = %x 正常程序 %s \n", dwTmpCRC32, szFindFile);
            }
            // 删除程序名称只保留"C:\"
            szFindFile[3] = '\0';
            ret = FindNextFile(hFindFile, &stFindFile);
        } while (ret != 0);
    }

    FindClose(hFindFile);

    system("pause");
    return 0;
}

运行程序输出效果如下图所示;

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1023780.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java“牵手”天猫商品列表页数据采集+天猫商品价格数据排序,天猫API接口申请指南

天猫开放平台接口获取商品列表和详情数据,具体步骤如下: 在开放平台注册并创建一个应用,获取到 App Key 和 App Secret等信息。使用获取到的信息进行签名和认证,获取 Access Token。调用开放平台提供的接口,传入商品 …

PM3398B-6P-1–3P-E 借助物联网和人工智能解决方案

PM3398B-6P-1–3P-E 借助物联网和人工智能解决方案 油砂中的卡车发动机捕获大量数据,如振动、温度、压力和吞吐量等参数。但是这些数据大部分都没有被使用。借助物联网和人工智能解决方案,您可以轻松利用这些数据获得有用的见解。这些见解有助于您提高发…

1.wifi开发,wifi连接初次连接电脑没有识别,搭建环境

wifi连接初次连接电脑没有识别 1.不识别可能是线的问题,即使wifi的灯亮了,虽然串口却没有找到。所以解决方法就是重新来一个usb的线 一。初步使用 (1)使用ESP烧写工具(选择esp8266) (2&#xf…

TienChin 渠道管理-添加渠道

在我们平时新建一个全新的 Java 类,这个类需要存放的包不存在,可以使用如下的方式进行创建: 含义就是说,将 ChannelVO 这个类放在 vo 这个包当中,如果存在则不创建,存在就将新建的类放入其中。 ChannelVO /…

2000-2018年各省能源消费和碳排放数据

2000-2018年各省能源消费和碳排放数据 1、时间:2000-2018年 2、范围:30个省市 3、指标:id、year、ENERGY、COAL、碳排放倒数*100 4、来源:能源年鉴 5、指标解释: 2018年碳排放和能源数据为插值法推算得到 碳排放…

SpringBoot接口中如何直接返回图片数据

SpringBoot接口中如何直接返回图片数据 目录 接口直接返回图片数据 起因 类似这种 根据个人经验 优雅的实现图片返回 接口直接返回图片数据 起因 最近在做涉及到分享推广的业务,需要由业务员分享二维码进入推广页面,由于是新项目,前期…

Vue.js基本语法上

🎬 艳艳耶✌️:个人主页 🔥 个人专栏 :《Spring与Mybatis集成整合》《springMvc使用》 ⛺️ 生活的理想,为了不断更新自己 ! 目录 1.插值 1.1 文本 1.2 v-v-html 1.3 数据双向绑定数据(v-model) 1.4 属性&#xff…

fork函数

二.fork函数 2.1函数原型 fork()函数在 C 语言中的原型如下&#xff1a; #include <unistd.h>pid_t fork(void);其中pid_t是一个整型数据类型&#xff0c;用于表示进程ID。fork()函数返回值是一个pid_t类型的值&#xff0c;具体含义如下&#xff1a; 如果调用fork()的…

Vue3 菜鸟入门(一)超详细:介绍、安装、打包、创建项目、目录结构、起步等

【学习笔记】Vue3 菜鸟入门&#xff08;一&#xff09;超详细&#xff1a;介绍、安装、打包、创建项目、目录结构、起步等 关键词&#xff1a;Vue 、Vue 3、Java、Spring Boot、Idea、数据库、一对一、培训、教学本文主要内容含Vue3介绍、安装、打包、创建项目、目录结构、起步…

避雷器雷击计数器检验

试验目的 由于密封不良&#xff0c; 放电计数器在运行中可能进入潮气或水分&#xff0c; 使内部元件锈蚀&#xff0c;导致计数器不能正确动作&#xff0c; 因此需定期试验以判断计数器是否状态良好、 能否正常动作&#xff0c; 以便总结运行经验并有助于事故分析。 带有泄漏电…

[论文阅读] SADGA: Structure-Aware Dual Graph Aggregation Network for Text-to-SQL

“SADGA: Structure-Aware Dual Graph Aggregation Network for Text-to-SQL” 是一篇 text2sql 领域的论文&#xff0c;发布于 NeurIPS 2021。 原文链接&#xff1a;https://arxiv.org/abs/2111.00653 项目代码链接&#xff1a;https://github.com/DMIRLAB-Group/SADGA 总体…

exev函数族

一.exev函数族 1.1功能 exec()函数族的主要功能是在当前进程中运行一个新的程序。使用这些函数可以实现以下功能&#xff1a; 程序替换&#xff08;Program Replacement&#xff09;&#xff1a;调用exec()函数后&#xff0c;当前进程的代码和数据会被新程序的代码和数据替换…

【JDK 8-集合框架】5.4 allMatch 和 anyMatch 函数

一、allMatch 函数 二、anyMatch 函数 三、其它函数学习 四、实战 > 执行结果 一、allMatch 函数 检查是否 匹配所有元素&#xff0c;返回 true 二、anyMatch 函数 检查是否 至少匹配一个元素&#xff0c;返回 true 三、其它函数学习 看源码 入参&#xff0c;返回值…

【ElementUI】ElementUI Tooltip 根据内容判断是否显示、文字提示自定义样式

【ElementUI】ElementUI Tooltip 根据内容判断是否显示、文字提示自定义样式 封装组件自定义内容 <template><span v-if"[, null, undefined].indexOf(content) -1"><el-tooltip :content"content" effect"light" placement&q…

ENVI IDL:OMI-NO2产品均值计算与可视化(附Python代码)-年、季、月均值计算

目录 01 实验题目 02 我的IDL代码 03 实验给定IDL代码 04 Python代码实现 4.1 我的Python代码 4.2 实验给定Python代码 01 实验题目 计算/coarse_data/chapter_2/NO2/目录下所有OMI-NO2产品数据集ColumnAmountNO2TropCloudScreened的月均值、季均值、年均值&#xff0c;并…

风控基础——MOB、Vintage是什么?

▍Vintage背景 Vintag一词最初来源于葡萄酒业 。由于每年采摘的葡萄会受到日照、气温、降水等因素的影响&#xff0c;最终酿造的葡萄酒品质会存在差异。在窖藏一定年份后&#xff0c;葡萄酒的品质将趋于稳定&#xff0c;也就是品质成熟&#xff0c;这段年份数被称为成熟期。表…

广州华锐互动:利用VR复原文化遗址,沉浸式体验历史文物古迹的魅力

在过去的几十年里&#xff0c;科技发展飞速&#xff0c;为我们打开了无数新的视角和可能性。其中&#xff0c;虚拟现实&#xff08;Virtual Reality&#xff0c;简称VR&#xff09;技术的崭新应用&#xff0c;为我们提供了一种全新的、近乎身临其境的体验历史的方式。本文将重点…

全网最全Kettle教程-Kettle概述

文章目录 第一章 Kettle概述1.1 Kettle发展历程1.2 Kettle简介1.3 Kettle相关俗语1.4 Kettle设计与组成1.5 Kettle功能模块1.6 Kettle的执行Transformation&#xff08;转换&#xff09;1.7 Kettle商业和社区版区别1.8 数据集成与ETL1.9 ETL工具比较 第一章 Kettle概述 1.1 Ke…

HTTP DNS的工作模式

HttpDNS 其实就是&#xff0c;不走传统的 DNS 解析&#xff0c;而是自己搭建基于 HTTP 协议的 DNS 服务器集群&#xff0c;分布在多个地点和多个运营商。当客户端需要 DNS 解析的时候&#xff0c;直接通过 HTTP 协议进行请求这个服务器集群&#xff0c;得到就近的地址。 这就相…

如何构建一个高质量的论文框架

一个高质量的论文框架对于论文撰写非常重要。它可以为你的研究提供一个有序和清晰的结构&#xff0c;突出你的研究贡献&#xff0c;简化写作难度&#xff0c;方便修改和审阅&#xff0c;并提升你的专业形象。因此&#xff0c;建议在撰写论文之前充分考虑并构建一个合适的论文框…