【文章标题】: Buzof 2.0 算法分析
【文章作者】: Xuanyue
【软件名称】: Buzof 2.0
【下载地址】: http://www.basta.com/ProdBuzof.htm
【保护方式】: 注册码
【使用工具】: OllyDBD、Microsoft Visual C++ 6.0
【操作平台】: win2000
【软件介绍】: Buzof允许你自动回答、关闭、最小化任何窗口。
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!初学Crack,这可说是我破的第一个win32软件、写的第一个keygen,望前辈高手指出不足~
--------------------------------------------------------------------------------
【详细过程】
  一、算法跟踪
  
  根据注册框提示信息,很容易找到下面;
  
  
  
  0041D5B7  |. /0F84 4B010000 JE Buzof-BA.0041D708
  0041D5BD  |. |8BC3          MOV EAX,EBX
  0041D5BF  |. |8D50 02       LEA EDX,DWORD PTR DS:[EAX+2]             ;  第一位舍去存edx
  0041D5C2  |> |66:8B08       /MOV CX,WORD PTR DS:[EAX]                ;  检测长度
  0041D5C5  |. |83C0 02       |ADD EAX,2
  0041D5C8  |. |66:85C9       |TEST CX,CX
  0041D5CB  |.^|75 F5         \JNZ SHORT Buzof-BA.0041D5C2
  0041D5CD  |. |2BC2          SUB EAX,EDX
  0041D5CF  |. |D1F8          SAR EAX,1
  0041D5D1  |. |83F8 10       CMP EAX,10                               ;  是否是16位
  0041D5D4  |. |0F85 30010000 JNZ Buzof-BA.0041D70A
  0041D5DA  |. |56            PUSH ESI
  0041D5DB  |. |8BF0          MOV ESI,EAX                              ;  长度存esi
  0041D5DD  |. |8D49 00       LEA ECX,DWORD PTR DS:[ECX]
  0041D5E0  |> |0FB74473 FE   /MOVZX EAX,WORD PTR DS:[EBX+ESI*2-2]
  0041D5E5  |. |83EE 01       |SUB ESI,1
  0041D5E8  |. |50            |PUSH EAX
  0041D5E9  |. |E8 212C0100   |CALL Buzof-BA.0043020F
  0041D5EE  |. |83C4 04       |ADD ESP,4                               ;  出栈
  0041D5F1  |. |85C0          |TEST EAX,EAX                            ;  检测是否为数字
  0041D5F3  |. |0F84 22010000 |JE Buzof-BA.0041D71B                    ;  不是则跳出
  0041D5F9  |. |85F6          |TEST ESI,ESI
  0041D5FB  |.^|75 E3         \JNZ SHORT Buzof-BA.0041D5E0
  0041D5FD  |. |55            PUSH EBP
  0041D5FE  |. |0FB76B 1E     MOVZX EBP,WORD PTR DS:[EBX+1E]           ;  最后一位存ebp
  0041D602  |. |83ED 30       SUB EBP,30                               ;  unicode转成数字
  0041D605  |. |8BC5          MOV EAX,EBP
  0041D607  |. |0FAFC5        IMUL EAX,EBP                             ;  平方
  0041D60A  |. |99            CDQ
  0041D60B  |. |B9 0A000000   MOV ECX,0A
  0041D610  |. |F7F9          IDIV ECX                                 ;  除以10
  0041D612  |. |83C2 30       ADD EDX,30                               ;  综上,为(x-0x30)^2%10+30
  0041D615  |. |66:39146B     CMP WORD PTR DS:[EBX+EBP*2],DX           ;  设最后一位是数字a,则第a+1位必须等于edx值
  0041D619     |0F85 EF000000 JNZ Buzof-BA.0041D70E
  0041D61F  |. |8D45 01       LEA EAX,DWORD PTR SS:[EBP+1]             ;  (a+1)%15存入eax
  0041D622  |. |83F8 0F       CMP EAX,0F
  0041D625  |. |7C 03         JL SHORT Buzof-BA.0041D62A
  0041D627  |. |83E8 0F       SUB EAX,0F
  0041D62A  |> |0FB70C43      MOVZX ECX,WORD PTR DS:[EBX+EAX*2]
  0041D62E  |. |8D71 D0       LEA ESI,DWORD PTR DS:[ECX-30]            ;  第a+2位转成数字存esi
  0041D631  |. |83FE 02       CMP ESI,2
  0041D634  |. |7D 05         JGE SHORT Buzof-BA.0041D63B              ;  >2,ecx置1;=2,置0;否则置ffffffff(失败)
  0041D636  |. |83C9 FF       OR ECX,FFFFFFFF
  0041D639  |. |EB 08         JMP SHORT Buzof-BA.0041D643
  0041D63B  |> |33C9          XOR ECX,ECX
  0041D63D  |. |83FE 02       CMP ESI,2
  0041D640  |. |0F9FC1        SETG CL
  0041D643  |> |8B5424 10     MOV EDX,DWORD PTR SS:[ESP+10]
  0041D647  |. |83C0 01       ADD EAX,1                                ;  eax<=(a+2)%15
  0041D64A  |. |83F8 0F       CMP EAX,0F
  0041D64D  |. |890A          MOV DWORD PTR DS:[EDX],ECX
  0041D64F  |. |7C 03         JL SHORT Buzof-BA.0041D654
  0041D651  |. |83E8 0F       SUB EAX,0F
  0041D654  |> |8BC8          MOV ECX,EAX                              ;  ecx<=(a+2)%15
  0041D656  |. |83C0 03       ADD EAX,3                                ;  eax<=(a+5)%15
  0041D659  |. |83F8 0F       CMP EAX,0F
  0041D65C  |. |7C 03         JL SHORT Buzof-BA.0041D661
  0041D65E  |. |83E8 0F       SUB EAX,0F
  0041D661  |> |57            PUSH EDI
  0041D662  |. |0FB73C4B      MOVZX EDI,WORD PTR DS:[EBX+ECX*2]
  0041D666  |. |8BC8          MOV ECX,EAX                              ;  ecx<=(a+5)%15
  0041D668  |. |83C0 03       ADD EAX,3                                ;  eax<=(a+8)%15
  0041D66B  |. |83EF 30       SUB EDI,30                               ;  edi<=第a+3位转数字
  0041D66E  |. |83F8 0F       CMP EAX,0F
  0041D671  |. |7C 03         JL SHORT Buzof-BA.0041D676
  0041D673  |. |83E8 0F       SUB EAX,0F
  0041D676  |> |0FB70C4B      MOVZX ECX,WORD PTR DS:[EBX+ECX*2]        ;  ecx<=第a+6位转数字
  0041D67A  |. |83E9 30       SUB ECX,30
  0041D67D  |. |8BD0          MOV EDX,EAX                              ;  edx<=(a+8)%15
  0041D67F  |. |6BC9 64       IMUL ECX,ECX,64                          ;  ecx=ecx*100由下知,ecx只能为0
  0041D682  |. |83C0 03       ADD EAX,3                                ;  edx<=(a+11)%15
  0041D685  |. |83F8 0F       CMP EAX,0F
  0041D688  |. |7C 03         JL SHORT Buzof-BA.0041D68D
  0041D68A  |. |83E8 0F       SUB EAX,0F
  0041D68D  |> |0FB71453      MOVZX EDX,WORD PTR DS:[EBX+EDX*2]        ;  edx<=第a+9位转数字
  0041D691  |. |0FB70443      MOVZX EAX,WORD PTR DS:[EBX+EAX*2]        ;  eax<=第a+12位Unicode+ecx
  0041D695  |. |83EA 30       SUB EDX,30
  0041D698  |. |03C1          ADD EAX,ECX
  0041D69A  |. |8D1492        LEA EDX,DWORD PTR DS:[EDX+EDX*4]         ;  edx=edx*5
  0041D69D  |. |8D4C50 D0     LEA ECX,DWORD PTR DS:[EAX+EDX*2-30]      ;  13==第a+9位数字*10+第a+12位数字+第a+6位数字*100(0)
  0041D6A1  |. |83F9 0D       CMP ECX,0D
  0041D6A4     |75 6E         JNZ SHORT Buzof-BA.0041D714
  0041D6A6  |. |33C9          XOR ECX,ECX
  0041D6A8  |. |B8 10000000   MOV EAX,10
  0041D6AD  |. |8D49 00       LEA ECX,DWORD PTR DS:[ECX]
  0041D6B0  |> |0FB75443 FE   /MOVZX EDX,WORD PTR DS:[EBX+EAX*2-2]     ;  从最后一位开始循环检查
  0041D6B5  |. |83E8 01       |SUB EAX,1
  0041D6B8  |. |0FAFD0        |IMUL EDX,EAX                            ;  ecx<=第(x+1)位Unicode*x之和
  0041D6BB  |. |03CA          |ADD ECX,EDX
  0041D6BD  |. |85C0          |TEST EAX,EAX
  0041D6BF  |.^|75 EF         \JNZ SHORT Buzof-BA.0041D6B0
  0041D6C1  |. |8D45 0E       LEA EAX,DWORD PTR SS:[EBP+E]             ;  y=(最后一位数字加+14)%15
  0041D6C4  |. |83F8 0F       CMP EAX,0F
  0041D6C7  |. |7C 03         JL SHORT Buzof-BA.0041D6CC
  0041D6C9  |. |83E8 0F       SUB EAX,0F
  0041D6CC  |> |0FB71443      MOVZX EDX,WORD PTR DS:[EBX+EAX*2]        ;  edx<=第(y+1)位unicode*y
  0041D6D0  |. |0FAFD0        IMUL EDX,EAX
  0041D6D3  |. |2BCA          SUB ECX,EDX
  0041D6D5  |. |83E8 01       SUB EAX,1
  0041D6D8  |. |79 03         JNS SHORT Buzof-BA.0041D6DD
  0041D6DA  |. |83C0 0F       ADD EAX,0F
  0041D6DD  |> |0FB73443      MOVZX ESI,WORD PTR DS:[EBX+EAX*2]        ;  esi<=第y位unicode
  0041D6E1  |. |0FB7D6        MOVZX EDX,SI                             ;  edx<=第y位unicode*(y-1)
  0041D6E4  |. |0FAFD0        IMUL EDX,EAX
  0041D6E7  |. |2BCA          SUB ECX,EDX                              ;  ecx=sum(sn[i]*i)-sn[y]*y-sn[y-1]*(y-1)
  0041D6E9  |. |E8 12FEFFFF   CALL Buzof-BA.0041D500
  0041D6EE  |. |66:3BC6       CMP AX,SI                                ;  第y位unicode==0x30+ecx-(高8位(0x66666667*ecx)>>2)*5*2
  0041D6F1  |. |75 21         JNZ SHORT Buzof-BA.0041D714
  0041D6F3  |. |57            PUSH EDI
  0041D6F4  |. |E8 27FEFFFF   CALL Buzof-BA.0041D520
  0041D6F9  |. |83C4 04       ADD ESP,4
  0041D6FC  |. |85C0          TEST EAX,EAX
  0041D6FE     |74 14         JE SHORT Buzof-BA.0041D714
  0041D700  |. |5F            POP EDI
  0041D701  |. |5D            POP EBP
  0041D702  |. |B8 01000000   MOV EAX,1
  0041D707  |. |5E            POP ESI
  0041D708  |> \5B            POP EBX
  0041D709  |.  C3            RETN
  

  
  0041D500  /$  B8 67666666   MOV EAX,66666667
  0041D505  |.  F7E9          IMUL ECX                                 ;  最大0x37933333869
  0041D507  |.  C1FA 02       SAR EDX,2
  0041D50A  |.  8BC2          MOV EAX,EDX
  0041D50C  |.  C1E8 1F       SHR EAX,1F
  0041D50F  |.  03C2          ADD EAX,EDX
  0041D511  |.  8D0480        LEA EAX,DWORD PTR DS:[EAX+EAX*4]
  0041D514  |.  03C0          ADD EAX,EAX
  0041D516  |.  8BD0          MOV EDX,EAX
  0041D518  |.  8BC1          MOV EAX,ECX
  0041D51A  |.  2BC2          SUB EAX,EDX
  0041D51C  |.  83C0 30       ADD EAX,30
  0041D51F  \.  C3            RETN
  
  

  0041D520  /$  83EC 08       SUB ESP,8
  0041D523  |.  85DB          TEST EBX,EBX
  0041D525  |.  75 06         JNZ SHORT Buzof-BA.0041D52D
  0041D527  |.  33C0          XOR EAX,EAX
  0041D529  |.  83C4 08       ADD ESP,8
  0041D52C  |.  C3            RETN
  0041D52D  |>  55            PUSH EBP
  0041D52E  |.  56            PUSH ESI
  0041D52F  |.  57            PUSH EDI
  0041D530  |.  33ED          XOR EBP,EBP
  0041D532  |.  33FF          XOR EDI,EDI
  0041D534  |.  C74424 0C 020>MOV DWORD PTR SS:[ESP+C],2
  0041D53C  |.  C74424 10 010>MOV DWORD PTR SS:[ESP+10],1
  0041D544  |.  33F6          XOR ESI,ESI
  0041D546  |>  0FB70473      /MOVZX EAX,WORD PTR DS:[EBX+ESI*2]
  0041D54A  |.  50            |PUSH EAX
  0041D54B  |.  E8 BF2C0100   |CALL Buzof-BA.0043020F                  ;  判断其是否是数字
  0041D550  |.  83C4 04       |ADD ESP,4
  0041D553  |.  85C0          |TEST EAX,EAX
  0041D555  |.  74 1F         |JE SHORT Buzof-BA.0041D576
  0041D557  |.  0FB70473      |MOVZX EAX,WORD PTR DS:[EBX+ESI*2]
  0041D55B  |.  83E8 30       |SUB EAX,30
  0041D55E  |.  0FAF44BC 0C   |IMUL EAX,DWORD PTR SS:[ESP+EDI*4+C]     ;  十位个位相加(2*第x位数字)(x为奇数)/第x位数字(x偶数)
  0041D563  |.  83F8 0A       |CMP EAX,0A
  0041D566  |.  7C 03         |JL SHORT Buzof-BA.0041D56B
  0041D568  |.  83E8 09       |SUB EAX,9
  0041D56B  |>  33C9          |XOR ECX,ECX
  0041D56D  |.  03E8          |ADD EBP,EAX
  0041D56F  |.  85FF          |TEST EDI,EDI
  0041D571  |.  0F94C1        |SETE CL
  0041D574  |.  8BF9          |MOV EDI,ECX
  0041D576  |>  83C6 01       |ADD ESI,1
  0041D579  |.  83FE 10       |CMP ESI,10
  0041D57C  |.^ 7C C8         \JL SHORT Buzof-BA.0041D546
  0041D57E  |.  85ED          TEST EBP,EBP
  0041D580  |.  74 17         JE SHORT Buzof-BA.0041D599
  0041D582  |.  8BC5          MOV EAX,EBP
  0041D584  |.  99            CDQ
  0041D585  |.  F77C24 18     IDIV DWORD PTR SS:[ESP+18]
  0041D589  |.  85D2          TEST EDX,EDX
  0041D58B  |.  75 0C         JNZ SHORT Buzof-BA.0041D599
  0041D58D  |.  5F            POP EDI
  0041D58E  |.  5E            POP ESI
  0041D58F  |.  B8 01000000   MOV EAX,1
  0041D594  |.  5D            POP EBP
  0041D595  |.  83C4 08       ADD ESP,8
  0041D598  |.  C3            RETN
  0041D599  |>  5F            POP EDI
  0041D59A  |.  5E            POP ESI
  0041D59B  |.  33C0          XOR EAX,EAX
  0041D59D  |.  5D            POP EBP
  0041D59E  |.  83C4 08       ADD ESP,8
  0041D5A1  \.  C3            RETN
  
  
  
  
  二、算法小结
  
  
  这个程序检测字符是否位数字的办法很有趣,就是Buzof-BA.0043020F,有兴趣可以看下:
  
  0043AC14  |> \66:817D 08 00>CMP WORD PTR SS:[EBP+8],100              ;  不为0xffff,且<0x0100
  0043AC1A  |.  73 16         JNB SHORT Buzof-BA.0043AC32
  0043AC1C  |.  0FB745 08     MOVZX EAX,WORD PTR SS:[EBP+8]
  0043AC20  |.  8B0D 84FC4500 MOV ECX,DWORD PTR DS:[45FC84]            ;  该地址为软件自有的一张表,大小0x200
  0043AC26  |.  0FB70441      MOVZX EAX,WORD PTR DS:[ECX+EAX*2]        ;  具观察,数字0x30-0x39表中对应0x84
  0043AC2A  |.  0FB74D 0C     MOVZX ECX,WORD PTR SS:[EBP+C]            ;  为4;显然软件只接受数字,还有一些如B2之类的字符
  0043AC2E  |.  23C1          AND EAX,ECX                              ;  0x84&4=4
  0043AC30  |.  C9            LEAVE
  0043AC31  |.  C3            RETN
  
  程序内建了一张对应于0-255ascii码的表,内容如下:
  
  004519C2  20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00   . . . . . . . .
  004519D2  20 00 68 00 28 00 28 00 28 00 28 00 20 00 20 00   .h.(.(.(.(. . .
  004519E2  20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00   . . . . . . . .
  004519F2  20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00   . . . . . . . .
  00451A02  48 00 10 00 10 00 10 00 10 00 10 00 10 00 10 00  H........
  00451A12  10 00 10 00 10 00 10 00 10 00 10 00 10 00 10 00  ........
  00451A22  84 00 84 00 84 00 84 00 84 00 84 00 84 00 84 00  ????????
  00451A32  84 00 84 00 10 00 10 00 10 00 10 00 10 00 10 00  ??......
  00451A42  10 00 81 01 81 01 81 01 81 01 81 01 81 01 01 01  .??????
  00451A52  01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01  
  00451A62  01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01  
  00451A72  01 01 01 01 01 01 10 00 10 00 10 00 10 00 10 00  .....
  00451A82  10 00 82 01 82 01 82 01 82 01 82 01 82 01 02 01  .??????
  00451A92  02 01 02 01 02 01 02 01 02 01 02 01 02 01 02 01  
  00451AA2  02 01 02 01 02 01 02 01 02 01 02 01 02 01 02 01  
  00451AB2  02 01 02 01 02 01 10 00 10 00 10 00 10 00 20 00  .... .
  00451AC2  20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00   . . . . . . . .
  00451AD2  20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00   . . . . . . . .
  00451AE2  20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00   . . . . . . . .
  00451AF2  20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00   . . . . . . . .
  00451B02  48 00 10 00 10 00 10 00 10 00 10 00 10 00 10 00  H........
  00451B12  10 00 10 00 10 00 10 00 10 00 10 00 10 00 10 00  ........
  00451B22  10 00 10 00 14 00 14 00 10 00 10 00 10 00 10 00  ........
  00451B32  10 00 14 00 10 00 10 00 10 00 10 00 10 00 10 00  ........
  00451B42  01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01  
  00451B52  01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01  
  00451B62  01 01 01 01 01 01 01 01 01 01 01 01 01 01 10 00  .
  00451B72  01 01 01 01 01 01 01 01 01 01 01 01 01 01 02 01  
  00451B82  02 01 02 01 02 01 02 01 02 01 02 01 02 01 02 01  
  00451B92  02 01 02 01 02 01 02 01 02 01 02 01 02 01 02 01  
  00451BA2  02 01 02 01 02 01 02 01 02 01 02 01 02 01 10 00  .
  00451BB2  02 01 02 01 02 01 02 01 02 01 02 01 02 01 02 01  
  00451BC2  01 01 00 00 00 00 80 81 82 83 84 85 86 87 88 89  ....?????
  
  你可以发现对应数字0-9(即0x30-0x39)的地方,表中的值全为0x84,程序对字符判断时,传了一个值为4的参数和查表得到的0x84做与操作,返回非零说明是数字。我不知他为何如此大费周章,难道是为了增加破解难度?抑或别的程序也这样做,我是新手,在这方面没经验忘高手指教。
  
  
  根据上面的分析,合法注册码有如下要求:
  1)由16位数字(0-9)组成,用字符串数组a[16]表示,为表述方便,增加一个对应位转成数字的整形辅助数组n[16].
  2)(n[15]^2)%10==n[n[15]]  (^为次方).
  3)13==n[(n[15]+11)%15]+n[(n[15]+8)%15]*10+n[n[15]+5]*100.
  4)n[n[15]+1]>1.
  5)用如下算法生成的数s:
  s=0;
  for(int i=0;i<16;i++)
  {
    if(i==((n[15]+14)%15)||i==((n[15]+13)%15))continue;
    s+=(i*a[i]);
  }
  需满足条件:n[(n[15]+13)%15]==s-(((0x66666667*s)<<32)>>2)*5*2.
  6)用如下算法生成的数m:
  m=0;
  for(int i=0;i<16;i++)
  {
    int t=n[i]*(i%2+1);
    m+=(t/10+t%10);
  }
  需满足条件:0==m%n[n[15]+2].
  
  
  下面生成注册码:
  
  n[15]任取为x(0-9),则n[x]=(x^2)%10,n[x+5]=0,n[(x+8)%15]=1,n[(x+11)%15]=3
  
  为使条件5满足,不妨取n[x+2]=1,剩余的数除了n[(x+13)%15],其他任取,但n[x+1]>1,n[(x+13)%15]可由条件5推得。
  
  又由于x,(x+8)%15,(x+11)%15,(x+13)%15,x+5,x+2,x+1模15两两不等,所以各条件不会发生矛盾。
  
  
  
  注册机的c++源码:
  
  
  int main(int argc, char* argv[])
  {
    srand((unsigned)time( NULL ));
    char sn[17];
    sn[16]=0;
    for(int i=0;i<16;i++)sn[i]=-1;
    sn[15]=rand()%10;
    char x=sn[15];
    sn[x]=(x*x)%10;
    sn[x+5]=0;
    sn[(x+8)%15]=1;
    sn[(x+11)%15]=3;
    sn[x+2]=1;
    for(i=0;i<15;i++)
      if(sn[i]<0)sn[i]=char(rand()%10);
    if(sn[x+1]<2)sn[x+1]=2;
  
    __int64 s=0;
    for(i=0;i<16;i++)
    {
      if(i==((x+14)%15)||i==((x+13)%15))continue;
      s+=(i*(sn[i]+0x30));
    }
    
    sn[(x+13)%15]=char(s-((s*0x66666667)>>0x22)*0xa);
    for(i=0;i<16;i++)sn[i]+=0x30;
    char sn1[9];
    strncpy(sn1,sn,8);
    sn1[8]=0;
    printf("Buzof 2.0 Key: %s-%s\n",sn1,sn+8);
    return 0;
  }
  
--------------------------------------------------------------------------------
【经验总结】
  发现自己实在是水平有限,s-((s*0x66666667)>>0x22)*0xa应该可表示成s*0.0000XXX的形式,看了好久才搞明白。。。。
  这也应该是一个偏简单的算法,跟了我一天。。。不过是第一次,可以理解,嘿嘿~~
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2007年02月22日 12:32:25