crackme下载:http://www.pediy.com/tutorial/chap6/Exercise/section01/chap6-1-1-01.zip
声明:只是写给和我一样的新人看的,希望看完能有所启发,大家一起学习,共同提高
第一次写破文,如有不明之处,还请指正
第一步:peid查壳
没有壳,进行下一步工作
第二步:试运行一下
随便输入,点check,意料之中,出错了
第三步:OD载入
右键-->字符串参考-->查找ASCII码
在bad serial, sorry!上双击跟随
00401122 B9 08000000 mov ecx,8
00401127 BE 44304000 mov esi,crackme.00403044
0040112C BF 08304000 mov edi,crackme.00403008
00401131 8A06 mov al,byte ptr ds:[esi]
00401133 3A07 cmp al,byte ptr ds:[edi]
00401135 75 1D jnz short crackme.00401154
00401137 46 inc esi
00401138 47 inc edi
00401139 ^ E2 F6 loopd short crackme.00401131
0040113B 6A 40 push 40
0040113D 68 35304000 push crackme.00403035 ; crackme 1.0
00401142 68 10304000 push crackme.00403010 ; good work cracker
00401147 FF35 54304000 push dword ptr ds:[403054]
0040114D E8 3C000000 call <jmp.&USER32.MessageBoxA>
00401152 EB 17 jmp short crackme.0040116B
00401154 6A 30 push 30
00401156 68 35304000 push crackme.00403035 ; crackme 1.0
0040115B 68 22304000 push crackme.00403022 ; bad serial, sorry!
00401160 FF35 54304000 push dword ptr ds:[403054]
00401166 E8 23000000 call <jmp.&USER32.MessageBoxA>
这一行00401135 75 1D jnz short crackme.00401154
就是关键跳转了,只要将这里的jnz改为je就可以爆破成功,但是我们的目的是找出注册码,所以继续……
我们来到这一段的段头处004010C9 56 push esi
F2下断,F9运行,注册框又弹出来了,随便输一个,123456789(事实上通过分析我们知道注册码的长度应为8),check
好了,断下来了
004010C9 56 push esi
004010CA 57 push edi
004010CB 51 push ecx
004010CC 33F6 xor esi,esi
004010CE 33FF xor edi,edi
004010D0 B9 08000000 mov ecx,8 ; 长度为8
004010D5 BE 44304000 mov esi,crackme.00403044 ; ASCII "123456789"
004010DA 8036 32 xor byte ptr ds:[esi],32 ; 将esi,即我们输入的假码的每一位与32异或,结果存入esi指向的地址00403044中
004010DD 46 inc esi ;esi每次+1
004010DE ^ E2 FA loopd short crackme.004010DA ; 循环8次
在这一段中,我们的假码已经送入00403044这个地址里,ASCII "123456789"的16进制即为31 32 33 34 35 36 37 38 39,其每一位与32(即ASCII"2")异或,则00403044处的值由我们原先的假码变为异或后的03 00 01 06 07 04 05 0A 39,由于只取8位(mov ecx,8),最后一位的39并未参与运算。
这里简要说一下异或运算,即换算成二进制,按位比较,不同的位置1,相同的位置0
1 XOR 0 = 1
0 XOR 1 = 1
1 XOR 1 = 0
13 XOR 124
0 0 0 0 1 1 0 1 (13)
0 1 1 1 1 1 0 0 (124)
----------------
0 1 1 1 0 0 0 1 (113)
所以xor esi,esi 也就是将esi清零的意思。
这里我们的计算就可以借助系统自带的计算器,附件-->计算器-->查看-->科学型,记得选择十六进制哦。好了,接着分析……
004010E0 BE 44304000 mov esi,crackme.00403044 ; 注意00403044处的值已改为异或后的,不再是我们输入的假码了
004010E5 B9 04000000 mov ecx,4 ; 长度为8
004010EA 8A06 mov al,byte ptr ds:[esi] ; esi的第一字节送入al
004010EC 8A5E 01 mov bl,byte ptr ds:[esi+1] ; 第二字节送入bl
004010EF 32C3 xor al,bl ; 异或,并将结果送入al
004010F1 8887 4C304000 mov byte ptr ds:[edi+40304C],al ; 将al中的值送入edi+40304C中
004010F7 83C6 02 add esi,2 ; esi+2,为的是继续取后面的值以进行运算
004010FA 47 inc edi
004010FB ^ E2 ED loopd short crackme.004010EA ; 循环4次
这一段的主要作用是将我们前一段得到的值再次处理,即将原长度为8的异或后的假码(这里设为M1),第1、2字节异或,第3、4字节异或,依此类推,得到长度为4的值(03 07 03 0F,这里设为M2),送入0040304C这个地址中。
004010FD BE 4C304000 mov esi,crackme.0040304C ; 0040304C处的值送入esi,即经过再次处理的假码
00401102 8A06 mov al,byte ptr ds:[esi]
00401104 8A5E 01 mov bl,byte ptr ds:[esi+1]
00401107 32C3 xor al,bl ;esi的1、2位异或,结果送入al
00401109 8A5E 02 mov bl,byte ptr ds:[esi+2]
0040110C 8A4E 03 mov cl,byte ptr ds:[esi+3]
0040110F 32D9 xor bl,cl ;esi的3、4位异或,结果送入bl
00401111 32C3 xor al,bl ;al和bl异或,结果送入al
这一段的作用是将经过再次处理的假码03 07 03 0F,两两异或直到得出最终的值(08)存入al
(这里设为m,可以看到此时eax=00000008,因al就是指eax的最后两位)
00401113 B9 08000000 mov ecx,8 ; 长度为8
00401118 BE 44304000 mov esi,crackme.00403044 ; 00403044处存的是经过第一次处理的假码
0040111D 3006 xor byte ptr ds:[esi],al ; 每位与刚刚得到的al值异或
0040111F 46 inc esi
00401120 ^ E2 FB loopd short crackme.0040111D ; 循环8次
这一段的作用是将第一次处理后的假码即M1,其每一位与al即m异或,得到的值(0B 08 09 0E 0F 0C 0D 02,设为M3)存入00403044中。
00401122 B9 08000000 mov ecx,8 ;长度为8
00401127 BE 44304000 mov esi,crackme.00403044
0040112C BF 08304000 mov edi,crackme.00403008 ;00403008处的值送入edi
00401131 8A06 mov al,byte ptr ds:[esi] ;将esi的每个字节送入al中
00401133 3A07 cmp al,byte ptr ds:[edi] ;edi的每个字节与al比较,关键比较
00401135 75 1D jnz short crackme.00401154 ;这里就是关键跳转
……
00401154 6A 30 push 30
00401156 68 35304000 push crackme.00403035 ; crackme 1.0
0040115B 68 22304000 push crackme.00403022 ; bad serial, sorry!
00401160 FF35 54304000 push dword ptr ds:[403054]
00403008这个地址存的就是经过几次异或运算应得的值(设为Y),与00403044处的值比较,如果不等就会跳到00401154,弹出注册失败的对话框。
我们到00403008这里看看,OD中ctrl+G,输入该地址,回车
00403008 /71 18 jno short crackme.00403022
0040300A |59 pop ecx
0040300B |1B79 42 sbb edi,dword ptr ds:[ecx+42]
0040300E |45 inc ebp
0040300F |4C dec esp
那么正确的值应该就是71 18 59 1B 79 42 45 4C,也许你迫不及待地将这个值换算成ASCII码,以为这就是正确的注册码了。忘记了吗?这只是正确的注册码经过一系列运算之后得到的值,至于怎样得到真正的注册码,且听我细细道来……
从这里开始,我们就要涉及更多的xor异或运算了,不妨记住如下规律:
m xor 0 = m
m xor m = 0
X1 xor X2 xor X3 = X1 xor X3 xor X2 = (X1 xor X2) xor X3 ,即交换律和结合律
X1 xor X2 = m --> X1 = X2 xor m ,xor的逆运算就是它自己
(X1 xor m) xor (X2 xor m) =(X1 xor X2) xor (m xor m) = X1 xor X2
通过前面的分析,我们知道,当我们输入的假码超过8位时,程序只会取前8位,多余的不纳入运算(在本例中我们输入的最后一位"9",即16进制的39,其地址一开始为0040304C,但是经过第二次运算之后就被新的假码M2填充了)。那么少于8位时会怎么样,不妨假设我们输入的是"1234567"(即16进制的31 32 33 34 35 36 37),第一次异或运算后的结果是03 00 01 06 07 04 05 00(因为不足8位,因此第8次循环时结果为00),这与第8位为"2"的情况一样,所以可以认为不足8位时程序会自动用"2"补足。
好了,既然知道注册码为8位,设我们输入的注册码用16进制表示为X1,X2,X3,……,X8
则m={[(X1 xor 32) xor (X2 xor 32)] xor [(X3 xor 32) xor (X4 xor 32)] } xor { [(X5 xor 32) xor (X6 xor 32)] xor [(X7 xor 32) xor ( X8 xor 32 )] }
化简得m=X1 xor X2 xor X3 xor X4 xor X5 xor X6 xor X7 xor X8
同时有m xor (X1 xor 32)=71
m xor (X2 xor 32) =18
m xor (X3 xor 32) =59
m xor (X4 xor 32) =1B
m xor (X5 xor 32) =79
m xor (X6 xor 32) =42
m xor (X7 xor 32) =45
m xor (X8 xor 32) =4C
即m xor X1=71 xor 32=43
m xor X2=18 xor 32=2A
m xor X3=59 xor 32=6B
m xor X4=1B xor 32=29
m xor X5=79 xor 32=4B
m xor X6=42 xor 32=70
m xor X7=45 xor 32=77
m xor X8=4C xor 32=7E
8个式子异或得X1 xor X2 xor X3 xor X4 xor X5 xor X6 xor X7 xor X8=19
即m=19
则X1=43 xor 19=5A ;"Z"
X2=2A xor 19=33 ;"3"
X3=6B xor 19=72 ;"r"
X4=29 xor 19=30 ;"0"
X5=4B xor 19=52 ;"R"
X6=70 xor 19=69 ;"i"
X7=77 xor 19=6E ;"n"
X8=7E xor 19=67 ;"g"
OK,把我们的成果输入进去,bingo!
PS:今天突然发现原来http://www.pediy.com/tutorial/chap6/Chap6-1-11.htm#这里已经把答案给出来了,仔细对比了一下,发现参考答案最后反推注册码的做法更简单
我分析了一下这样做的原因:由于m xor X1=71 xor 32
m xor X2=18 xor 32
m xor X3=59 xor 32
m xor X4=1B xor 32
m xor X5=79 xor 32
m xor X6=42 xor 32
m xor X7=45 xor 32
m xor X8=4C xor 32
八个式子异或一下,就得到左边=X1 xor X2 xor X3 xor X4 xor X5 xor X6 xor X7 xor X8=m,
右边=(71 xor 32) xor (18 xor 32) xor (59 xor 32) xor (1B xor 32) xor (79 xor 32) xor (42 xor 32 xor (45 xor 32) xor (4C xor 32 )
即m=(71 xor 32) xor (18 xor 32) xor (59 xor 32) xor (1B xor 32) xor (79 xor 32) xor (42 xor 32 xor (45 xor 32) xor (4C xor 32 )
再看看这个m={[(X1 xor 32) xor (X2 xor 32)] xor [(X3 xor 32) xor (X4 xor 32)] } xor { [(X5 xor 32) xor (X6 xor 32)] xor [(X7 xor 32) xor ( X8 xor 32 )] }
这不就相当于将我们找到的经过处理的真码,按照我们输入的假码的处理方法,进行计算吗?
所以只要将71 18 59 1B 79 42 45 4C 两两异或,就像原X1 X2 X3 X4 X5 X6 X7 X8 那样处理就能得到正确的m了。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)