软文发稿公司,网站关键词优化seo,快手里做网站荣耀封面的视频,招商计划书模板pptCRC介绍 在玩某些游戏#xff0c;例如fps类游戏时#xff0c;你想要修改某些特定的数值实现一些功能#xff0c;这时你很有可能会被查封账号甚至禁封机器码。因为你更改了游戏中的数据#xff0c;从而导致接收方收到”错误的数据“。为尽量提高接收方收到数据的正确率…CRC介绍在玩某些游戏例如fps类游戏时你想要修改某些特定的数值实现一些功能这时你很有可能会被查封账号甚至禁封机器码。因为你更改了游戏中的数据从而导致接收方收到”错误的数据“。为尽量提高接收方收到数据的正确率在接收数据之前需要对数据进行差错检测这种检测就是我们所说的CRC检测。CRC也叫循环冗余校验码它属于密码学一类算法常用于数据校验一般会用来检测程序是否被脱壳或者被修改以达到防破解的目的。CRC运算实际上就是将数据k进行模2运算得到余数n然后将n拼接到k的后面生成kn为循环冗余校验码的字长。接着发送kn到接收方作为被除数进行模2运算判断余数是否为0如果余数非0则CRC检测出数据被修改了。简单点说就是把需要校验的数据与生成多项式进行循环异或处理。PS1.发送方和接受方会约定一个特定的除数它是一个定值我们也叫除数为生成多项式。2.在计算余数时被除数也就是数据k需要进行补0补0个数为生成多项式长度-1个0。3.余数长度一定与补零的长度一致流程图讲了这么多不如来个例子好理解例子1这里数据为1110101生成多项式为101那么我们要传给接收方的数据就为1110101数据10余数111010110这个就是CRC的计算原理了CRC计算的两种方式1.直接计算法这里我们通过例子来讲解例子2首先我们看到这里的生成项是1101然后在计算中的除数蓝色字体标记大多是1101而有时是0000当除数为1101时被除数的首位都是1而首位不为1时就是0000。那么我们不妨做个假设既然被除数和除数的首位为1时会被消掉那么我们就不需要四位异或了改成三位异或三位异或的话被除数一次就取三个而除数取后三个当被除数首位为1时就左移一位让新的三位与除数生成项的后三位进行异或当被除数移出位是0时就异或000然后不断重复此步骤直至结束。这里是针对本例题的当你的生成项为n时你就取n-1位异或那么就会有人问到底需要重复几次才算结束呢处理次数待处理数据位数被除数位数商的位数本题次数为6次例如本题第一次被除数取100左移一位得001然后与101异或得100。100左移一位得000然后与101异或得101。101左移一位得010然后与101异或得111。111左移一位得110然后与101异或得011。011左移一位得110然后与000异或得110与000异或值是不变的。110左移一位得100然后与101异或得001得到余数刚好6次。2.驱动表法驱动表法没有直接计算法得直观但是效率却比直接计算法要高那么如何实现呢我们知道直接计算法是一步一步从上往下来异或得到得结果在算得过程中会有异或许多生成项而生成项又是不变的那么是不是可以提前计算出与数据前几位符合的生成项之和然后再异或呢那么我们就将0000 0000 ~ 1111 1111这个范围的所有生成项计算出来存储为表格计算的时候取数据的首字节进行索引找到表中对应生成项异或的和与去掉首字节的数据进行异或就行了。表的形成终于过度到表了这里我们来用算法实现表让你清楚明白它的原理这里我们拿CRC32表的形成举例首先得了解一下CRC32的生成项是什么想要了解更多的CRC以及它的生成多项式可以去这里看http://www.ip33.com/crc.html#include windows.h #include stdio.h int main() { DWORD crc; for (DWORD i 0; i 256; i)//256个元素 { crc i; for (DWORD k 0; k 8; k)//因为这里异或是从数据的高位开始所以需要计算的数据左移8位这里就需要计算8次 { if (crc 1)//判断最高位是否为1 crc (crc 1) ^ 0xEDB88320;//最高位为1右移一位然后与0xEDB88320异或 else crc crc 1;//最高位为0时不用异或整体数据右移一位。相当于例子2中110与000异或值是不变的 } printf (0x%08x, , crc); if (((i1)%6) NULL ) printf (\n); } } /*CRC32表 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d */注意这里用红色标识的右移这里如果按照直接计算法来说不应该是要左移吗为什么又右移了呢注意看这个表的倒数第二个CRC32它的输入和输出都是需要进行反转的也就是相当于逆向我们就要将左移修改成右移当然还会有人问它的多项式不应该是0x04C11DB7吗怎么又变成了0xEDB88320了呢这是它是因为0xEDB88320是0x04C11DB7的反转。这个表的生成很简单一般是用的是0xEDB88320这个反转多项式假如用0x04C11DB7这个正常多项式则必须还要交换位显然会很麻烦。做一个CRC的检测程序相信大家差不多能够理解CRC实现的大概过程了前面主要是对CRC大致了解而我们真正需要深入了解的是CRC32。CRC32常用于游戏以及一些 ARJ、LHA等压缩工具软件那么接下来我们来写一个CRC32的检测程序。#include windows.h #include stdio.h DWORD crc32_table[256]; void CRC32_Table() { DWORD crc; //DWORD crc32_table[256]; for (int i 0; i 256; i) { crc i; for (DWORD k 0; k 8; k) { if (crc 1) crc (crc 1) ^ 0xEDB88320; else crc 1; } crc32_table[i] crc; //生成并存储CRC32数据表 } } //根据CRC32表计算CRC校验码 DWORD Check_CRC32(DWORD crc, PUCHAR Data, DWORD len) { crc 0xFFFFFFFF; //将CRC初始化为-1 CRC32_Table(); for (DWORD i 0; i len; i) { crc (crc 8) ^ crc32_table[(crc ^ Data[i]) 0xff]; } return ~crc;//输出的反转 } int main() { SetConsoleTitle(CRC32检测器); printf(开始检测); //初始内存校验值 DWORD Original_CRC32 Check_CRC32(0, (PUCHAR)0x400000, 0x112000); while (1) { //CRC循环校验实现实时检测 DWORD Cycle_CRC32 Check_CRC32(0, (PUCHAR)0x400000, 0x112000);//这里第二个参数是基址第三个个参数是一个校验的范围也就是程序主模块镜像大小。 if (Cycle_CRC32 ! Original_CRC32) { MessageBoxA(NULL, 已检测到您修改了代码, 警告, MB_YESNO); } //为了防止频繁弹出信息框这里使用的Sleep函数控制检测的周期每5s弹出一次 Sleep(5000); } getchar(); }这里初始化是因为待测数据的内容和长度是随机的如果寄存器初始值为 0那么待测字节是1字节的0x00与待测字节是 N 字节的 0x00计算出来的CRC32值都是0那 CRC 值就没有意义了所以寄存器用0xFFFFFFFF 进行初始化就可以避免这个问题了我这里的文件大小对应的是主模块镜像大小实践是否能成功这里我们用CE进行数据的修改这里我们先手动添加地址然后再将数值进行更改我这里是改成了11111然后过了5秒就弹出了警告。可以看出这个检测程序成功了当然有些有点基础的人会问CRC不是检测代码的吗为什么这里你修改的是数值也可以检测呢因为CRC是在代码段中进行操作实现的在内存中数据根代码没有实质性的区别