5.1 内存CRC32完整性检测

news2024/12/28 19:31:37

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

内存CRC32特征检测通常用于防止软件破解或打补丁,内存特征码检查实现原理是通过定位到.text节表的首地址及该节的长度,然后计算该节的CRC32值并存入全局变量,通过在程序内部打开一个子线程用于实时监测内存,一旦发现CRC32值发生了变化,则可执行终止程序运行等操作,以此来实现防止破解或打补丁的目的。

我们来看这样一段代码,程序通过GetModuleHandle(NULL)函数获取到自身程序的句柄,并通过PE结构定位到.text节,取出该节内的VirtualAddress虚拟地址,以及VirtualSize虚拟长度,最后调用CRC32((BYTE*)(va_base), sec_len)获取到该节的CRC数据。

// 检查内存中CRC32特征值
DWORD CalculateMemoryCRC32()
{
    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNtHeader = NULL;
    PIMAGE_SECTION_HEADER pSecHeader = NULL;
    DWORD ImageBase;

    // 获取基地址
    ImageBase = (DWORD)GetModuleHandle(NULL);

    // 定位到PE头结构
    pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
    pNtHeader = (PIMAGE_NT_HEADERS32)((DWORD)pDosHeader + pDosHeader->e_lfanew);

    // 定位第一个区块地址,因为默认的话第一个就是.text节
    pSecHeader = IMAGE_FIRST_SECTION(pNtHeader);
    DWORD va_base = ImageBase + pSecHeader->VirtualAddress;   // 定位代码节va基地址
    DWORD sec_len = pSecHeader->Misc.VirtualSize;             // 获取代码节长度
    printf("镜像基址(.text): %x | 镜像大小: %d \n", va_base, sec_len);

    DWORD CheckCRC32 = CRC32((BYTE*)(va_base), sec_len);
    printf(".text节CRC32 = %x \n", CheckCRC32);

    return CheckCRC32;
}

当主程序执行时,我们首先通过CalculateMemoryCRC32函数获取到当前代码段的校验码,并存储到OriginalCRC32全局变量内,在循环体内通过不断的计算CRC数据并与全局初始值做对比,以此来实现防止破解的作用。

int main(int argc, char *argv[])
{
    // 用于保存初始化时 .text 节中的CRC32值
    DWORD OriginalCRC32 = 0;

    // 初始化时,给全局变量赋值,记录下初始的CRC32值
    OriginalCRC32 = CalculateMemoryCRC32();

    while (1)
    {
        // 每隔3秒计算一次
        Sleep(3000);

        // 计算新的CRC
        DWORD NewCRC32 = CalculateMemoryCRC32();
        if (OriginalCRC32 == NewCRC32)
        {
            printf("[+] 当前CRC [ %x ] 程序没有被打补丁 \n",NewCRC32);
        }
        else
        {
            printf("[-] 当前CRC [ %x ] 已被打补丁 \n", NewCRC32);
        }
    }

    system("pause");
    return 0;
}

编译并运行上述程序片段,当读者使用x64dbg修改内存中的字节时,此处将int3修改为nopCRC32会提示我们内存已经被打补丁,输出效果如下图所示;

当然上述方法虽然可以对全局进行保护,但如果程序过大则此类验证效率将变得很低,我们需要通过使用打标签的方式对特定内存区域进行保护,如下代码中所示,我们通过begin设置开始保护标签,通过end设置结束保护标签,通过size = end_addr - begin_addr;计算即可获取到当前所需要保护的内存长度,最后通过CalculateMemoryCRC32实现计算内存CRC的目的,读者可以在当前进程内启动子线程用于实现专门的内存检测。

// 检查内存中CRC32特征值
DWORD CalculateMemoryCRC32(DWORD va_base, DWORD sec_len)
{
    DWORD CheckCRC32 = CRC32((BYTE*)(va_base), sec_len);
    return CheckCRC32;
}

