【破文标题】光驱伴侣的注册算法分析及简单的分析一下程序
【破文作者】小娃崽[DFCG]
【作者邮箱】wanzailuan@yahoo.com.cn
【作者主页】
【破解工具】OD
【破解平台】XP+SP2
【软件名称】光驱伴侣V1.2
【软件大小】68.0 KB 
【原版下载】不记得了
【保护方式】序列号
【软件简介】无
------------------------------------------------------------------------
<pre>
004045BC   .  68 0C934000   push    0040930C                          ; /IniFileName = "C:\Doc
004045C1   .  8D4424 0C     lea     eax, dword ptr [esp+C]            ; |
004045C5   .  6A 15         push    15                                ; |BufSize = 15 (21.)
004045C7   .  50            push    eax                               ; |ReturnBuffer
004045C8   .  68 10944000   push    00409410                          ; |Default = ""
004045CD   .  68 28914000   push    00409128                          ; |licensecode
004045D2   .  68 20914000   push    00409120                          ; |license
004045D7   .  FF15 54604000 call    dword ptr [<&KERNEL32.GetPrivateP>; \GetPrivateProfileStringA
//取得当前目录下CDPartner.ini中[License]
//LicenseCode的内容
004045DD   .  8D4C24 08     lea     ecx, dword ptr [esp+8]
004045E1   .  51            push    ecx                               ; /Arg1=LicenseCode的内容
004045E2   .  8D4C24 08     lea     ecx, dword ptr [esp+8]            ; |
004045E6   .  E8 95F5FFFF   call    00403B80                          ; \cdpartne.00403B80
//关键的call,跟进
004045EB   .  85C0          test    eax, eax
004045ED   .  75 07         jnz     short 004045F6                     //爆破点

跟进关键call
00403B80  /$  83EC 18       sub     esp, 18
00403B83  |.  8D4424 00     lea     eax, dword ptr [esp]
00403B87  |.  53            push    ebx
00403B88  |.  55            push    ebp
00403B89  |.  56            push    esi
00403B8A  |.  57            push    edi
00403B8B  |.  50            push    eax
00403B8C  |.  E8 2FFFFFFF   call    00403AC0
00403B91  |.  8B7C24 2C     mov     edi, dword ptr [esp+2C]          ;  注册码到EDI
00403B95  |.  57            push    edi                              ; /String
00403B96  |.  FF15 64604000 call    dword ptr [<&KERNEL32.lstrlenA>] ; \lstrlenA
00403B9C  |.  83F8 14       cmp     eax, 14                          ;  注册码要等于14(20)位
00403B9F      0F85 AB000000 jnz     00403C50
00403BA5  |.  8A07          mov     al, byte ptr [edi]               ;  注册码第1位到al
00403BA7  |.  3C 44         cmp     al, 44                           
//注册码第一位等于D吗?
00403BA9  |.  75 04         jnz     short 00403BAF
//不等跳到 00403BAF
00403BAB  |.  33ED          xor     ebp, ebp
//等于的话EBP清零                         
00403BAD  |.  EB 23         jmp     short 00403BD2
//然后跳到00403BD2
00403BAF  |>  3C 39         cmp     al, 39
//第一位不等于D跳到这里比较是不是等于9
00403BB1  |.  75 07         jnz     short 00403BBA
//不等于跳到00403BBA
00403BB3  |.  BD 01000000   mov     ebp, 1   
//等于的话EBP置1                       
00403BB8  |.  EB 18         jmp     short 00403BD2
//然后跳到00403BD2继续执行
00403BBA  |>  3C 41         cmp     al, 41
//不等于D,9跳到这里比较是不是等于A
00403BBC  |.  75 07         jnz     short 00403BC5
//不等于跳到00403BC5
00403BBE  |.  BD 02000000   mov     ebp, 2  
//等于的话EBP=2                         
00403BC3  |.  EB 0D         jmp     short 00403BD2
//然后跳到00403BD2继续执行
00403BC5  |>  3C 35         cmp     al, 35
//不等于D,9,A跳到这里比较是不是等于5
00403BC7  |.  0F85 83000000 jnz     00403C50
//不等于跳到00403C50(会注册失败哦,不能跳)~
00403BCD  |.  BD 03000000   mov     ebp, 3 
等于EBP=3        
//以上分析告诉我们,注册码第一位要等于D,9,A,或者5 ,等于D时EBP=0;等于9时,EBP=1;等于A时,EBP=2,等于5时,EBP=3  
/////////////////////////////////////////一个循环////////////////////////////////////////////////////              
00403BD2  |>  33DB          xor     ebx, ebx
00403BD4  |.  BE 01000000   mov     esi, 1                           ;  ESI置1
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
00403BD9  |>  8A143E        /mov     dl, byte ptr [esi+edi]          ;注册码第[esi]位到DL
00403BDC  |.  33C9          |xor     ecx, ecx                        ;ECX被清零
00403BDE  |>  3891 EC914000 |/cmp     byte ptr [ecx+4091EC], dl      
//到这里D 004091EC一下查看是什么数据
004091EC  30 31 32 33 34 35 36 37                 01234567
004091F4  38 39 41 42 43 44 45 46                 89ABCDEF
原来是0123456789ABCDEF
  
00403BE4  |.  74 06         ||je      short 00403BEC
相等了跳到 00403BEC
00403BE6  |.  41            ||inc     ecx
00403BE7  |.  83F9 10       ||cmp     ecx, 10
00403BEA  |.^ 7C F2         |\jl      short 00403BDE
//这个小循环的作用是比较注册码第ESI位等于几
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
00403BEC  |>  83F9 10       |cmp     ecx, 10
//测试ECX=10(16)吗,也就是注册码第ESI位要在0——F之间,要不就注册失败哦
//ECX返回的结果其实等于CODE[ESI]
00403BEF  |.  74 5F         |je      short 00403C50
//等于就注册失败了,所以这里不能跳
00403BF1  |.  8D04EB        |lea     eax, dword ptr [ebx+ebp*8]
//EAX=[EBX+EBP*8],观察发现是这样的结果
00403BF4  |.  3B3485 6C9140>|cmp     esi, dword ptr [eax*4+40916C]
//D一下40916C看看,很明显的哦
0040916C  01 00 00 00 04 00 00 00                 ......
00409174  07 00 00 00 08 00 00 00                 ......
0040917C  09 00 00 00 0E 00 00 00                 .......
00409184  11 00 00 00 13 00 00 00                 ......
0040918C  03 00 00 00 05 00 00 00                 ......
00409194  07 00 00 00 09 00 00 00                 .......
0040919C  0A 00 00 00 0D 00 00 00                 ........
004091A4  10 00 00 00 12 00 00 00                 ......
004091AC  02 00 00 00 03 00 00 00                 ......
004091B4  06 00 00 00 08 00 00 00                 ......
004091BC  09 00 00 00 0B 00 00 00                 .... ...
004091C4  0F 00 00 00 11 00 00 00                 ......
004091CC  05 00 00 00 06 00 00 00                 ......
004091D4  09 00 00 00 0C 00 00 00                 ........
004091DC  0F 00 00 00 10 00 00 00                 ......
004091E4  12 00 00 00 13 00 00 00                 ......
//S[]={1,4,7,8,9,E,11,13,,3,5,7,9,a,d,,10,12,2,3,6,8,9,b,f,11,5,6,9,c,f,10,12,13}
//下标:(EBX+EBP*8)+1
00403BFB  |.  75 29         |jnz     short 00403C26
//不相等跳到00403C26
00403BFD  |.  8A543E FF     |mov     dl, byte ptr [esi+edi-1]
//注册码第[ESI-1]位到dl
00403C01  |.  33C0          |xor     eax, eax                             //EAX=0
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
00403C03  |>  3890 EC914000 |/cmp     byte ptr [eax+4091EC], dl
00403C09  |.  74 06         ||je      short 00403C11
00403C0B  |.  40            ||inc     eax
00403C0C  |.  83F8 10       ||cmp     eax, 10
00403C0F  |.^ 7C F2         |\jl      short 00403C03
//这个小循环的作用同上!
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
00403C11  |>  03C6          |add     eax, esi
//EAX其实等于CODE[ESI-1]
//EAX=EAX+ESI
00403C13  |.  25 0F000080   |and     eax, 8000000F
//于8000000F进行与运算
00403C18  |.  79 05         |jns     short 00403C1F
//SF=0跳,也就是EAX返回正值跳
00403C1A  |.  48            |dec     eax
//不跳EAX-1
00403C1B  |.  83C8 F0       |or      eax, FFFFFFF0
//再or FFFFFFF0
00403C1E  |.  40            |inc     eax
//最后EAX+1
00403C1F  |>  3BC8          |cmp     ecx, eax
//比较EAX与ECX
00403C21  |.  75 2D         |jnz     short 00403C50
不相等注册失败!
00403C23  |.  43            |inc     ebx                                   //EBX=EBX+1,在EAX=ECX的情况下才++的哦
00403C24  |.  EB 15         |jmp     short 00403C3B
00403C26  |>  33C0          |xor     eax, eax
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
00403C28  |>  3890 EC914000 |/cmp     byte ptr [eax+4091EC], dl
00403C2E  |.  74 06         ||je      short 00403C36
00403C30  |.  40            ||inc     eax
00403C31  |.  83F8 10       ||cmp     eax, 10
00403C34  |.^ 7C F2         |\jl      short 00403C28
//这个小循环的作用同上!
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
00403C36  |>  83F8 10       |cmp     eax, 10
00403C39  |.  74 15         |je      short 00403C50
00403C3B  |>  46            |inc     esi                                      //ESI=ESI+1,作用是指向注册码下一位拉!
00403C3C  |.  83FE 14       |cmp     esi, 14                                  //和注册码位数20比较
00403C3F  |.^ 7C 98         \jl      short 00403BD9                          //小于20继续循环
//////////////////////////////////////////一个循环////////////////////////////////////////////////////////
00403C41  |.  5F            pop     edi
00403C42  |.  5E            pop     esi
00403C43  |.  5D            pop     ebp
00403C44  |.  B8 01000000   mov     eax, 1                           ;注册成功的标志
00403C49  |.  5B            pop     ebx
00403C4A  |.  83C4 18       add     esp, 18
00403C4D  |.  C2 0400       retn    4
00403C50  |>  5F            pop     edi                              ;  Default case of switch 00403BA7
00403C51  |.  5E            pop     esi
00403C52  |.  5D            pop     ebp
00403C53  |.  33C0          xor     eax, eax                         ;注册失败的标志
00403C55  |.  5B            pop     ebx
00403C56  |.  83C4 18       add     esp, 18
00403C59  \.  C2 0400       retn    4
            
算法总结:
             ECX=CODE[ESI]                                //ESI从零开始,CODE[ESI]指注册码第ESI位
             EAX=CODE[ESI-1]+ESI AND 8000000F
                        若EAX为负,那么再让EAX=(EAX-1) OR or FFFFFFF0 +1
  

            让第0位=5,那么EBP=3;也就是ESI=5,6,9,C,F,10,12,13时比较EAX,ECX
            让第4位=1;ESI=5;  那么第5位=(1+esi) AND 8000000F=6
                       ESI=6 ;那么第6位=(6+6)   AND 8000000F=C
                       esi=9;  那么第9位=(1+9) and 8000000f=A    //让第8位=1
                       ESI=C; 那么第C位=(1+c) and 8000000f=D   //让第B位=1
                       ESI=F; 那么第F位=(1+f) and 8000000f=0   //让第E位=1
                       ESI=10,那么第10位=(0+10) AND 8000000F=0 
                       ESI=12,那么第12位=(1+12) and 8000000f=3 //让第11位=1     
                       ESI=13,那么第13位=(3+13) and 8000000f= 6  
                      
最后我们得到5???16c?1a?1d?100136?   ?表示0--F任意的一个,注意要大写!!
比如我们输入:522216C21A21D21001362,程序就会提示你注册成功!
------------------------------------------------------------------------

------------------------------------------------------------------------
程序代码分析:
我关心的只是打开以及关闭光驱的代码,这个软件其实提供的也只有这两个功能而已!
=======================================打开光驱的子函数=================================================================
004010C0  /$  81EC CC000000 sub     esp, 0CC                         ;为函数开辟堆栈空间                 
004010C6  |.  8A8424 D00000>mov     al, byte ptr [esp+D0]            ;  [esp+d0]指向的内容就是你的光驱,比如'G'
004010CD  |.  56            push    esi                              
004010CE  |.  6A 64         push    64                               ; /n = 64 (100.)
004010D0  |.  8D4C24 0C     lea     ecx, dword ptr [esp+C]           ; |
004010D4  |.  68 50904000   push    00409050                         ; |open
004010D9  |.  51            push    ecx                              ; |String1
004010DA  |.  884424 10     mov     byte ptr [esp+10], al            ; |
004010DE  |.  C64424 11 3A  mov     byte ptr [esp+11], 3A            ; |
004010E3  |.  C64424 12 00  mov     byte ptr [esp+12], 0             ; |
004010E8  |.  FF15 6C604000 call    dword ptr [<&KERNEL32.lstrcpynA>>; \lstrcpynA
//复制这个"open"
004010EE  |.  8B35 70604000 mov     esi, dword ptr [<&KERNEL32.lstrc>;  kernel32.lstrcatA
//esi=lstrcatA,call esi=call lstrcatA 
004010F4  |.  8D5424 04     lea     edx, dword ptr [esp+4]           ;光驱盘符到EDX
004010F8  |.  8D4424 08     lea     eax, dword ptr [esp+8]           ;'open'到EAX
004010FC  |.  52            push    edx                              ; /StringToAdd
004010FD  |.  50            push    eax                              ; |ConcatString
004010FE  |.  FFD6          call    esi                              ; \lstrcatA
//调用lstrcatA连接两个字符串!
00401100  |.  8D4C24 08     lea     ecx, dword ptr [esp+8]
[esp+8]的内容就是连接好的字符串-->ecx,我这里是ECX="open G:"
00401104  |.  68 38904000   push    00409038                         ; / "type cdaudio alias x"
00401109  |.  51            push    ecx                              ; |ConcatString
0040110A  |.  FFD6          call    esi                              ; \lstrcatA
//将"open G:"与"type cdaudio alias x"连接在一起
0040110C  |.  8B35 CC634000 mov     esi, dword ptr [<&WINMM.mciSendS>;  WINMM.mciSendStringA
//ESI=mciSendStringA 
00401112  |.  6A 00         push    0
00401114  |.  8D5424 70     lea     edx, dword ptr [esp+70]
00401118  |.  6A 64         push    64
0040111A  |.  8D4424 10     lea     eax, dword ptr [esp+10]          //[ESP+10]="open G: type cdaudio alias x"
0040111E  |.  52            push    edx
0040111F  |.  50            push    eax
00401120  |.  FFD6          call    esi                              ;  <&WINMM.mciSendStringA>
//CALL mciSendStringA( "open G: type cdaudio alias x,[esp+70],64,0")
00401122  |.  6A 00         push    0
00401124  |.  8D4C24 70     lea     ecx, dword ptr [esp+70]
00401128  |.  6A 64         push    64
0040112A  |.  51            push    ecx
0040112B  |.  68 28904000   push    00409028                         ;  set x door open
00401130  |.  FFD6          call    esi
// mciSendStringA( "set x door open",[esp+70],64,0),到这里我的光驱打开了,真讨厌
00401132  |.  6A 00         push    0
00401134  |.  8D5424 70     lea     edx, dword ptr [esp+70]
00401138  |.  6A 64         push    64
0040113A  |.  52            push    edx
0040113B  |.  68 20904000   push    00409020                         ;  close x
00401140  |.  FFD6          call    esi
//mciSendStringA("close x ,[esp+70],64,0" )
00401142  |.  5E            pop     esi
00401143  |.  81C4 CC000000 add     esp, 0CC
00401149  \.  C2 0400       retn    4
===============================================================================================================

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$关闭光驱的子函数$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
00401150  /$  81EC CC000000 sub     esp, 0CC                        ;为函数开辟堆栈空间
00401156  |.  8A8424 D00000>mov     al, byte ptr [esp+D0]           ;[esp+D0]指向光驱,比如'G'
0040115D  |.  56            push    esi
0040115E  |.  6A 64         push    64                               ; /n = 64 (100.)
00401160  |.  8D4C24 0C     lea     ecx, dword ptr [esp+C]           ; |
00401164  |.  68 50904000   push    00409050                         ; |open
00401169  |.  51            push    ecx                              ; |String1
0040116A  |.  884424 10     mov     byte ptr [esp+10], al            ; |
0040116E  |.  C64424 11 3A  mov     byte ptr [esp+11], 3A            ; |
00401173  |.  C64424 12 00  mov     byte ptr [esp+12], 0             ; |
00401178  |.  FF15 6C604000 call    dword ptr [<&KERNEL32.lstrcpynA>>; \lstrcpynA
0040117E  |.  8B35 70604000 mov     esi, dword ptr [<&KERNEL32.lstrc>;  kernel32.lstrcatA
//复制这个"open"
00401184  |.  8D5424 04     lea     edx, dword ptr [esp+4]           ;光驱盘符到EDX
00401188  |.  8D4424 08     lea     eax, dword ptr [esp+8]           'open'到EAX
0040118C  |.  52            push    edx                              ; /StringToAdd
0040118D  |.  50            push    eax                              ; |ConcatString
0040118E  |.  FFD6          call    esi                              ; \lstrcatA
//连接"open"+"G:"
00401190  |.  8D4C24 08     lea     ecx, dword ptr [esp+8]
00401194  |.  68 38904000   push    00409038                         ; / type cdaudio alias x
00401199  |.  51            push    ecx                              ; |ConcatString
0040119A  |.  FFD6          call    esi                              ; \lstrcatA
//连接"open G:"与"type cdaudio alias x"
0040119C  |.  8B35 CC634000 mov     esi, dword ptr [<&WINMM.mciSendS>;  WINMM.mciSendStringA
004011A2  |.  6A 00         push    0
004011A4  |.  8D5424 70     lea     edx, dword ptr [esp+70]
004011A8  |.  6A 64         push    64
004011AA  |.  8D4424 10     lea     eax, dword ptr [esp+10]          ;[ESP+10]的内容是"open G: type cdaudio alias x"
004011AE  |.  52            push    edx
004011AF  |.  50            push    eax
004011B0  |.  FFD6          call    esi                              ;  <&WINMM.mciSendStringA>
//mciSendStringA("open G: type cdaudio alias x",[esp+70],64,0)
004011B2  |.  6A 00         push    0
004011B4  |.  8D4C24 70     lea     ecx, dword ptr [esp+70]
004011B8  |.  6A 64         push    64
004011BA  |.  51            push    ecx
004011BB  |.  68 58904000   push    00409058                         ;  set x door closed
004011C0  |.  FFD6          call    esi
//mciSendStringA("set x door closed",[esp+70],64,0),到这里我的光驱就关闭了
004011C2  |.  6A 00         push    0
004011C4  |.  8D5424 70     lea     edx, dword ptr [esp+70]
004011C8  |.  6A 64         push    64
004011CA  |.  52            push    edx
004011CB  |.  68 20904000   push    00409020                         ;  close x
004011D0  |.  FFD6          call    esi
//mciSendStringA("close x",[esp+70],64,0)
004011D2  |.  5E            pop     esi
004011D3  |.  81C4 CC000000 add     esp, 0CC
004011D9  \.  C2 0400       retn    4

判断是不是光驱的我们可以用GetDriveTypeA,用类似下面的代码检测就可以了,作者也是这样的,代码在0040105B---004010A0之间,就不具体

分析了,主要是获得思路。
     for(drive='c';drive<'z';drive++)
          {
            if GetDriveTypeA(drive)==5  
                 s=drive;                 //最好用一个数组来接受,有些用户可能有多个光驱
                 return;
          }
简单的分析了一下代码,这其实是我第4次这样分析别人的程序了,为什么呢!因为当初学习C的时候感觉只能用来写算术题,写不出什么好的

应用程序来,所以后来就不学了!现在认识到要做高手必须得掌握一门编程语言(我的好友觉悟更高:高手也要吃饭!~_~),我的目的就是想看

看人家是怎样写出自己的程序的!
这个程序我还是留到等我学会编程了再写!^_^

【版权声明】"破"文一篇,随意转载,但请保持文章的完整性