打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
在 VS2008 下用 CRC32 算法实现程序自校验

老话题,程序自校验。不过放在 VS2008 下,情况又发生了变化。

 

作为软件开发者,我们一般不希望程序出来之后被人非法修改,比如破解或冠以 xxx 版等称谓,所以都会跟反调试反跟踪作斗争,当然,提到反跟踪作斗争,就像矛与盾,这个话题永远是无止境的,较量也是无止境的。再怎么想方设法保护程序,总有被 cracker 攻破的时候,只是时间的问题。当然我们也不能觉得既然这样那保护不保护也就无所谓了,就像我们明知道人生总有尽头,但不是会立即去报到一样:)

呵呵,婆婆妈妈这么多,意思只有一个,条件允许的话,还是适当的加上一些保护未必就是坏事。至于软件保护,可能稍微懂点的人立马会想到一个字,壳。是的,好的壳能给 cracker 增加不少的难度,那也是很大的话题,一般壳都具有自校验的功能,那我们可以尝试一下自己来实现这个小功能,而常用的自校验算法莫过于 CRC32 了,因为它加密之后的长度正好符合某些特定结构的长度。

之所以单独记下来作为备忘,是因为不同于以往 ASM 或者 VC6.0 等编译的程序,情况发生了些不痛不痒的变化,影响到最终方案的实施了。

读这篇文章,假设您已经知道了 CRC32 的基本概念,正在尝试实现程序自校验功能的开发者。我分成了下面几个部分:

 

一、不得不提的 CRC32 码表的生成:

查表法计算 CRC32 值是最快的。通常,您也可以保留一大段的 0xXXXXXXXX 等静态码表在程序里面,这并没有错,也完全可以。但是,PEid 等,具有一些插件,可以依据特征码来判定程序所使用的算法,所以在程序里面保留大段的静态码表会提前暴露身份,因此最好采用动态生成的方法。一个经典的动态码表的生成代码如下所示:

  1. void CXCrc32::GenerateCrc32Table()  
  2. {  
  3.     ::SecureZeroMemory(&arCrc32Table, 256 * sizeof(DWORD));  
  4.     for (int i = 0; i < 256; i++)  
  5.     {  
  6.         DWORD dwTempCrc = i;  
  7.         for (int j = 0; j < 8; j++)  
  8.         {  
  9.             dwTempCrc = (dwTempCrc & 1) ? (dwTempCrc >> 1) ^ 0xEDB88320 : dwTempCrc >> 1;  
  10.         }  
  11.         arCrc32Table[i] = dwTempCrc;  
  12.     }  
  13. }  

这里的 arCrc32Table 就是我们要使用的 CRC32 码表,您最好放在类里面,在构造函数里面调用,这样后续的加密等就有了依据的表了。

 

二、加密字符串和文件,计算过程很简单,按 BYTE 进行,代码也很少:

  1. DWORD CXCrc32::CalculateBufferCrc(const LPBYTE pbtBuffer, DWORD& dwSize)  
  2. {  
  3.     ASSERT(dwSize >= 0);  
  4.     LPBYTE pbtTempBuffer = pbtBuffer;  
  5.     DWORD dwTempCrc = 0xFFFFFFFF;  
  6.     while (dwSize--)  
  7.     {  
  8.         dwTempCrc = ((dwTempCrc >> 8) & 0x00FFFFFF) ^ arCrc32Table[(dwTempCrc ^ (*pbtTempBuffer)) & 0xFF];  
  9.         pbtTempBuffer++;  
  10.     }  
  11.     return dwTempCrc ^ 0xFFFFFFFF;  
  12. }  

 

三、了解一下 PE 文件结构是很有必要的:



 

四、生成文件的 CRC32 值后,写入文件,这是最头疼的问题,这就是前面所说的变化:

以往通常都是保存在 IMAGE_OPTIONAL_HEADER.Win32VersionValue 中,因为这是一个保留值,没有使用,其长度 DWORD 正好符合 CRC32 加密之后的长度, 4 个字节。所以他是一个理想的存储位置。

但是,在 VS2008 + XP Sp3 下(Vista 下我没有测试),情况很不同了:似乎这个所谓的保留值不再是保留值了,虽然编译器编译出来默认仍然是 0,我们仍然可以修改,但是对大小已经有了严格的限制,DWORD 值大小不能超过 5 !!

这一点就浪费了我不少的时间,一开始以为老办法仍然可行,没想到双击修改 Win32VersionValue 后的程序根本没反应,就跟没运行一样,而且,这样的东西根本没办法调试,所以只好一点一点试,然后拿 PE 工具查看 PE 头信息。最后测试发现不能超过 5,那实在是一件很沮丧的事,因为一旦 cracker 知道你是使用 CRC 来做自校验(比如我在第一点里面提到的静态码表),这个地方他肯定会关注,枚举不超过 5 次程序就被破了,那也太让他们扫兴了。

在网上搜索了一下,发现有人写的博客有:http://hi.baidu.com/zuikee/blog/item/738e7fd1286d9ad4562c8452.html,但是很可惜,这个值在 VS2008 下根本不管用,9.0 的 VC 运行库似乎就卯定了 0-5 了,哎,愁啊!

 

于是另想办法

查找 MSDN 关于 PE 的说明

http://msdn.microsoft.com/en-us/library/ms680339(VS.85).aspx

发现有个成员被标记为 obsolete,大喜,That's it! 就是他了,你不要了我正好需要,呵呵

于是编译、写入文件,测试,一切 OK:

 

五、单纯的 FileSize 是不可靠的,不是说不行,因为 cracker 也可以计算现在文件的 CRC32 值,回写过去,那就又挂了,所以计算最终需要写入的 CRC32 值的时候,可以加上一些特殊信息,比如,你的生日,女朋友的手机号等等,当然你在程序里面校验文件是够被修改的时候,也是需要加入同样的特殊信息的。

 

六、也可以把这个 CRC32 值也在自身 exe 文件末尾或者另外挂个 dll,但,似乎都没与这种方案妥当。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
CRC校验码在单片机中的程序实现的求取
[原创]CRC技术的实现与破解(10.21更新)
S7-200 CRC校验程序
Modbus CRC校验程序
CRC32校验算法C语言版(查表法)
一个简单的算法Crackme
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服