软件破解逆向安全(五)CRC检测

博客介绍了多种对抗游戏作弊的技术,如数据检测、CRC检测等。着重讲解了CRC检测,包括其属于密码学算法,用于数据校验,阐述了算法原理、实现方式,还给出了动手写CRC校验的示例,以及破解CRC检测的思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们先了解一下几种对抗游戏作弊的技术:

⒈数据检测:对基础的游戏数据进行校验,例如坐标是否违规越界地图(坐标瞬移功能),人物短时间位移距离是否过大(人物加速功能)等等

 

⒉CRC检测:基于游戏程序代码的检验,例如将人物移动中判断障碍物的je条件跳转修改为jmp强制跳转(人物穿墙功能)等等

 

⒊封包检测:将游戏数据封包进行校验,防止利用封包漏洞实现违规操作,例如之前的穿X火线强登(可以登录任意账号)等等

 

⒋机器检测:现在鹅厂 安全组好像换人了 ,游戏机器码封的都挺狠,一封就十年,不过道高一尺,魔高一丈,目前依然不够完善,很多朋友还是可以Pass

 

⒌Call检测:非法调用Call导致校验值非法,例如攻击Call的严格校验(角色扮演游戏自动打怪脚本都是调用Call的)等等

 

⒍堆栈检测:该检测归于调用Call过程中产生的问题

 

⒎文件检测:对于游戏本地文件的检测,例如之前穿X火线几年前风靡一时的REZ文件(快刀秒杀,穿墙,遁地,飞天)等等

 

⒏模块检测:很多外x挂采用“注入”的形式,所以模块检测在游戏安全对抗中也扮演着极其重要的作用

 

⒐特征检测:这个主要检测典型的使用“易语言”开发的程序,或者部分外x挂市场比较大的毒瘤程序,或者菜单绘制(imgui绘制)等等

 

⒑调试检测:针对调试器和调试行为的检测,对Ollydbg,CheatEngine等调试器特征和调试行为的检测等。

 

⒒游戏保护:主要是利用R3各种反调试技术以及驱动层的HOOK等技术实现的游戏保护,例如鹅厂的TP等等

 

说过检测之前我们先了解一下什么是crc检测。CRC,中文名称为循环冗余校验,CRC属于密码学一类算法,常用于数据校验,一般会用来检测程序是否被脱壳或者被修改,以达到防破解的目的。

CRC算法原理

数据发送过程:

多项式转化为二进制数,这个2进制数作为除数。

CRC校验码的位数=上面计算除数的位数-1

校验码的位数是多少,就把需要校验的数据左移多少位,得到的就是被除数

被除数 模二除 除数 = 商+余数

余数就是我们需要的CRC校验码

数据接收过程:0

多项式转化为二进制数,这个2进制数作为除数。

接收到的数据和CRC码拼接起来,作为被除数

除数确定了,被除数也确定了,接下来再次使用“模2除法”校验

结果为0,则接受的数据正确,结果不为0接收的数据不正确

还是不懂,很好,再翻译一遍

多项式就是一个指定的数值,用我们需要校验的数据模二除这个多项式的数值,得到的余数就是CRC校验码。

CRC算法实现

首先生成CRC校验码,我们这里按字节计算CRC,先写个函数生成一张字节CRC校验码的表,因为每个字节从00-FF有256个组合,所以每个字节有256种不同的校验码。

简单一句话总结一下:CRC是一种校验算法并且该算法被广泛应用于文件,数据等的校验

 

光说不练假把式,我们来动手写一个crc校验:

#include <Windows.h>
#include <stdio.h>


int crc = NULL;
int have_crc_table = NULL;
unsigned int crc32_table[256];


//生成具有256个元素的CRC32表
void Crc_Make_Table()
{
    have_crc_table = 1;


    for (int i = 0; i < 256; i++)
    {
        crc = i;
        for (int j = 0; j < 8; j++)
        {
            if (crc & 1)
                crc = (crc >> 1) ^ 0xEDB88320; //CRC32 多项式的值,也可以是0x04C11DB7
            else
                crc >>= 1;
        }
        crc32_table[i] = crc; //生成并存储CRC32数据表
    }
}


//根据CRC32数据表计算内存或文件CRC校验码
unsigned int Calc_Crc32(unsigned int crc, char* Data, int len)
{
    crc = 0xFFFFFFFF; //将CRC初始化为-1


    //判断CRC32表是否生成
    if (!have_crc_table)
        Crc_Make_Table();


    for (int i = 0; i < len; i++)
    {
        crc = (crc >> 8) ^ crc32_table[(crc ^ Data[i]) & 0xff];
    }
    return ~crc;
}


