精华内容
下载资源
问答
  • 软件破解逆向安全(五)CRC检测

    千次阅读 2020-11-17 21:19:14
    CRC检测:基于游戏程序代码的检验,例如将人物移动中判断障碍物的je条件跳转修改为jmp强制跳转(人物穿墙功能)等等 ⒊封包检测:将游戏数据封包进行校验,防止利用封包漏洞实现违规操作,例如之前的穿X火线强...

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

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

     

    ⒉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检测出来了。

     

     

     

     

     

     

     

     

     

     

     

    展开全文
  • CRC检验原理

    2012-10-13 12:02:00
    CRC检验原理实际上就是在一个p位二进制数据序列之后附加一个r位二进制检验码(序列),从而构成一个总长为n=p+r位的二进制序列;附加在数据序列之后的这个检验码与数据序列的内容之间存在着某种特定的关系。如果因...

    介绍1:

    一、基本原理

    CRC检验原理实际上就是在一个p位二进制数据序列之后附加一个r位二进制检验码(序列),从而构成一个总长为n=p+r位的二进制序列;附加在数据序列之后的这个检验码与数据序列的内容之间存在着某种特定的关系。如果因干扰等原因使数据序列中的某一位或某些位发生错误,这种特定关系就会被破坏。因此,通过检查这一关系,就可以实现对数据正确性的检验。

    二、几个基本概念

    1、帧检验序列FCS(Frame Check Sequence):为了进行差错检验而添加的冗余码。

    2、多项式模2运行:实际上是按位异或(Exclusive OR)运算,即相同为0,相异为1,也就是不考虑进位、借位的二进制加减运算。如:10011011 + 11001010 = 01010001。

    3、生成多项式(generator polynomial):当进行CRC检验时,发送方与接收方需要事先约定一个除数,即生成多项式,一般记作G(x)。生成多项式的最高位与最低位必须是1。常用的CRC码的生成多项式有:

    CRC8=X8+X5+X4+1

    CRC-CCITT=X16+X12+X5+1

    CRC16=X16+X15+X5+1

    CRC12=X12+X11+X3+X2+1

    CRC32=X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+1

    每一个生成多项式都可以与一个代码相对应,如CRC8对应代码:100110001。

    三、CRC检验码的计算

    设信息字段为K位,校验字段为R位,则码字长度为N(N=K+R)。设双方事先约定了一个R次多项式g(x),则CRC码:

    V(x)=A(x)g(x)=xRm(x)+r(x)

    其中: m(x)为K次信息多项式, r(x)为R-1次校验多项式。

    这里r(x)对应的代码即为冗余码,加在原信息字段后即形成CRC码。

    r(x)的计算方法为:在K位信息字段的后面添加R个0,再除以g(x)对应的代码序列,得到的余数即为r(x)对应的代码(应为R-1位;若不足,而在高位补0)。

    计算示例

    设需要发送的信息为M = 1010001101,产生多项式对应的代码为P = 110101,R=5。在M后加5个0,然后对P做模2除法运算,得余数r(x)对应的代码:01110。故实际需要发送的数据是101000110101110。

    图片

    四、错误检测

    当接收方收到数据后,用收到的数据对P(事先约定的)进行模2除法,若余数为0,则认为数据传输无差错;若余数不为0,则认为数据传输出现了错误,由于不知道错误发生在什么地方,因而不能进行自动纠正,一般的做法是丢弃接收的数据。

    五、几点说明:

    1、CRC是一种常用的检错码,并不能用于自动纠错。

    2、只要经过严格的挑选,并使用位数足够多的除数 P,那么出现检测不到的差错的概率就很小很小。

    3、仅用循环冗余检验 CRC 差错检测技术只能做到无差错接受(只是非常近似的认为是无差错的),并不能保证可靠传输。

    介绍2:

    1、循环校验码(CRC码):是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。

    2、生成CRC码的基本原理:任意一个由二进制位串组成的代码都可以和一个系数仅为‘0’和‘1’取值的多项式一一对应。例如:代码1010111对应的多项式为x6+x4+x2+x+1,而多项式为x5+x3+x2+x+1对应的代码101111。

    3、CRC码集选择的原则若设码字长度为N,信息字段为K位,校验字段为R位(N=K+R),则对于CRC码集中的任一码字,存在且仅存在一个R次多项式g(x),使得

    V(x)=A(x)g(x)=xRm(x)+r(x);

    其中:<wbr><wbr><wbr> m(x)为K次信息多项式, r(x)为R-1次校验多项式,</wbr></wbr></wbr>

    <wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> g(x)称为生成多项式:</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>

    g(x)=g0+g1x+ g2x2+...+g(R-1)x(R-1)+gRxR

    发送方通过指定的g(x)产生CRC码字,接收方则通过该g(x)来验证收到的CRC码字。

    4、CRC校验码软件生成方法:

    <wbr><wbr><wbr> 借助于多项式除法,其余数为校验字段。</wbr></wbr></wbr>

    例如:信息字段代码为: 1011001;对应m(x)=x6+x4+x3+1<wbr></wbr>

    <wbr><wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr></wbr> 假设生成多项式为:g(x)=x4+x3+1;则对应g(x)的代码为: 11001

    <wbr><wbr><wbr><wbr><wbr> x<sup><span style="font-size:12px">4</span></sup>m(x)=x<sup><span style="font-size:12px">10</span></sup>+x<sup><span style="font-size:12px">8</span></sup>+x<sup><span style="font-size:12px">7</span></sup>+x<sup><span style="font-size:12px">4</span></sup> 对应的代码记为:10110010000</wbr></wbr></wbr></wbr></wbr>

    采用多项式除法:<wbr> 得余数为: 1010<wbr><wbr><wbr><wbr> (即校验字段为:1010)</wbr></wbr></wbr></wbr></wbr>

    发送方:发出的传输字段为:<wbr><strong>1 0 1 1 0 0 1 <span style="color:#ff0000">1 0 10</span></strong></wbr>

    <wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr> 信息字段<wbr><wbr><wbr><wbr><wbr><wbr><span style="color:#ff0000"> 校验字段</span></wbr></wbr></wbr></wbr></wbr></wbr>

    接收方:使用相同的生成码进行校验:接收到的字段/生成码(二进制除法)如果能够除尽,则正确,

    展开全文
  • CRC软件加密保护中的应用 CRC(CyclicRedundancyCheck,直译:循环冗余校验)技术是一项很成熟的技术,在众多领域有广泛的应用,在数据存储和通信传输应用中处处都可以看到它的身影。最常用的CRC校验形式有CRC...

    ​CRC 在软件加密保护中的应用

    CRC(CyclicRedundancyCheck,直译:循环冗余校验)技术是一项很成熟的技术,在众多领域有广泛的应用,在数据存储和通信传输应用中处处都可以看到它的身影。最常用的CRC校验形式有CRC-16,CRC-32两种形式,采用CRC-16校验,可以保证在1014 位码元中只含有一位未被检测出的错误,采用CRC-32校验的出错概率比CRC-16还低105 倍。CRC的主要特点就是:检错能力极强,开销很小,易于实现。从性能和开销上综合考虑,其远远优于奇偶校验及算术和校验等方式。因此,很多软件在加密保护时都将CRC技术应用其中。本文拟从CRC校验的原理解剖入手,用实际代码和应用给大家解析CRC校验在软件加密中的实际应用,希望能给您的软件加密保护提供一些帮助和建议。

    CRC 校验的原理解析

    在实际应用中,根据环境和需求的变化,CRC形成了多种变形方式。比如:通讯协议X.25的帧检错序列采用的是CRC-CCITT方式,ARJ、LHA、ZIP等压缩软件采用的是CRC-32方式,磁盘驱动器的读写采用的是CRC-16方式,GIF、TIFF等图像存储格式也使用CRC作为检错技术。

    目前,比较流行的CRC形式主要是:CRC-16(CRC-CCITT)、CRC-32两种,CRC-4、CRC-8、CRC-12等形式的应用比较少见。其实,虽然有这么多种变形方式,但其原理是完全相同的,只是在实现上有一点变化而已,下面我们就对其原理进行一番解剖,希求通透。
    CRC的算法本质是(模-2)除法的余数运算,使用的除数不同,CRC的类型也就不一样。怎么样,不好理解吧?没关系,我们继续讲解:CRC的算法其实是采用了多项式编码的方法,您可以将要被处理的数据块M看成一个n阶的二进制多项式,其形式如下:

    http://bbs.pediy.com/upload/2005/4/image/pdf.gif

    a 是对应的阶数(位数)的值;
    x是对应的“模(进制)”数,由于我们处理的都是二进制数,所以x就是2 了。(模-2)的意思现在您明白了吧?
    下面我们用一个数进行解释吧:
    有一个二进制数M=10010101,其对应的多项式就可以表示为:

    http://bbs.pediy.com/upload/2005/4/image/pdf3.gif

    CRC校验就是基于这种多项式进行的运算,其乘除法运算过程与普通代数多项式的乘除法相同,其加减法运算以2为模,加减时不进(借)位,实际上与逻辑异或(XOR)运算是一致的。
    通常,根据多项表达(运算)式的不同,就形成了不同的CRC形式,以下是各种常用的多项表达(运算)式:

    http://bbs.pediy.com/upload/2005/4/image/pdf1.gif

    这些多项表达式的值就是(模-2)除法的除数,只要能确定使用哪一种多项式(也就是对应除数),您就可以很简单的获取CRC检验码了。下面就给您介绍CRC检验码的计算过程(看起来麻烦,其实简单):

    1、先确定您要使用的CRC校验形式,以此确定对应除数(用G来表示)和选定阶数(用r来表示)。(如果选择CRC-4的话,r就等于4,选择CRC-16话,r就等于16,以此类推。)
    2、在待处理的数据块M'后附加上r个0。假设原始数据块的长度是m位的话,附加之后的长度就变成m+r位了,我们用M来代表附加后的值。
    3、用第一步选择的生成多项式的值(即对应除数G)来除第二步附加0后生成的值(M),循环计算,一直到余数的阶数小于等于r-1,这时所得到的余数(用Y表示)就是原始数据M'经过所选择的CRC校验形式所生成的CRC校验码。

    ●如果您想将生成的校验码与原始数据进行复合,只需要用第二步生成的(M)以模2的方法减去得到的CRC校验码(Y),所得到的值就是包含了CRC校验码的数据串M''。(不过在

    软件加密过程中可能用不到这一步)。
    怎么样,很简单吧,只需要三步,就可以得到CRC 的校验码。还不明白?举个例子吧:
    设原始数据M'=1100110100
    选择CRC-4的形式,则G=24+2+1=19=10011(二进制)
    r =G 的二进制位数减1=5-1=4
    对原始数据M'进行处理,在其尾部附加r个0,即:
    M=M'+0000=11001101000000
    再用G 循环除M:
    其实校验码生成的过程就是一个循环移位的运算,位与位之间就是异或(XOR)运算。

    ◆一个数据的校验过程是这样的,如果有大量数据(比如说一个可执行程序或一个压缩包)将如何进行校验呢?其实很简单,只要将一个文件看成一个被一些数字分割的很长的位字串就可以了,只是这个位字串比较TA而已,你只要按标准的方式对这个比较长的位字串进行(模-2)除法运算,就一定会得到一个余数---CRC校验码,而这个校验码就是这个文件的CRC校验值。


    CRC 校验的代码实现


    好了,理论上的准备是很多了,现在要用进入实践了。下面,我们将给您提供一段很简单而实用的代码,用来实现CRC-32校验,最终,我会用这段代码实现软件加密保护。
    大家可以看到,上面生成CRC校验码的过程中,使用了大量的位运算和逻辑操作。而我想告诉大家的是,基于位运算的算法是非常慢的而且效率很低。因此,在实际使用中不推荐使用“计算法”来生成CRC校验码,而建议使用“查表法”来进行CRC校验码计算。查表法又是什么方法呢?这里我不做过多的分析,简单的说,它是利用预先计算出的标准码表(对

    应不同的校验形式有不同的码表,见附表1、2),用简单的移位和XOR操作,快速计算出CRC校验码的方法。具体的算法就是:

    (1)将上次计算出的CRC校验码右移一个字节;
    (2)将移出的这个字节与新的要校验的字节进行XOR 运算;
    (3)用运算出的值在预先生成码表中进行索引,获取对应的值(称为余式);
    (4)用获取的值与第(1)步右移后的值进行XOR 运算;
    (5)如果要校验的数据已经处理完,则第(4)步的结果就是最终的CRC校验码。如果还有数据要进行处理,则再转到第(1)步运行。

    看上面的过程是十分简单的,不好理解的可能是“预先生成的码表”。其实这个码表就是2^8 的数组,为什么是8次方呢?因为我们是用字节来进行运算的,而一个字节是8位,所以就是2的8次方了。因此这个码表就是拥有256值的数组,对应的每个值实际上就是0-255以对应的CRC多项表达式(见原理分析)为权的CRC码。如CRC-16的多项表达式就是
    http://bbs.pediy.com/upload/2005/4/image/pdf4.gif ,CRC-32的多项表达式就是:
    http://bbs.pediy.com/upload/2005/4/image/pdf5.gif

    附表1、2中分别给出了对应两种形式的码表(汇编格式),您只要复制到您的代码中即可使用(可能要做一些修饰)。

    如果您不想将这么一大堆码表复制到您的代码中,也可以使用动态生成码表(不过是给256个数字进行CRC计算而已)。下面是生成CRC-32码表的代码(c语言):

    //--------------------------------------
    //GenCrc32Tbl函数动态生成CRC-32的预置码表
    //Code:Chenji
    //--------------------------------------
    unsignedintCRC.//在Windows下编程,int的大小是32位
    unsignedintCRC_32_Tbl[256].//用来保存码表

    voidGenCrc32Tbl()
    {
    for(inti=0.i<256.++i){//用++i以提高效率
    CRC=i;
    for(intj=0.j<8.++j)
    {//这个循环实际上就是用"计算法"来求取CRC的校验码
    if(CRC&1)
    CRC=(CRC>>1)^0xEDB88320;
    else //0xEDB88320就是CRC-32多项表达式的值
    CRC>>=1;
    }
    CRC_32_Tbl[i]=CRC.
    }
    }
    //-------------------------------------------------

    ●上面的代码其实就已经实现了用“计算法”求取CRC校验码的过程,只要做些修改就可以完全实现。您只要将上面的代码复制到程序中,并调用GenCrc32Tbl函数,就可以在CRC_32_Tbl中生成CRC-32的预置码表。有了码表,用“查表法”计算CRC-32计算校验码就易如反掌了。根据上面介绍的算法,用C语言只需要一行就可以实现。

    CRC32=CRC_32_Tbl[(CRC32^((unsigned__int8*)p)[i])&0xff]^(CRC32>>8);
    怎么样?简单吧。

    下面是完整的一个实现函数,更加简单:

    //--------------------------------------------
    //CalcCRC32函数计算出给定数据串的CRC-32校验码
    //Code : Chenji
    //--------------------------------------------
    unsigned int CalcCRC32(void *DataBuff,unsigned int BufLen)
    {//DataBuff是指向数据串的指针,BufLen是数据串的长度
    unsigned int CRC32=0xffffffff; //设置初始值

    for(unsigned long i=0; i<BufLen; ++i)
    CRC32 = CRC_32_Tbl[(CRC32^((unsigned __int8 *)DataBuff)[i]) & 0xff] ^ (CRC32>>8);
    //如果你的编译器不支持unsigned __int8定义,请试用unsigned char
    return CRC32;
    }
    //-----------------------------------------------------


    怎么样,用查表法计算CRC校验码是不是很简单,很快捷?您只要将上面的代码复制您的程序中,赋与对应的参数,就可以实现CRC-32校验了。还等什么,马上开始现实之旅。


    CRC 校验在软件加密保护中的攻与防

    上面用大篇幅介绍CRC的原理与实现,都是为现在的实战打基础,现在我们就要用实战来校验了。
    大家已经知道,CRC校验生成的结果只是一个Long型的整数,市面上一些软件是如何将这个整数应用在软件加密保护中呢?这里我给大家介绍两种常用的方式:
    1、是对程序自身的进行保护。首先对原始可执行程序进行CRC校验,同时保存校验结果(可以保存在注册表、配置文件或可执行程序本身)。在程序运行时,对程序自身进行CRC校验,并将运算出的结果与保存的原始结果进行比较,如果不相同,就说明程序已经被修改(最有可能是被破解或被病毒感染)。即使只有1Bit的修改,都会被CRC检查出来,所以用CRC做自校验相当有效。


    2、用CRC校验算法,对注册名和注册码进行变形运算和判断,以此做为注册保护和授权的手段。
    这两种方式在软件保护上的运用十分广泛。可以说,每一种软件加壳(加密)保护软件(如upx,Aspack,FSG等)都使用了CRC进行自身校验保护。
    为了证明CRC在软件加密保护上的效果,我制作了一套测试用例,大家可以在http://www.xxx.com上下载CRCTest.rar压缩包,按本文进行测试和分析。
    压缩包中有两个可执行程序:crctest.exe和Makecrc.exe。其中crctest.exe就是我们要进行分析的对象,界面如下:

    软件已经进行了CRC外壳校验保护,同时,使用CRC-32算法做注册码校验,可以说将CRC在软件加密保护上的应用全部发挥出来了。
    MakeCrc.exe是配套工具,用来给上面的程序注入CRC保护码和计算注册码。
    现在,可以打开crctest.exe 文件,并随意输入注册名和注册码,看一看!
    您也可以用16进制编辑器(如:Hiew,010Editor,RTA等),将crctest.exe的最后一个字节00修改成0F保存修改后,再运行程序,程序会提示被修改。

    怎么样,这就是CRC保护的效果。如果您试图强行暴破来完成注册的话,就必须修改原始文件,但是软件将会在自校验时发现自己被修改了,然后自动退出。除非您得到正确的注册码或注册算法,而软件使用的注册算法也是由CRC算法变形实现的。如果在不知道具体算法的情况,想要强行暴破是比较麻烦的,这就是CRC的威力。市面上大多数软件大多是这样做的,毕竟谁也不想自己的软件被人破解或修改,难道您不这么认为吗?
    但是现在,我们就要挑战这个难题,在不了解注册算法的情况,如何实现强行暴破,彻底攻破CRC 的保护。这可能是您最希望了解的,还等什么,开始吧!

    首先,您要准备一些工具:Ollydbg1.10、DeDe、Peid全能插件版,也许还需要PE-tools1.50。这些软件您可以在网上很轻松的找到,如果没有可以与我联系。

    第一步:检查

    Peid是目前最流行,也是比较完善的检测软件。可以检测软件是否加壳,使用了什么编译器等诸多信息,同时其丰富的插件可以完成许多扩展功能。现在,我们先用Peid检测crctest.exe,查看程序的基本信息。Peid显示软件是用“BorlandC++1999”版的编译器进行编译的,其实一般情况下,用BCB编译的程序也会显示为用“BorlandC++1999”编译。

    我们再用其中的插件“KryptoANALyzer”,来分析程序中是否有通用的加密算法。我们可以看到,程序使用了CRC-32 算法:

    ◆这里想告诉大家的是,KryptoANALyzer是使用查询数组(码表)来确定软件使用了什么算法,而软件使用动态生成数组(码表)的话,它是无法检测出算法来的。呵呵,这也是

    它的漏洞了。你可以程序中保存一个其它算法的码表来混淆检测器。(crctest.exe中就定义了一个CRC32的数组,但我们并没有使用它,而是使用了动态生成的码表)

    第二步:分析

    了解软件没有加壳,而且可能是由BCB编译的之后,我们就要着手分析了。针对Borland公司出品的Delphi和BCB编译器所生成执行程序,可以使用DeDe反编译器进行分析,它可以很好的恢复程序的原始代码信息。
    下面就是用DeDe将crctest.exe载入分析,现在我们切换到“过程”页面,选择“main”单元:btn_OKClick事件是我们感兴趣的地方,当按下“注册”按钮时,这个事件会被调用。

    双击这个事件,我们就可以看到这个事件的汇编代码,在其中显示的汇编代码已经被DeDe 处理过,对标准的函数调用已经进行了注释,其可读性很好。00401C90这个地址就是这个事件函数的入口点,如果您有一些基本功,可以认真分析一下。您也许可以看出关键的代码。不过,下面我们要进入动态调试了!

    第三步:调试破解

    在检测和分析的基础上,我们可以开始动态调试了。我要用动态的数据来解释破解的思路与过程。现在,请打开Ollydbg动态调试器,将crctest.exe载入,停在程序的入口处。
    按Ctrl+G,输入00401C90,直接定位到“注册”按钮的点击事件函数入口处,并按F2下断点。
    接下来,可以按F9运行程序,进入调试,然后在窗口中,随便输入注册名和注册码,点击“注册”按钮,程序将会中断在00401C90处:不断按F8单步运行,其间您可以看到许多的

    数据在变化,不用管它,一直按F8运行,直到显示注册错误的信息框,再看运行的状态。
    可以看到,在运行00401FDF这个地址的时候,软件显示了注册错误的信息框。显然这个call00468C08指令就是显示信息框的函数。我们只要找到调用这个
    Call的调用(有点绕舌),就可以找到关键点了。大家向上回溯代码可以看到下面的内容:我们将汇编代码提取出来如下:

    ===========================

    /*401F65*/ lea edx,[local.2]
    /*401F68*/ lea eax,[local.4]
    /*401F6B*/ call crctest.00468DA0 // 对比注册码是否正确
    /*401F70*/ test al, al
    /*401F72*/ je shortcrctest.00401FC7//如果不正确就跳走
    /*401F74*/ mov eax,dwordptrds:[46EF94]
    /*401F79*/ push 40040
    /*401F7E*/ lea ecx,dwordptrds:[edi+141]
    /*401F84*/ lea edx,dwordptrds:[edi+EB]
    /*401F8A*/ mov eax,dwordptrds:[eax]
    /*401F8C*/ call crctest.00468C08 // 显示成功注册的提示信息
    /*401F91*/ mov wordptrds:[ebx+10],8C

    /*401F97*/ lea edx,dwordptrds:[edi+146]
    /*401F9D*/ lea eax,[local.14]
    /*401FA0*/ call crctest.00468C18
    /*401FA5*/ inc dwordptrds:[ebx+1C]
    /*401FA8*/ mov edx,dwordptrds:[eax]
    /*401FAA*/ mov eax,dwordptrds:[esi+2F8]
    /*401FB0*/ call crctest.00452658
    /*401FB5*/ dec dwordptrds:[ebx+1C]
    /*401FB8*/ lea eax,[local.14]
    /*401FBB*/ mov edx, 2
    /*401FC0*/ call crctest.00468CD0
    /*401FC5*/ jmp shortcrctest.00401FE4
    /*401FC7*/ mov eax,dwordptrds:[46EF94]//跳转到这里
    /*401FCC*/ push 40010
    /*401FD1*/ lea ecx,dwordptrds:[edi+1B4]
    /*401FD7*/ lea edx,dwordptrds:[edi+16A]
    /*401FDD*/ mov eax,dwordptrds:[eax]
    /*401FDF*/ call crctest.00468C08 // 显示错误注册的提示信息

    ===========================
    由此可以看到软件的注册检查是很简单的,只要将00401F72 处的代码:
    jeshortcrctest.00401FC7
    修改为:
    nopnop
    就可以暴破了!大家可以在Ollydbg中将00401F72处的代码修改成下面的形式:

    然后,取消所有的断点,直接按F9运行程序,再随意输入注册名和注册码,点击“注册”。看到了吗?

    软件已经成功注册了!但是真的成功了吗?不要高兴的太早,还有CRC自校验没有解决呢!请先将修改过的程序保存为另一个文件crctest_1.exe。
    ●方法:在汇编代码上点右键,选择“复制到可执行程序”--“所有改动”,再选择“全部复制”打开新的窗口。在新的窗口中点右键,选择“保存文件”,输入文件名就可以保存。
    现在,请暂时关闭ollydbg,运行新保存的文件crctest_1.exe。怎么样,没有成功吧!软件发现自己被修改了。目前,我们只完成了注册码校验的暴破,还没有解决CRC 的校验保护,这才是我们的重头戏,而这其实很简单。马上动手!
    再次打开ollydbg,这次就要载入crctest_1.exe了,因为它已经暴破了注册校验的部分。在开始之前,我们要分析一下思路:软件要进行自校验,就一定要读文件到内存中,我们

    只要找到读文件的函数,就可以顺藤摸瓜找到校验的核心部分了。好,在ollydbg中按ctrl+n打开函数导入导出表,找到ReadFile函数。在ReadFile这一行上点右键,选择“在每个

    参考上设置断点”,状态条上显示有六个断点被设置。不管它了,按F9开始运行!很快软件就被断下来:


    大家不用花时间在这些汇编代码上,我们的目标是关键跳转点。一直按F8返回到上级调用:

    最终我们会返回到00401A8B 这个地址,而在其上、下方有两个调用:
    /*401A86*/ call crctest_.00401B8C //计算当前的CRC校验码
    /*401A8B*/ mov esi,eax
    /*401A8D*/ mov eax,ebx
    /*401A8F*/ call crctest_.00401AA0 //读取原始的CRC校验码

    这两个调用分别返回当前的CRC校验码和原始的CRC校验码,具体过程大家可以进入其中进行分析,这里不做详解。接下来,继续按F8,直到返回到更上级的调用(建议按Alt+B,关闭所有中断):

    经过三次返回,我们终于看到了关键点:
    /*40193E*/ call crctest_.00401A80 // 这个调用进行自校验
    /*401943*/ test al, al // 检查校验的结果
    /*401945*/ jnz shortcrctest_.0040196F//如果通过就跳走
    /*401947*/ mov eax,dwordptrds:[46EF94]
    /*40194C*/ push 40010
    /*401951*/ mov ecx,crctest_.0046A5E0
    /*401956*/ mov edx,crctest_.0046A5BC
    /*40195B*/ mov eax,dwordptrds:[eax]
    /*40195D*/ call crctest_.00468C08
    /*401962*/ mov edx,dwordptrds:[46EF94]
    /*401968*/ mov eax,dwordptrds:[edx]
    /*40196A*/ call crctest_.004488FC
    /*40196F*/ mov edx,[local.10]//通过以后,就跳到这里
    /*401972*/ mov dwordptrfs:[0],edx
    /*401979*/ mov eax,[local.1]
    /*40197C*/ test bl, bl
    /*40197E*/ je shortcrctest_.00401985
    /*401980*/ call crctest_.00468F61
    /*401985*/ pop esi
    /*401986*/ pop ebx
    /*401987*/ mov esp,ebp
    /*401989*/ pop ebp
    /*40198A*/ retn

    很显然,我们只要将00401945 处的代码:
    jnzshortcrctest_.0040196F
    修改为:jmpshortcrctest_.0040196F//强行跳转
    就可以强制为自校验通过的状态。好了,接下来的保存工作就不用我多说了。最后,再用Keymake软件制作出破解补丁就可以完成注册了!软件包中就保存了破解补丁

    crctest_patch.exe,大家只要运行就可以看到效果了!
    OK,到目前为止,我为您制作的CRC保护实际已经被完全破解了,整个过程比较?嗦,只是力求详尽。在看过这一部分后,您应该对破解CRC保护的软件有了感性和理性的认识。
    (注:原文链接http://bbs.pediy.com/showthread.php?t=17195

    展开全文
  • CRC检测

    2021-06-27 19:25:43
    进一步熟悉和掌握VerilogHDL的基本语法,利用已学习的知识来完成CRC代码的设计,并通过仿真验证掌握开发软件的使用方法。 2.课程设计题目描述和要求 CRC即循环冗余校验码(CyclicRedundancyCheck),是数据通信领域中...

    1.设计目的
    进一步熟悉和掌握 Verilog HDL的基本语法,利用已学习的知识来完成CRC代码的设计,并通过仿真验证掌握开发软件的使用方法。
    2.课程设计题目描述和要求
    CRC即循环冗余校验码(Cyclic Redundancy Check),是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。本设计中采用的是串行数据接收并添加 CRC 校验位,要求能够正确完成数据的接收和并行输出,并能够在有效数据之后添加CRC校验位,能够正确地发送和接收数据。
    3. 设计思想和过程
    在设计CRC代码时首先要掌握CRC的基本原理。接收方和发送方事先有一个约定,也就是一串二进制数,在整个传输过程中,这个数始终保持不变。在发送方,利用生成多项式对信息多项式做模2除生成校验码。在接收方利用生成多项式对收到的编码多项式做模2除检测。整个算法应满足以下条件。
    (1)生成多项式的最高位和最低位必须为1。
    (2)当被传送信息(CRC码)任何一位发生错误时,被生成多项式做除后应该使余数不为0。
    (3)不同位发生错误时,应该使余数不同。
    在做除法的时候,CRC的除法使用的是模2的减法,最后实现的实际效果就是两个值的异或,按照除法的顺序完成余数的计算,但做除法中的减法步骤时使用异或操作就可以得到最后的结果。
    代码:

    odule cre( data send,ready_ s,data out, resend,data in,reset,data receive,ready r,clk,err);

    parameter width=1, amount-12;

    output [width* amount+4:0] data_ send;

    output ready s;

    output [width-1:0] data out;output resend;//resend-重发信 号输出高电平有效input [width-1:0]data_ in;

    width.input reset;input [width* amount+4:0] data_ receive;

    input ready_ r;

    input err;

    input clk;

    crc_ send sendl (data_ send, ready_ s,data in,reset,clk);

    erc_ receive receivel (data _out, resend, data send, ready_ r,clk,err);

    endmodulemodule erc_ send(data_ send, ready_ s,data in,reset,clk);

    parameter width=1, amount-12;

    output [width*amount+4:0] data send;

    output ready s;input [width1:0] data in;

    input reset,clk;

    reg [width* amount+4:0] data send;

    reg ready s;

    reg [width* amount:0] buf_ in;

    reg lwidth* amount+4:0] buf data s;integer n,i;

    begin

    if (reset)n=0;elseif(n

    buf_in=buf_in<

    buf_in[width1:0]=data_in;n=n+1;

    end

    else

    begin

    buf in=buf_in<

    buf_in[width1:0]=data_in;

    buf_data_s[width*amount+4:5]=buf_in;

    if(buf_in[11])buf_in[11:6]=buf_in[11:6]^6'b110101;

    if(buf_in[10])buf_in[10:5]=buf_in[10:5]^6'b110101;

    if(buf_in[9])buf_in[9:4]=buf_in[9:4]^6'b110101;

    if(buf_in[8])buf_in[8:3]=buf_in[8:3]^6'b110101;

    if(buf_in[7])buf_in[7:2]=buf_in[7:2]^6'b110101;

    if(buf_in[6])buf_in[6:1]=buf_in[6:1]^6'b110101;

    if(buf_in[5])buf_in[5:0]=buf_in[5:0]^6'b110101;

    buf_data_s[4:0]=buf_in[4:0];

    data_send[width*amount+4:0]=buf_data_s[width*amount+4:0];

    n=0;

    ready_s<=1;endendendmodulemodule crc_receive(data_out,resend,data_receive,ready_r,clk,err);

    parameter width=1,amount=12;

    output [width1:0]  data_out;

    output resend;input[width*amount+4:0] data_ receive;

    input ready_r,clk,err;

    beginif (reset)n=0;

    else

    if(n

    buf_in=buf_in<

    n=n+1;

    end

    else

    begin

    buf in=buf_in<

    buf_in[width1:0]=data_in;

    buf_data_s[width*amount+4:5]=buf_in;

    if(buf_in[11])buf_in[11:6]=buf_in[11:6]^6'b110101;

    if(buf_in[10])buf_in[10:5]=buf_in[10:5]^6'b110101;

    if(buf_in[9])buf_in[9:4]=buf_in[9:4]^6'b110101;

    if(buf_in[8])buf_in[8:3]=buf_in[8:3]^6'b110101;

    if(buf_in[7])buf_in[7:2]=buf_in[7:2]^6'b110101;

    if(buf_in[6])buf_in[6:1]=buf_in[6:1]^6'b110101;

    if(buf_in[5])buf_in[5:0]=buf_in[5:0]^6'b110101;

    buf_data_s[4:0]=buf_in[4:0];

    data_send[width*amount+4:0]=buf_data_s[width*amount+4:0];

    n=0;

    ready_s<=1;endendendmodulemodule crc_receive(data_out,resend,data_receive,ready_r,clk,err);

    parameter width=1,amount=12;output [width1:0]  data_out;

    output resend;

    input[width*amount+4:0] data_ receive;

    input ready_r,clk,err;reg [width1:0] data_out;reg resend;

    reg [width*amount+4:0] buf_receive;

    reg [width*amount:0] buf_data_r;

    reg right;

    integer m;

    always @(posedge clk)

    begin 

    if(ready_r)beginbuf_receive=data_receive;

    if(err)buf_receive=data_receive;

    if(err)buf_receive[16]=~buf_receive[16];

    buf_data_r[width*amount:0]=buf_receive[width*amount+4:5];

    if(buf_data_r[11])buf_data_r[11:6]=buf_data_r[11:6]^6'b110101;

    if(buf_data_r[10])buf_data_r[10:5]=buf_data_r[10:5]^6'b110101;

    if(buf_data_r[9])buf_data_r[9:4]=buf_data_r[9:4]^6'b110101;

    if(buf_data_r[8])buf_data_r[8:3]=buf_data_r[8:3]^6'b110101;

    if(buf_data_r[7])buf_data_r[7:2]=buf_data_r[7:2]^6'b110101;

    if(buf_data_r[6])buf_data_r[6:1]=buf_data_r[6:1]^6'b110101;

    if(buf_data_r[5])buf_data_r[5:0]=buf_data_r[5:0]^6'b110101;if(!(buf_data_r[4:0]^buf_receive[4:0]))beginright=1;

    resend=0;data_out=buf_receive[16];

    buf_receive=buf_receive<

    endelsebeginright=0;

    resend=1;

    data_out='bz;

    end

    end

    else if(right)

    beginif(m

    module crc_test;

    reg data_in,rest,clk,err;

    reg [15:0] shift;

    wire [16:0] data_send;

    wire ready;

    always #50 clk=~clk;

    initial

    begin

    clk=1;

    err=0;

    shift=16'h8000;

    reset=0;#10 reset=1;

    #20 reset=0;#9600 err=1;

    #100 err=0;

    #500000 $stop;

    endalways @(posedge clk)begindata_in=shift[0];

    shift=shift>>1;

    shift[15]=shift[14]^shift[11];

    if(!shift([15:12]);

    shift[15:12]=4'b1000;

    endcrc_send send(data_send,ready,data_in,reset,clk);

    crc_receive receive(data_out,resend,data_send,ready,clk,err);

    endmodule

    截图:

    视频链接:https://b23.tv/OBAwZK

    展开全文
  • 这样软件就可以利用这些校验信息来检测传输过程中是否出现了错误(在绝大多数情况下都有效)。在此后的一周里你天天去泡图书馆(在没有加班费的空闲时间),借了最厚的通信书籍查阅有关错误校验的知识。 Finally ...
  • CRC16检验小工具 1.1

    2014-05-24 10:04:21
    解压后,打开CRC16这个文件名,CRC16检验小工具 1.1。
  • STM32的CRC检验函数

    千次阅读 2018-06-10 12:19:49
    crc_cfg.h" //---CRC32表 const UINT32_T crc32Tab[256] = { 0x00000000,0x04C11DB7,0x09823B6E,0x0D4326D9,0x130476DC,0x17C56B6B,0x1A864DB2,0x1E475005, 0x2608EDB8,0x22C9F00F,0x2F8AD6D6,0x2B4BC.....
  • 汇总搜索的CRC校验相关的博客文章,从中收益,记录下来方便以后查阅。 关于STM32F4xx的硬件CRC32校验 STM32的硬件CRC stm32学习之CRC-32校验 STM32F10x 学习笔记3(CRC计算单元) CRC8校验 CRC8算法
  • CRC

    2018-10-18 23:22:15
    定义:CRC是一种根据网络数据包或者电脑文件等数据产生简短固定位数校验码的一种散列函数,主要用来检测或校验数据传输或者保存后可能出现的错误。它是利用除法及余数的原理来作错误侦测。 在数据存储和数据通讯...
  • 单片机CRC8检验C语言实现

    万次阅读 2017-11-17 14:47:38
    CRC校验类型:CRC8/MAXIM 多项式:X8+X5+X4+1 Poly:0011 0001 0x31 高位放到后面就变成 1000 1100 0xc8 C现实代码: unsigned char crc8_chk_value(unsigned char *message, unsigned char len) {  uint8 crc;  ...
  • 界面化操作软件,可以进行8/16/24/32位循环冗余校验,支持查表计算和按位计算,支持生成查找表。注意待校验数据是按照msb的次序输入,即bit7先计算,bit0最后计算。
  • MD5 sha1 crc32 检验工具

    2010-07-09 13:05:00
    最实用的提取 MD5 sha1 crc32工具 鉴别软件的纯洁性
  • 一款带CRC计算的串口调试软件

    热门讨论 2011-10-29 21:16:16
    11、 有效的检测通讯错误,避免软件死机(如USB转串口设备拔出检测); 12、 数据接收窗口及文件发送均采用多线程设计。 13、 带有文件和数据帧ModebusCRC16校验、CRC16校验、累加和校验、异或校验,ModebusLRC计算...
  • crc8查表法校验程序和校验检查软件

    热门讨论 2012-08-03 20:25:07
    crc8校验的原理,程序和检验软件 CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通信领域中最常用的一种差错校验码,其特征是信息字段和校验字段的长度可以任意选定。 CRC校验可以简单地描述为:例如...
  • crc

    2012-12-02 17:51:45
    1 、循环校验码( CRC 码): 是数据通信领域中最常用的一种差错校验码,其特 征是信息字段和校验字段的长度可以任意选定。 2 、生成 CRC 码的基本原理: 任意一个由二进制位串组成的代码都可以和一个系 数仅为 ...
  • 通过对不同校验方法的分析,介绍了一种适合PC机与8031单片机通讯差错校验的CRC方法并给出了其实现的软件流程图。
  • 硬件CRC循环冗余检验实验 CRC 是(Cyclic Redundancy Check) 的缩写意思是循环冗余校验CRC 循环冗余校验 技术主要应用于核实数据远程传输或者数据存储的正确性和完整性神舟系列开发板使用的 STM32 芯片都内置了一个...
  • 平常开发使用到数据通信的时候,我们常常会进行数据检验。而循环冗余检验CRC)是最简单且常用的一种了。为此对该模块进行了封装,方便使用。
  • 关于十六进制数据的CRC16校验码自写软件安装包十六进制数据的CRC16校验码自写软件链接与图片全部代码 十六进制数据的CRC16校验码自写软件 这里分享一个自己写的简单软件,是使用VS-2019,C#编程,最后打包成安装包...
  • CRC32

    2018-12-26 14:52:31
    检错能力极强,开销小,易于用编码器及检测电路实现。从其检错能力来看,它所不能发现的错误的几率仅为0.0047%以下。从性能上和开销上考虑,均远远优于奇偶校验及算术和校验等方式。因而,在数据存储和数据通讯领域...
  • 循环冗余检验CRC

    千次阅读 2016-11-19 16:23:39
    在嵌入式软件开发中,经常要用到CRC 算法对各种数据进行校验。因此,掌握基本的CRC算法应是嵌入式程序员的基本技能。可是,我认识的嵌入式程序员中能真正掌握CRC算法的人却很少,平常在项目中见到的CRC的代码多数都...
  • 基友大傻串口调试工具开发的源码,采用c#语言编写,带CRC校验功能。
  • CRC8/CRC16/CRC32最全总结

    千次阅读 2020-07-08 23:08:58
    循环冗余校验(英语:Cyclic redundancy check,通称“CRC”)是一种根据网络数据包或电脑文件等数据产生简短固定位数校验码的一种散列函数,主要用来检测或校验数据传输或者保存后可能出现的错误。 Wikipedia 一...
  • CRC16

    2021-08-02 15:26:32
    CRC选择 当数据帧长度在8bits-128bits范围内时,推荐CRC-8(CRC-8能够减少额外比特的开销,且有更好的性能表现) 当数据帧长度在128bits-2048bits范围内时,推荐CRC-12,CRC-16,CRC-CCITT(CRC-12额外比特的开销更小...
  • CRC 校验

    千次阅读 2018-04-09 12:28:49
    上篇RocketMQ(二):RPC通讯介绍了rocketmq的一些rpc细节,其实这些内容不仅仅是rocketmq内容,任何通信模块基本都是类似的,这块内容是高度公用的,今天我们来看看 CRC 校验,也是通信模块里面常常使用到的技术。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 16,439
精华内容 6,575
关键字:

crc检验软件