iawen 发表于 2007-12-29 16:20:47

CD/DVD Data Recovery V1.0.01281的算法分析

查壳,无!
OD载入,输入试炼码,有提示,查找参考字符………………
找到关键段的段首后,F8单步:
====================================================
0041A980/.55            push    ebp
0041A981|.8BEC          mov   ebp, esp
0041A983|.83EC 20       sub   esp, 20

………………
0041A999|.E8 F210FFFF   call    0040BA90//取用户名的长度
0041A99E|.83F8 02       cmp   eax, 2   ;用户名必须大于2位
0041A9A1|.7D 13         jge   short 0041A9B6
0041A9A3|.6A 00         push    0
0041A9A5|.6A 00         push    0
0041A9A7|.68 F8E34400   push    0044E3F8                         ;please input correct user name!


0041A9BC|.E8 CF10FFFF   call    0040BA90//取注册码的长度
0041A9C1|.83F8 08       cmp   eax, 8                           ;注册码必须>=8位
0041A9C4|.7D 13         jge   short 0041A9D9
0041A9C6|.6A 00         push    0
0041A9C8|.6A 00         push    0
0041A9CA|.68 18E44400   push    0044E418                         ;please input correct registration code!


0041A9D9|> \6A 00         push    0                              ; /Arg1 = 00000000
0041A9DB|.8B4D E0       mov   ecx, dword ptr           ; |
0041A9DE|.83C1 70       add   ecx, 70                        ; |
0041A9E1|.E8 0ACEFFFF   call    004177F0                         ; \F7进入,频繁调用,涉及算法
        //下面一大堆都是调用这个函数,呵呵,调用的形式如:
            int func1(int i,char* str)
            作用:取指定字符串中的i位的字符

*****************************
子函数:CALL 004177F0:
*****************************
004177F3|.51            push    ecx
        //
004177F4|.894D FC       mov   dword ptr , ecx
004177F7|.837D 08 00    cmp   dword ptr , 0
004177FB|.7C 0D         jl      short 0041780A
004177FD|.8B4D FC       mov   ecx, dword ptr
00417800|.E8 8B42FFFF   call    0040BA90
00417805|.3945 08       cmp   dword ptr , eax
00417808|.7E 0A         jle   short 00417814
0041780A|>68 57000780   push    80070057                  ; /Arg1 = 80070057
0041780F|.E8 5C36FFFF   call    0040AE70                  ; \CDDVDDR.0040AE70
00417814|>8B45 FC       mov   eax, dword ptr
00417817|.8B08          mov   ecx, dword ptr
00417819|.8B55 08       mov   edx, dword ptr
0041781C|.8A0411      mov   al, byte ptr

先是对用户名的前两位各取了两次:
0041A9D9|> \6A 00         push    0                              ; /Arg1 = 00000000
0041A9DB|.8B4D E0       mov   ecx, dword ptr           ; |
0041A9DE|.83C1 70       add   ecx, 70                        ; |
0041A9E1|.E8 0ACEFFFF   call    004177F0                         ; \CDDVDDR.004177F0
0041A9E6|.8845 EF       mov   byte ptr , al            ;取用户名的第1个字符
0041A9E9|.6A 01         push    1                              ; /Arg1 = 00000001
0041A9EB|.8B4D E0       mov   ecx, dword ptr           ; |
0041A9EE|.83C1 70       add   ecx, 70                        ; |
0041A9F1|.E8 FACDFFFF   call    004177F0                         ; \CDDVDDR.004177F0
0041A9F6|.8845 F8       mov   byte ptr , al             ;取用户名第2位
0041A9F9|.6A 00         push    0                              ; /Arg1 = 00000000
0041A9FB|.8B4D E0       mov   ecx, dword ptr           ; |
0041A9FE|.83C1 70       add   ecx, 70                        ; |
0041AA01|.E8 EACDFFFF   call    004177F0                         ; \CDDVDDR.004177F0
0041AA06|.8845 FF       mov   byte ptr , al
0041AA09|.6A 01         push    1                              ; /Arg1 = 00000001
0041AA0B|.8B4D E0       mov   ecx, dword ptr           ; |
0041AA0E|.83C1 70       add   ecx, 70                        ; |
0041AA11|.E8 DACDFFFF   call    004177F0                         ; \CDDVDDR.004177F0

然后分别对取出的4位进行运算:
0041AA19|.0FB645 EF   movzx   eax, byte ptr
0041AA1D|.83C8 43       or      eax, 43
0041AA20|.8845 EF       mov   byte ptr , al

只是其中的常量在改变,呵呵…………
换位表达如:
*******************************************************
第1位------->EAX------->EAX=EAX OR 43
AL------->
第2位------->ECX------->ECX=ECX OR 44
CL------->
第1位------->EDX------->EDX=EAX OR 52
DL------->
第2位------->EAX------->ECX=ECX OR 44
CL------->

继续对取出的4位计算,方式如:
0041AA41|.0FB645 EF   movzx   eax, byte ptr
0041AA45|.99            cdq
0041AA46|.B9 0A000000   mov   ecx, 0A
0041AA4B|.F7F9          idiv    ecx
0041AA4D|.8855 EF       mov   byte ptr , dl

其实也就是一个求余的运算,换位表达如下:
= MOD A
= MOD A
= MOD A
= MOD A