int main()
{
    SetConsoleTitleA("Crc检测过掉学习工具");


    printf("使用CE工具->添加地址0x402000->查找访问并尝试过掉检测!\n\n");


    printf("如果修改主程序模块,将会提示 “CRC代码校验检测到您修改了代码!”:\n\n\n\n\n");




    //初始内存校验值
    unsigned int uMainMoudleSumA = Calc_Crc32(0, (char*)0x400000, 0x1F000);//400000- 41D000


    //while循环开启CRC检测
    while (1)
    {
        //CRC循环检测内存实时校验值
        unsigned int TmpCrcSum = Calc_Crc32(0, (char*)0x400000, 0x1F000);


        if (TmpCrcSum != uMainMoudleSumA)
        {
            //封号处理-掉线处理
            MessageBoxA(NULL, "CRC代码校验检测到您修改了代码!", "Caption", MB_OK);
        }


        //为了方便,我在这里使用的Sleep函数控制检测的周期
        Sleep(2000);
    }


    getchar();
 

注:release编译的时候记得关一下各种优化

这里有一点注意的,

//计算内存校验值

Calc_Crc32(0, (char*)0x400000, 0x1F000);

最后一个参数是一个校验的范围,我们用PE相关工具去确定程序主模块镜像大小。

我们看我这里就要改一下,要不会出问题。

我们改一下这里的数值就相当于改了代码,就触发了crc校验

那么接下来,我们就想办法给他搞掉。

首先,在攻击前,我们要知道代码的CRC检测是针对代码段的

代码段是用来执行的,正常情况下不会有其他数据访问代码段,被访问的大多是数据段,代码段被访问,很可疑就是CRC检测

此处说的“访问”的概念,大家可以通过CheatEngine工具中的“找出是什么访问了这个地址”来理解

针对0x402000这个地址,我们去看一下什么访问了

记住这行汇编,出现这个基本上就是crc检测了。同时记住40103f这个地址,我们去od里跟一下。

我们单步的走一走看看

第一次这里是400000,走了一遍后

变成了400001,,也就是说,它在循环的递增检测所有范围内的内存代码数据。

这块的代码时crc校验的那里,我们要到的是if比较那一块,很明显我们要跳出这个call。但是下面有一个jmp,很明显我们正常跑是出不去的,我们需要到函数头那里找出返回地址

我们在这里回车就到我们的主程序里了

找到我们就要修改,call下面的eax是call返回的数值。大概看一下(因为是我们自己写的),我们就知道这个汇编程序的逻辑,先运行一个crc校验给local.1,然后不断的重复运行crc校验给local.2,这俩进行比较,不一样就弹对话框,那么我们破解的思路就有了,一个是把cmp xxx改成cmp eax,eax,这样就永远一样了,还有一种就是把je改成jmp,这样不管比较如何都不执行错误的代码,当然还有很多思路,大家可以试这改改,然后发现不管我们怎么改代码的数据都不会被crc检测出来了。

 

 

 

 

 

 

 

 

 

 

 

易语言 CRC32.ec校验模块 林子深作品 比其他的都便宜 CRC32.ec校验模块 林子深作品 下载 CRC32.ec校验模块下载 我们很有必要给自己的软件加上更好的保护。CRC校验就是其中的一种不错的方法。 CRC是什么东西呢?其实我们大家都不应该会对它陌生,回忆一下?你用过RAR和ZIP等压缩软件吗?它们是不是常常会给你一个恼人的“CRC校验错误”信息呢?我想你应该明白了吧,CRC就是块数据的计算值,它的全称是“Cyclic Redundancy Check”,中文名是“循环冗余码”,“CRC校验”就是“循环冗余校验”。 CRC有什么用呢?它的应用范围很广泛,最常见的就是在网络传输中进行信息的校对。其实我们大可以把它应用到软件保护中去,因为它的计算是非常非常非常严格的。严格到什么程度呢?你的程序只要被改动了一个字节(甚至只是大小写的改动),它的值就会跟原来的不同。呵呵,是不是很厉害呢?所以只要给你的“原”程序计算好CRC值,储存在某个地方,然后在程序中随机地再对文件进行CRC校验,接着跟第一次生成并保存好的CRC值进行比较,如果相等的话就说明你的程序没有被修改/破解过,如果不等的话,那么很可能你的程序遭到了病毒的感染,或者被奸人用16进制工具暴力破解过了。 CRC的本质是进行XOR运算,运算的过程我们不用管它,因为运算过程对最后的结果没有意义;我们真正感兴趣的只是最终得到的余数,这个余数就是CRC值。 易语言用户林子深提供了一个CRC32.EC的易模块,这个模块可以在论坛上或资源网上搜索到。大家可以直接拿过来用,导入易语言后如下图所示: 调用方式可为如下代码: 判断(取循环风俗冗余校验和(读入文件(取执行文件名()))= 18293823767) 其中上述的数字为主程序的CRC码值。 大家可以利用上述特性,即结果是数值的特性,不用进行比较,而是用加减法的方法得出前后两个CRC验的差值,如果为0,那说明两个数字是相等的,主程序没有被改动过。否则就是被改过的。 例如下述代码: 程序被改 = 1 计次循环首(取绝对值(取循环风俗冗余校验和(读入文件(取执行文件名()))- 18293823767),) 程序被改 = 0- 跳出循环() 计次循环尾() 返回(程序被改) 上述代码中,“取绝对值()”是将负数也转换为正数,以方便进行计次循环。 上述代码中,数值型变量“程序被改”为1表示没有被改动过,如果为0表示被改动过。返回的数值就可以进行一些陷阱的计算了。 我的方案的缺点分析: CRC-32的值其实可以由奸人自行计算得出后,重新写入到程序验证处。这样的话,我们做的工作岂不是没有意义了? 其实解决的方法还是有的,我们可以在计算CRC-32值之前,对参与转换的字符串加点手脚,例如对这个字符串进行移位、xor等操作,或者把自己的生日等信息加入到字符串中,随你的便什么都行,总之不是单纯的文件的内容就行了,然后在最后比较的时候,也用同样的方法反计算出CRC-32值。这样得到的CRC-32就不是由文件的内容计算出来的,相信对破解者的阻力也会加大不少。 总结: 以上的方法大家都可以在软件中采用,最好写到一个DLL文件中,然后多放几个需要验证的子程序,随时以备调用即可。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值