Initial value : FFFFFFFF Reflected : True XOR out with : FFFFFFFF
作为对你好奇心的奖励, 这里是CRC-16标准: :) Name : \Width : 16 Poly : 8005 Initial value : 0000 Reflected : True XOR out with : 0000
'XOR out with' 是为了最终得到CRC而用来与记存器最后结果做XOR运算的值. 假如你想了解一些关于'reversed'逆向CRC poly的话,请看我的参考文章.
我是在16位DOS模式下用的32位编码,因此你会在这个程序中看到很多32位与16位混合
的编码...当然这是很容易转换成纯32位编码的.注意这个程序是经过完整测试并且能够
正常运行的.下面的Java 和 C 代码都是由这个汇编代码而来的. 底下的这段程序就是用来计算CRC-32 table的: xor ebx, ebx ;ebx=0, 将被用做一个指针. InitTableLoop:
xor eax, eax ;eax=0 为计算新的entry. mov al, bl ;al<-bl
;生成入口. xor cx, cx entryLoop: test eax, 1 jz no_topbit shr eax, 1 xor eax, poly jmp entrygoon no_topbit:
shr eax, 1 entrygoon: inc cx test cx, 8 jz entryLoop
mov dword ptr[ebx*4 + crctable], eax inc bx test bx, 256 jz InitTableLoop
注释: - crctable 是一个包含256个dword的数组. - 由于使用反射算法,EAX被向右移. - 因此最低的8位被处理了. 用Java和C写的代码如下(int is 32 bit):
for (int bx=0; bx<256; bx++){ int eax=0;
eax=eax&0xFFFFFF00+bx&0xFF; // 就是 'mov al,bl' 指令 for (int cx=0; cx<8; cx++){ if (eax&&0x1) { eax>>=1; eax^=poly; }
else eax>>=1; }
crctable[bx]=eax; }
下面的汇编代码是用来计算CRC-32的: computeLoop: xor ebx, ebx xor al, [si] mov bl, al shr eax, 8
xor eax, dword ptr[4*ebx+crctable] inc si
loop computeLoop xor eax, 0FFFFFFFFh
注释: - ds:si 指向将要被处理的byte string信息流. - cx 信息流的长度. - eax 是当前的CRC.
- crctable是用来计算CRC的值表. - 此例中记存器的初始值为: FFFFFFFF.
- 要将中间值与FFFFFFFFh做XOR才能得到CRC 下面是Java和C写的代码: for (int cx=0; cx>=8; eax^=crcTable[ebx]; }
eax^=0xFFFFFFFF;
现在我们已经完成了本文的第一部分:CRC原理部分,所以如果你希望能够对CRC做更深
的研究,那么我建议你去读在本文最后给出连接上的资料,我读了.好了,终于到了本文最
有意思的部分,CRC的逆向分析!
------------------------------------------------------------------------------------ 第二部分 CRC的逆向分析:
我遇到了很多障碍,当我思考如何破解CRC时.我试图使用一些特殊顺序的字节使CRC无效.
但我没有做到...后来我意识到这种方法是行不同的,因为CRC内建了一些处理过程,
无论你
改变任何位它都不会出问题,真正的CRC就是在不断变化的,总是在变化的.找一些CRC程序,
你可以自己尝试一下.
现在我知道我只能'纠正'在CRC后面的那些我想改变的字节.所以我要构造一个字节序列,
它可以将CRC转化成任何我想要的样子!
具体实现这个想法
一个字节串? 01234567890123456789012345678901234567890123456789012
You want to change from ^ this byte to ^ this one. 就是位置9->26.
同时我们需要额外的4个字节用来在最后恢复原始字节串.
当你计算CRC-32时,从0-8都没有问题,直到第9位,修补过的字节串会使CRC发生根本的改变.
即使当走过了第26位,以后的字节都没有改变,你也不可能在得到原始的CRC了,不可能了!你读
过后面的段落时就会明白为什么.间而言之,当你修改一个字节串时,要保证CRC不变.
1. 计算并保存从1~9位的CRC.
2. 继续计算直到第27位还有额外的4字节并保存结果.
3. 用1的值来计算新的字节串和额外4字节的CRC(对应patch后的新的CRC值),