int main(int argc, char *argv[])
{
    // 用于保存初始化时 .text 节中的CRC32值
    DWORD OriginalCRC32 = 0;

    DWORD begin_addr, end_addr, size;
    
    // 获取到两个位置的偏移地址
    __asm mov begin_addr, offset begin;
    __asm mov end_addr, offset end;

    // 计算出 两者内存差值
    size = end_addr - begin_addr;

    // 校验指定内存位置
    OriginalCRC32 = CalculateMemoryCRC32(begin_addr, size);

    while (1)
    {
        // 标记为需要保护的区域
    begin:
        printf("hello lyshark \n");
        printf("hello lyshark \n");
        printf("hello lyshark \n");

        // 保护区域声明结束
    end:

        // 计算并对比
        if (OriginalCRC32 == CalculateMemoryCRC32(begin_addr, size))
        {
            printf("[+] 此区域没有被修改 \n");
        }
        else
        {
            printf("[-] 此区域已被修改\n");
        }

        Sleep(3000);
    }
    system("pause");
    return 0;
}

当保护区域内的参数发生变化时则会弹出数据被篡改,如下所示我们通过填充一个nop指令,观察下图,读者能够发现我们的检测生效了;

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

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

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

相关文章

无涯教程-JavaScript - POWER函数

描述 POWER函数返回加到幂的数字的输出。 语法 POWER (number, power)争论 Argument描述Required/OptionalNumber 基数。 它可以是任何实数。 RequiredPowerThe exponent to which the base number is raised.Required Notes 可以使用" ^"运算符代替POWER来指示…

【深度学习实验】线性模型(四):使用Pytorch实现线性模型:使用随机梯度下降优化器训练模型

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入库 1. 线性模型linear_model 2. 损失函数loss_function 3. 定义数据 4. 初始化权重和偏置 5. 模型训练 6. 迭代 7. 实验结果 8. 完整代码 一、实验介绍 使用随机梯度下降优化…

【ES6知识】Iterator迭代器与 class类

文章目录 一、Iterator迭代器1.1 基础知识概述1.2 工作原理1.3 Symbol.iterator1.4 Generator函数来实现Symbol.iterator接口 二、ES6 Class 类2.1 概述2.2 ES6中的继承2.3 面向对象应用 - React 一、Iterator迭代器 1.1 基础知识概述 迭代器(Iterator&#xff09…

JAVA实现PDF转图片

前言 使用wps自带的转换工具&#xff0c;需要花钱&#xff0c;不花钱的话还带水印。于是&#xff0c;使用java程序将pdf转换为图片。 代码 依赖 <dependencies><dependency><groupId>org.apache.pdfbox</groupId><artifactId>fontbox</ar…

几个国内可用的强大的GPT工具

前言&#xff1a; 人工智能发布至今&#xff0c;过去了九个多月&#xff0c;已经成为了我们不管是工作还是生活中一个重要的辅助工具&#xff0c;大大提升了效率&#xff0c;作为一个人工智能的自然语言处理工具&#xff0c;它给各大行业的提供了一个巨大的生产工具&#xff0c…

Vue Grid Layout -️ 适用Vue.js的栅格布局系统,在vue3+上使用

文章目录 1、官网简介2、在vue3中使用1)、需要导入vue3支持的版本插件2)、在mian.js里引入&#xff1a;3)、在组件中使用 3、layout布局的计算逻辑4、 gridLayout 的属性 该栅格系统目前对 vue2 的支持是最好的&#xff0c;vue3 是需要用插件支持的&#xff0c;会在小节详细讲解…

目标检测:Edge Based Oriented Object Detection

论文作者&#xff1a;Jianghu Shen,Xiaojun Wu 作者单位&#xff1a;Harbin Institute of Technology Shenzhen 论文链接&#xff1a;http://arxiv.org/abs/2309.08265v1 内容简介&#xff1a; 1&#xff09;方向&#xff1a;遥感领域中的目标检测技术 2&#xff09;应用&…

肖sir__mysql之存储__012

mysql之存储 一、存储 1、什么是存储过程 定义&#xff1a;存储过程就是实现某个特定功能的sql语句的集合&#xff0c;编译后的存储过程会保存在数据库中&#xff0c;通过存储过程的名称可以反复的调用执行。 2、存储过程的优点? (1)存储创建后&#xff0c;可以反复的调用&am…

液晶LCD显示驱动VK2C23可支持最大416点(52SEGx8COM)的LCD屏提供LQFP48、LQFP64的封装

