📄 chap6-2-4.htm.primary
字号:
<html>
<head>
<title>Crack Tutorial</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<link rel="stylesheet" href="style/css.css" type="text/css">
<link rel="stylesheet" href="../STYLE/Css.css" type="text/css">
</head>
<body bgcolor="white" text="#000000" link="#004080" vlink="#004080" background="../image/Back.gif">
<p><a href="../catalog.htm">目录</a>>>第6章</p>
<p align="center" class="shadow1Copy"><b class="p3">第6章 软件保护技术</b></p>
<table width="80%" border="0" cellspacing="0" cellpadding="3" align="center" bgcolor="#bcbcbc" bordercolor="#111111" class="shadow1">
<tr>
<td class="shadow1" width="25%">
<div align="center"><a href="Chap6-1.htm"><font color="#FFFFFF">第一节 常见保护技巧</font></a></div>
</td>
<td class="shadow1" width="25%">
<div align="center"><a href="Chap6-2.htm"><font color="#FFFFFF">第二节 反跟踪技术</font></a></div>
</td>
<td class="shadow1" width="25%">
<div align="center"><a href="Chap6-3.htm"><font color="#FFFFFF">第三节 加密算法</font></a></div>
</td>
<td class="shadow1" width="25%">
<div align="center"><a href="Chap6-4.htm"><font color="#FFFFFF">第四节 软件保护建议</font></a></div>
</td>
</tr>
</table>
<p align="center"><span class="p9"><b>第二节 反跟踪技术</b></span></p>
<table border="1" width="80%" cellpadding="5" bordercolor="#111111" bgcolor="#efefef" align="center" cellspacing="0">
<tr>
<td width="33%" valign="middle" align="center" class="p9" height="23">
<div align="left" class="p"><span class="p9"><span class="p9"> <span class="p9">1、<a href="Chap6-2-1.htm">Anti-Debug</a></span></span></span></div>
</td>
<td width="33%" valign="middle" align="center" class="p9" height="23">
<div align="left"><span class="p9"><span class="p9"> </span>2、<a href="Chap6-2-2.htm">Anti-静态分析</a></span></div>
</td>
<td width="34%" valign="top" class="p9" height="23">
<div align="left"><span class="p9"><span class="p9"> <font color="#000000"> </font></span>3、<a href="Chap6-2-3.htm">Anti-Dump</a><font color="#000000"></font></span></div>
</td>
</tr>
<tr>
<td width="33%" valign="middle" align="center" class="p9" height="23">
<div align="left"><span class="p9"><span class="p9"> </span>4、<a href="Chap6-2-4.htm">CRC简介</a></span></div>
</td>
<td width="33%" valign="middle" align="center" class="p9" height="23">
<div align="left"><span class="p9"><span class="p9"> <font color="#000000"> </font></span>5、<a href="Chap6-2-5.htm">SEH技术</a></span></div>
</td>
<td width="34%" valign="top" class="p9" height="23">
<div align="left"></div>
</td>
</tr>
</table>
<p align="center"><span class="p9"><span class="p9"><span class="p9"><b>4、CRC简介</b></span></span></span></p>
<blockquote>
<p> 主题 :CRC原理及其逆向分析方法. <br>
作者 : Anarchriz/DREAD.<br>
发布日期 :29 april 1999 (最后更改 30 april 1999).<br>
目的 :CRC 算法.<br>
使用工具 :QEdit 2.1 (The best!) &Wordpad & some CRC progs.<br>
figure :CRC教程与c001的CRC逆向分析方法. <br>
翻译:arbin </p>
</blockquote>
<p></p>
<blockquote>
<p><br>
CRC原理及其逆向破解方法:</p>
<p>介绍:</p>
<p> 这篇短文包含CRC原理介绍和其逆向分析方法,很多程序员和破解者不是很清楚了解<br>
CRC的工作原理,而且几乎没人知道如何逆向分析它的方法,事实上它是非常有用的.<br>
首先,这篇教程教你一般如何计算CRC,你可以将它用在数据代码保护中.第二,主要是<br>
介绍如何逆向分析CRC-32,你可以以此来分析程序中的CRC保护(象反病毒编码).当然<br>
有很多有效的工具用来对付CRC,但我怀疑它是否会说明原理.<br>
我要告诉你,这篇短文里中应用了很多数学知识,这不会影响一些人,而且会被一般的<br>
程序员与逆向分析者很好理解.为什么?那么如果你不知道数学是如何被应用在CRC中,<br>
我建议你可以停止继续学习了.所以我假定你们(读者)都是具备二进制算术知识的.</p>
<p>第一部分:CRC 介绍,CRC是什么和计算CRC的方法. </p>
<p><br>
循环冗余码 CRC</p>
<p> 我们都知道CRC.甚至你没有印象,但当你想到那些来自诸如RAR,ZIP等压缩软件发给你<br>
由于错误连接和其他一些意外原因导致的文件错误的恼人的消息时,你就会知道.CRC是块<br>
数据的计算值,比如对每一个文件进行压缩.在一个解压缩过程中,程序会从新计算解压文件<br>
的CRC值,并且将之与从文件中读取的CRC值进行比对,如果值相同,那么正确.在CRC-32中,<br>
会有1/2^32的可能性发生对确认数据更改的校验错误. <br>
很多人认为CRC就是循环冗余校验,假如CRC真的就是循环冗余校验,那么很多人都错用了<br>
这个术语.你不能说"这个程序的CRC是12345678".人们也常说某一个程序有CRC校验,而不<br>
说是 "循环冗余校验" 校验.结论:CRC 代表循环冗余码,而不是循环冗余校验. <br>
计算是如何完成的呢?好,主要的想法就是将一个文件看成一个被一些数字分割的很长的<br>
位字串,这里会有一个余数---CRC!你总会有一个余数(可以是0),它至多比除数小一.<br>
(9/3=3 余数=0 ; (9+2)/3=3 余数=2)<br>
(或者它本身就包含一个除数在其中). <br>
在这里CRC计算方法与除法有一点点区别,除法就是将被减数重复的减去除数X次,然后留下<br>
余数.如果你希望得到原值,那么你就要把除数乘上X次,然后加上余数.<br>
CRC计算使用特殊的减法与加法完成的.也就是一种新的"算法".计算中每一位计算的进位值<br>
被"遗忘"了. <br>
看如下两个例子,1是普通减法,2和3是特殊的.<br>
-+<br>
(1) 1101 (2) 1010 1010 (3) 0+0=0 0-0=0<br>
1010- 1111+ 1111- 0+1=1 *0-1=1<br>
---- ---- ---- 1+0=1 1-0=1<br>
0011 0101 0101 *1+1=0 1-1=0<br>
在(1)中,右数第二列可以看成是0-1=-1,因此要从高位借1,就变成(10+0)-1=1.(这就象普通<br>
的'by-paper'十进制减法).特例(2,3)中,1+1会有正常的结果10,'1'是计算后的进位.这个值<br>
被忽略了.特殊情况0-1应该有正常结果'-1'就要退到下一位.这个值也被忽略了.假如你对编程<br>
有一定了解,这就象,XOR 操作或者更好.<br>
现在来看一个除法的例子:</p>
<p>在普通算法中:<br>
1001/1111000\1101 13 9/120\13<br>
1001 - 09 -|<br>
---- -- |<br>
1100 30 |<br>
1001 - 27 -<br>
---- --<br>
0110 3 -> 余数<br>
0000 -<br>
----<br>
1100<br>
1001 -<br>
----<br>
011 -> 3, 余数</p>
<p>在CRC算法中:<br>
1001/1111000\1110 9/120\14 余数为 6<br>
1001 -<br>
----<br>
1100<br>
1001 -<br>
----<br>
1010<br>
1001 -<br>
----<br>
0110<br>
0000 -<br>
----<br>
110 -> 余数<br>
(例 3)</p>
<p> 这个除法的商并不重要,也没必要去记住,因为他们仅仅是一组无关紧要的位串.真正<br>
重要的是余数!它就是这个值,可以说比原文件还重要的值,他就是基本的CRC.</p>
<p><br>
过度到真正的CRC码计算.</p>
<p> 进行一个CRC计算我们需要选则一个除数,从现在起我们称之为"poly".宽度W就是最高位<br>
的位置,所以这个poly 1001的W 是3,而不是4.注意最高位总是1,当你选定一个宽度,那么你只<br>
需要选择低W各位的值. <br>
假如我们想计算一个位串的CRC码,我们想确定每一个位都被处理过,因此,我们要在目标<br>
位串后面加上W个0位.在此例中,我们假设位串为1111.请仔细分析下面一个例子:</p>
<p>Poly = 10011, 宽度 W=4<br>
位串 Bitstring <br>
Bitstring + W zeros = 110101101 + 0000</p>
<p>10011/1101011010000\110000101 (我们不关心此运算的商)<br>
10011|||||||| -<br>
-----||||||||<br>
10011|||||||<br>
10011||||||| -<br>
-----|||||||<br>
00001||||||<br>
00000|||||| -<br>
-----||||||<br>
00010|||||<br>
00000||||| -<br>
-----|||||<br>
00101||||<br>
00000|||| -<br>
-----||||<br>
01010|||<br>
00000||| -<br>
-----|||<br>
10100||<br>
10011|| -<br>
-----||<br>
01110|<br>
00000| -<br>
-----|<br>
11100<br>
10011 -<br>
-----<br>
1111 -> 余数 -> the CRC!<br>
(例 4)</p>
<p>重要两点声明如下:<br>
1.只有当Bitstring的最高位为1,我们才将它与poly做XOR运算,否则我们只是将<br>
Bitstring左移一位.<br>
2.XOR运算的结果就是被操作位串bitstring与低W位进行XOR运算,因为最高位总为0.</p>
<p>算法设计:</p>
<p> 你们都应知道基于位运算的算法是非常慢的而且效率低下.但如果将计算放在每一字节上<br>
进行,那么效率将大大提高.不过我们只能接受poly的宽度是8的倍数(一个字节;).可以形<br>
象的看成这样一个宽度为32的poly(W=32):</p>
<p> 3 2 1 0 byte<br>
+---+---+---+---+<br>
Pop! <--| | | | |<-- bitstring with W zero bits added, in this case
32<br>
+---+---+---+---+<br>
1<--- 32 bits ---> this is the poly, 4*8 bits</p>
<p>(figure 1)<br>
这是一个你用来存放暂时CRC结果的记存器,现在我称它为CRC记存器或者记存器.你从右<br>
至左移动位串,当从左边移出的位是1,则整个记存器被与poly的低W位进行XOR运算.(此例<br>
中为32).事实上,我们精确的完成了上面除法所做的事情.</p>
<p><br>
移动前记存器值为:10110100<br>
当从右边移入4位时,左边的高4位将被移出,此例中1011将被移出,而1101被移入.</p>
<p>情况如下:<br>
当前8位CRC记存器 : 01001101<br>
刚刚被移出的高4位 : 1011<br>
我们用此poly : 101011100, 宽度 W=8</p>
<p>现在我们用如前介绍的方法来计算记存器的新值.<br>
顶部 记存器<br>
---- --------<br>
1011 01001101 高四位和当前记存器值<br>
1010 11100 + (*1) Poly 放在顶部最高位进行XOR运算 (因为那里是1)<br>
-------------<br>
0001 10101101 运算结果</p>
<p>现在我们仍有一位1在高4位:<br>
0001 10101101 上一步结果<br>
1 01011100+ (*2) Poly 放在顶部的最低位进行XOR运算 (因为那里是1)<br>
-------------<br>
0000 11110001 第二步运算结果<br>
^^^^<br>
现在顶部所有位均为0,所以我们不需要在与poly进行XOR运算</p>
<p>你可以得到相同的结果如果你先将(*1)与(*2)做XOR然后将结果与记存器值做XOR.<br>
这就是标准XOR运算的特性:<br>
(a XOR b) XOR c = a XOR (b XOR c) 由此,推出如下的运算顺序也是正确的.</p>
<p>1010 11100 poly (*1) 放在顶部最高位<br>
1 01011100+ polys (*2) 放在顶部最低位<br>
-------------<br>
1011 10111100 (*3) XOR运算结果</p>
<p>The result (*3) 将(*3)与记存器的值做XOR运算<br>
1011 10111100<br>
1011 01001101+ 如右:<br>
-------------<br>
0000 11110001</p>
<p>你看到了吗?得到一样的结果!现在(*3)变的重要了,因为顶部为1010则(3)的值总是等于<br>
10111100(当然是在一定的条件之下)这意味着你可以预先计算出任意顶部位结合的XOR值.<br>
注意,顶部结果总是0,这就是组合XOR操作导致的结果.(翻译不准确,保留原文)</p>
<p> 现在我们回到figure 1,对每一个顶部字节的值都做移出操作,我们可以预先计算出一个值.<br>
此例中,它将是一个包含256个double word(32 bit)双字的表.(附录中CRC-32的表).<br>
(翻译不准确,保留原文) </p>
<p>用伪语言表示我们的算法如下: </p>
<p>While (byte string is not exhausted)<br>
Begin<br>
Top = top_byte of register ;<br>
Register = Register shifted 8 bits left ORred with a new byte from string
;<br>
Register = Register XORred by value from precomputedTable at position Top
;<br>
End</p>
<p>direct table算法:<br>
上面提到的算法可以被优化.字节串中的字节在被用到之前没有必要经过整个记村器.用<br>
这个新的算法,我们可以直接用一个字节去XOR一个字节串通过将此字节移出记存器.结果<br>
指向预先计算的表中的一个值,这个值是用来被记存器的值做XOR运算的. <br>
我不十分确切的知道为什么这会得到同样的结果(这需要了解XOR运算的特性),但是这又<br>
极为便利,因为你无须在你的字节串后填充0字节/位.(如果你知道原理,请告诉我:) <br>
让我们来实现这个算法: <br>
<br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -