首页
社区
课程
招聘
[原创]一个简单的crackme算法分析,破解笔记第一弹
发表于: 2010-1-27 17:42 7225

[原创]一个简单的crackme算法分析,破解笔记第一弹

2010-1-27 17:42
7225

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期)

上传的附件:
收藏
免费 7
支持
分享
最新回复 (29)
雪    币: 189
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
算了,自己写的自己顶
2010-1-27 21:41
0
雪    币: 135
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
异或操作看似简单其实是最实用的加密算法了,真会把人搞晕的噻。
2010-1-28 09:01
0
雪    币: 189
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
我花了一天时间,参考了很多资料,才把这个搞懂的
2010-1-28 19:34
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
把你的那个crackme发上来哦。
2010-1-28 20:17
0
雪    币: 189
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
一开始就给了链接了啊,其实是看雪首页解密教学第六章第一节的习题
2010-1-28 20:26
0
雪    币: 85
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
o 值得学习啊,顶个
2010-1-28 20:44
0
雪    币: 172
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
看了教种只会暴破,那个异或的算法还是搞不懂
2010-1-29 17:48
0
雪    币: 189
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
因为有好几个循环,所以分析起来会比较吃力,异或就像这样

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)

先将13和124都换算成二进制,然后逐位进行比较,相同的那一位结果就是0,不同的就是1,这样就得到了一个新的二进制值,再换算成十进制就是113了
2010-1-29 19:00
0
雪    币: 51
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
这个不错 适合新手学习
2010-1-30 09:39
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
11
小算盘可以算 XOR
2010-1-30 10:47
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
学习
2010-1-30 11:23
0
雪    币: 6
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
向你学习,很强
2010-1-30 11:57
0
雪    币: 136
活跃值: (1465)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
14
很好..不错...厉害了...
2010-2-4 19:46
0
雪    币: 52
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
厉害厉害   支持楼主~!
2010-2-8 14:35
0
雪    币: 103
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
ASCII "123456789"的16进制即为31 32 33 34 35 36 37 38 39,这个是怎么算出来的?
2010-2-9 12:50
0
雪    币: 103
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
这种算法还算简单啊,看来我的路还很长!!
2010-2-9 12:58
0
雪    币: 10
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
天哪 这要是注册码长一点岂不是要花上好长时间
2010-2-10 16:26
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
哇  楼主厉害  学习。。。。。
2010-2-10 18:15
0
雪    币: 23
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
很好,学习了。
2010-2-10 22:21
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
很受启发啊,我是新手,就需要这样的贴子
2010-2-11 11:55
0
雪    币: 6790
活跃值: (4441)
能力值: (RANK:600 )
在线值:
发帖
回帖
粉丝
22
羡慕得到邀请码,支持顶一下,菜鸟我还要继续呀!
2010-2-11 14:39
0
雪    币: 189
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
23
http://www.pediy.com/tutorial/appen-a/append-A.htm
可以到这里看
2010-2-11 22:42
0
雪    币: 30
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
学习 学习
2010-2-12 11:58
0
雪    币: 105
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
恩~LZ已经开始有成果了·····
恭喜恭喜····
2010-2-13 01:15
0
游客
登录 | 注册 方可回帖
返回
//