VK2C23是一个点阵式存储映射的LCD驱动器&#xff0c;可支持最大224点&#xff08;56SEGx4COM&#xff09;或者最大416点&#xff08;52SEGx8COM&#xff09;的LCD屏。单片机可通过I2C接口配置显示参数和读写显示数据&#xff0c;也可通过指令进入省电模式。其高抗干扰&#xff…

Zoho Projects登顶福布斯2023年项目管理工具排行榜

Zoho Projects一款集成度较高的项目管理工具&#xff0c;近日入选福布斯2023年十佳项目管理工具榜单。作为一款为中小企业量身定制的解决方案&#xff0c;Zoho Projects以其卓越的功能和性价比&#xff0c;赢得了市场的广泛认可。 在当今竞争激烈的市场环境中&#xff0c;选择一…

F.cross_entropy的使用困惑--终结

1.由于按照cross_entropy的计算公式&#xff0c;F.cross_entropy(outs,label)这里面的outs和label的应该都是batch_size * one_hot_vec的形状&#xff0c;但是&#xff0c;这个函数呢&#xff0c;第二个label只要是batch_size * scalar即可&#xff0c;那个scalar就是index的位…

如果你用Markdown写公众号文章,试试我做的在线转换神器

大家好&#xff0c;我希望向大家介绍一款我最近开发的实用工具——"MarkdownConvert"&#xff0c;它能够以极简和高效的方式将Markdown文本转换为微信公众号所支持的HTML格式。它是我基于一个开源项目改进优化了页面&#xff0c;增加了自己喜欢的文章主题。 先聊聊这…

微信小程序传参的五种方式

文章目录 前言一、URL参数传递1.api跳转2.组件跳转 二、Storage本地存储三、全局变量globalData四、页面跳转时传参五、页面栈传参总结结语 前言 大家好&#xff0c;今天和大家分享一下微信小程序页面之间传参的五种方式&#xff0c;这个的话也是有人问了我一嘴&#xff0c;然…

Python进阶复习-文件与异常

目录 文件打开文件路径打开模式字符编码 文件读取逐行读取读取所有行 文件写入既读又写两种数据存储结构csv文件json文件 程序异常Exception万能捕捉 文件打开 文件路径 完整路径 with open("E:\hello.txt", "r", encoding"UTF-8") as file:c…

Socks5与HTTP的区别与应用场景

在网络访问中&#xff0c;代理服务器扮演着重要角色&#xff0c;用于保护用户隐私、提高访问速度等。Socks5代理和HTTP代理是两种常见的代理协议&#xff0c;它们在功能和应用场景上有所不同。本文将深入解析Socks5代理和HTTP代理的区别&#xff0c;帮助您更好地了解并选择适合…

Linux 信号捕捉函数 signal sigaction

signal函数 #include <signal.h> typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler); 功能&#xff1a;设置某个信号的捕捉行为 参数&#xff1a; -signum&#xff1a;要捕捉的信号 handler&#xff1a;对捕捉到的信号怎么处理…

安装了多个版本VS导致无法安装vsix

如&#xff0c;先后安装了VS2015、VS2019&#xff0c;现在想给VS2015安装一个qt-vsaddin插件&#xff0c;运行vsix报错 “View Install Log”里显示 2023/9/19 10:03:46 - 正在搜索适用的产品... 2023/9/19 10:03:46 - 找到的已安装产品 - Microsoft Visual Studio Ultimate …

中标麒麟--国产操作系统-九五小庞

那么&#xff0c;我国国产操作系统现状到底如何呢&#xff1f; 自 1999 年徐冠华部长一语点破我们的产业软肋之后&#xff0c;国产操作系统起步于国家“七五”计划期间&#xff0c;目前国产操作系统均是基于Linux内核进行的二次开发&#xff0c;中国国产操作系统进入Linux元年…

多线程详解(上)

文章目录 一、线程的概念1&#xff09;线程是什么2&#xff09;为甚要有线程&#xff08;1&#xff09;“并发编程”成为“刚需”&#xff08;2&#xff09;在并发编程中, 线程比进程更轻量. 3&#xff09;线程和进程的区别 二、Thread的使用1&#xff09;线程的创建继承Thread…

【随想】每日两题Day.7

题目&#xff1a;面试题 02.07.链表相交 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。 …