又是一个大循环:
0041AA7D|.C745 F0 00000>mov   dword ptr , 0
0041AA84|.C745 E8 00000>mov   dword ptr , 0            ;相当于计时器
0041AA8B|.EB 09         jmp   short 0041AA96
0041AA8D|>8B55 E8       /mov   edx, dword ptr
0041AA90|.83C2 01       |add   edx, 1
0041AA93|.8955 E8       |mov   dword ptr , edx
0041AA96|>8B4D E0      mov   ecx, dword ptr
0041AA99|.83C1 70       |add   ecx, 70
0041AA9C|.E8 EF0FFFFF   |call    0040BA90                        ;子函数,取用户名LEN
0041AAA1|.3945 E8       |cmp   dword ptr , eax
0041AAA4|.7D 1E         |jge   short 0041AAC4
0041AAA6|.8B45 E8       |mov   eax, dword ptr
0041AAA9|.50            |push    eax                           ; /Arg1
0041AAAA|.8B4D E0       |mov   ecx, dword ptr          ; |
0041AAAD|.83C1 70       |add   ecx, 70                         ; |
0041AAB0|.E8 3BCDFFFF   |call    004177F0                        ; \CDDVDDR.004177F0
0041AAB5|.8845 E7       |mov   byte ptr , al
0041AAB8|.0FB64D E7   |movzx   ecx, byte ptr
0041AABC|.034D F0       |add   ecx, dword ptr
0041AABF|.894D F0       |mov   dword ptr , ecx
0041AAC2|.^ EB C9         \jmp   short 0041AA8D                  ;用户名各位字符的ASCII累加到EBP-10
0041AAC4|>8B45 F0       mov   eax, dword ptr           ;将累加值送入EAX

这个更清晰了,就是累加用户名各位的字符的ASCII
换位表达如下:
total=0;
for(i=0;i<len(name);i++)
        total+=name
然后将total MOD A求余,值送往

接下来就是对注册码的判断了,看完了就会发现,其实上面做的一切就是“白搭”,呵呵
先假设一下,我们输入的注册码为code
0041AAD2|.6A 00         push    0                              ; /Arg1 = 00000000
0041AAD4|.8B4D E0       mov   ecx, dword ptr           ; |
0041AAD7|.83C1 74       add   ecx, 74                        ; |
0041AADA|.E8 11CDFFFF   call    004177F0                         ; \CDDVDDR.004177F0
0041AADF|.8845 FC       mov   byte ptr , al
……………………………………
0041AB42|.6A 07         push    7                              ; /Arg1 = 00000007
0041AB44|.8B4D E0       mov   ecx, dword ptr           ; |
0041AB47|.83C1 74       add   ecx, 74                        ; |
0041AB4A|.E8 A1CCFFFF   call    004177F0                         ; \CDDVDDR.004177F0
0041AB4F|.8845 FB       mov   byte ptr , al

上面一段取码行为的结果就是:
=code
=code
=code
=code

=code

=code
=code
=code

看了一大堆,其实只需要这一段就OK了,
0041AB52|.0FB655 EF   movzx   edx, byte ptr
0041AB56|.0FB645 FC   movzx   eax, byte ptr
0041AB5A|.83E8 30       sub   eax, 30
0041AB5D|.3BD0          cmp   edx, eax
0041AB5F|.75 3C         jnz   short 0041AB9D

希望你没有那么不幸,刚好此处的跳转没跳,那样你可能要多走一段弯路,不过那样的机率很小,/:013 。
我很幸运,跳转实现了,直接来到了下面这段代码:
==========================================================
0041ABA1|.83F8 39       cmp   eax, 39
0041ABA4|.0F85 A7000000 jnz   0041AC51
0041ABAA|.0FB64D FD   movzx   ecx, byte ptr
0041ABAE|.83F9 33       cmp   ecx, 33
0041ABB1|.0F85 9A000000 jnz   0041AC51
0041ABB7|.0FB655 F6   movzx   edx, byte ptr
0041ABBB|.83FA 30       cmp   edx, 30
0041ABBE|.0F85 8D000000 jnz   0041AC51
0041ABC4|.0FB645 F5   movzx   eax, byte ptr
0041ABC8|.83F8 31       cmp   eax, 31
0041ABCB|.0F85 80000000 jnz   0041AC51
0041ABD1|.0FB64D F9   movzx   ecx, byte ptr
0041ABD5|.83F9 36       cmp   ecx, 36
0041ABD8|.75 77         jnz   short 0041AC51
0041ABDA|.0FB655 F7   movzx   edx, byte ptr
0041ABDE|.83FA 36       cmp   edx, 36
0041ABE1|.75 6E         jnz   short 0041AC51
0041ABE3|.0FB645 FE   movzx   eax, byte ptr
0041ABE7|.83F8 36       cmp   eax, 36
0041ABEA|.75 65         jnz   short 0041AC51
0041ABEC|.0FB64D FB   movzx   ecx, byte ptr
0041ABF0|.83F9 36       cmp   ecx, 36
0041ABF3|.75 5C         jnz   short 0041AC51

========对照如下,只要符合下面的条件就OK了,花了半多个小时看前面,
========哎,……
========现在明白没有,
                code==39
                code=33
                code=30
                code=31
                code=36
                code=36
                code=36
                code=36

只要注册码满足下面的条件,就OK了,就这么简单,都不知道作者绕那么多弯弯是为什么???       
即:93016666****
另,注册码必须大于等于8位
程序运行界面如下:


附件为目标程序和算法跟踪过程:

[ 本帖最后由 iawen 于 2007-12-29 17:02 编辑 ]

网络断魂 发表于 2007-12-29 19:56:54

学习学习!!!!!!!!!

flyjmu 发表于 2007-12-31 00:13:25

先来研究一下软件 再来看楼主的破文 向楼主学习了
页: [1]
查看完整版本: CD/DVD Data Recovery V1.0.01281的算法分析