首页
社区
课程
招聘
[原创]HappyTown的CrackMe 17算法分析
发表于: 2007-7-17 17:31 6126

[原创]HappyTown的CrackMe 17算法分析

2007-7-17 17:31
6126

【文章作者】: 斜阳残雪
【作者邮箱】: zlm324@126.com
【下载地址】: 附件提供
【编写语言】: VC++ 6.0
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
                     发帖前没有搜索,不知道发重了没有。
--------------------------------------------------------------------------------
【详细过程】

  OD载入,找关键字,发现"Good job,man!",跟随,来到这里:
  
  0040106D   .  68 E9030000   push    3E9                              ; /ControlID = 3E9 (1001.)
  00401072   .  56            push    esi                              ; |hWnd
  00401073   .  FF15 B4504000 call    dword ptr [<&USER32.GetDlgItem>] ; \GetDlgItem
  00401079   .  50            push    eax                              ; /hWnd
  0040107A   .  FF15 CC504000 call    dword ptr [<&USER32.SetFocus>]   ; \SetFocus
  00401080   .  56            push    esi
  00401081   .  E8 AA000000   call    00401130                                ;关键Call
  00401086   .  83C4 04       add     esp, 4
  00401089   .  85C0          test    eax, eax
  0040108B   .  5E            pop     esi
  0040108C   .  0F84 8D000000 je      0040111F                                ;跳走则失败
  00401092   .  6A 40         push    40                               ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
  00401094   .  68 C4604000   push    004060C4                         ; |Title = "Congratulations"
  00401099   .  68 B4604000   push    004060B4                         ; |Text = "Good job, man!"
  0040109E   .  6A 00         push    0                                ; |hOwner = NULL
  004010A0   .  FF15 B8504000 call    dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
  004010A6   .  33C0          xor     eax, eax
  004010A8   .  C2 1000       retn    10
  
  我们跟进关键Call:
  (前面有一堆废话,略去)
  004011B6  |.  68 C9000000   push    0C9                              ; /Count = C9 (201.)
  004011BB  |.  52            push    edx                              ; |Buffer
  004011BC  |.  68 E8030000   push    3E8                              ; |ControlID = 3E8 (1000.)
  004011C1  |.  50            push    eax                              ; |hWnd
  004011C2  |.  FF15 AC504000 call    dword ptr [<&USER32.GetDlgItemTe>; \GetDlgItemTextA
  004011C8  |.  8BF0          mov     esi, eax
  004011CA  |.  83FE 06       cmp     esi, 6
  004011CD  |.  0F8C 3B020000 jl      0040140E
  004011D3  |.  83FE 0F       cmp     esi, 0F                          ;  姓名在6~16个字符之间
  004011D6  |.  0F8F 32020000 jg      0040140E
  004011DC  |.  8D4C24 4C     lea     ecx, dword ptr [esp+4C]
  004011E0  |.  56            push    esi
  004011E1  |.  51            push    ecx
  004011E2  |.  E8 39020000   call    00401420                         ;  小写字母转换成大写
  004011E7  |.  83C4 08       add     esp, 8
  004011EA  |.  85C0          test    eax, eax
  004011EC  |.  0F84 1C020000 je      0040140E
  004011F2  |.  33ED          xor     ebp, ebp
  004011F4  |.  33C9          xor     ecx, ecx
  004011F6  |.  3BF5          cmp     esi, ebp
  004011F8  |.  7E 2F         jle     short 00401229
  004011FA  |>  33FF          /xor     edi, edi                        ;  姓名处理过程,详见NameAnalysis
  004011FC  |.  3BCD          |cmp     ecx, ebp
  004011FE  |.  7E 24         |jle     short 00401224
  00401200  |>  8A543C 4C     |/mov     dl, byte ptr [esp+edi+4C]
  00401204  |.  8A440C 4C     ||mov     al, byte ptr [esp+ecx+4C]
  00401208  |.  3AD0          ||cmp     dl, al
  0040120A  |.  75 13         ||jnz     short 0040121F
  0040120C  |.  3BCE          ||cmp     ecx, esi
  0040120E  |.  8BC1          ||mov     eax, ecx
  00401210  |.  7D 0D         ||jge     short 0040121F                        ;此循环用于去掉一个字符后把后面的移动到前面去
  00401212  |>  8A5404 4D     ||/mov     dl, byte ptr [esp+eax+4D]
  00401216  |.  885404 4C     |||mov     byte ptr [esp+eax+4C], dl
  0040121A  |.  40            |||inc     eax
  0040121B  |.  3BC6          |||cmp     eax, esi
  0040121D  |.^ 7C F3         ||\jl      short 00401212
  0040121F  |>  47            ||inc     edi
  00401220  |.  3BF9          ||cmp     edi, ecx
  00401222  |.^ 7C DC         |\jl      short 00401200
  00401224  |>  41            |inc     ecx
  00401225  |.  3BCE          |cmp     ecx, esi
  00401227  |.^ 7C D1         \jl      short 004011FA
  00401229  |>  8D4424 4C     lea     eax, dword ptr [esp+4C]
  0040122D  |.  50            push    eax                              ; /String
  0040122E  |.  FF15 04504000 call    dword ptr [<&KERNEL32.lstrlenA>] ; \取处理完之后的姓名长度
  00401234  |.  8BF0          mov     esi, eax
  00401236  |.  83FE 06       cmp     esi, 6
  00401239  |.  0F8C CF010000 jl      0040140E                         ;  处理过的姓名必须长于6字节
  
  NameAnalysis代码:
  
  Function NameProc(Name As String) As String
  
  Dim n As Integer
  For i = 2 To Len(Name)
      If i > Len(Name) Then n = Len(Name) Else n = i
      For k = 1 To n - 1
          If Mid(Name, k, 1) = Mid(Name, i, 1) Then
              If k <= i Then
                  Name = Left(Name, i - 1) & Right(Name, Len(Name) - i)
              Else
                  Name = Left(Name, Len(Name) - 1)
              End If
          End If
      Next k
  Next i
  NameProc = Name
  End Function
  
  这段程序是我按照汇编代码翻译的,没有优化,唯一的不同在于VB不能处理chr(0),所以有一个折中处理。
  这段程序貌似是把姓名中重复的字符给去掉了,但细看的话却右不尽相同,
  应该是去掉了一定范围内的重复字符,我也说不太清楚,毕竟这只是一段程序,大家可以与汇编代码和内存数据比对着理解。
  
  例如:"PEDIYABCBIT"就会变成"PEDIYABCIT",近处的"B"被去掉了,但是远处的"I"却得以保留。
  
  接下来:
  0040123F  |.  8D4C24 4C     lea     ecx, dword ptr [esp+4C]
  00401243  |.  8D5424 20     lea     edx, dword ptr [esp+20]
  00401247  |.  51            push    ecx                              ; /String2
  00401248  |.  52            push    edx                              ; |String1
  00401249  |.  FF15 00504000 call    dword ptr [<&KERNEL32.lstrcpyA>] ; \lstrcpyA
  0040124F  |.  B3 41         mov     bl, 41                           ;  41="A"
  00401251  |.  896C24 10     mov     dword ptr [esp+10], ebp
  00401255  |.  8D7434 20     lea     esi, dword ptr [esp+esi+20]      ;  有效姓名长度入esi
  00401259  |>  80FB 4A       /cmp     bl, 4A                          ;  4A="J"
  0040125C  |.  75 0A         |jnz     short 00401268
  0040125E  |.  B3 49         |mov     bl, 49                          ;  Change "J" into "I"
  00401260  |.  C74424 10 010>|mov     dword ptr [esp+10], 1
  00401268  |>  0FBEC3        |movsx   eax, bl
  0040126B  |.  8D4C24 20     |lea     ecx, dword ptr [esp+20]
  0040126F  |.  50            |push    eax
  00401270  |.  51            |push    ecx
  00401271  |.  E8 2A020000   |call    004014A0                                ;此Call的作用根据处理后的结果猜测而得,里面的内容看不懂-_-!
  00401276  |.  83C4 08       |add     esp, 8
  00401279  |.  85C0          |test    eax, eax
  0040127B  |.  75 03         |jnz     short 00401280
  0040127D  |.  881E          |mov     byte ptr [esi], bl
  0040127F  |.  46            |inc     esi
  00401280  |>  8A5424 10     |mov     dl, byte ptr [esp+10]
  00401284  |.  896C24 10     |mov     dword ptr [esp+10], ebp
  00401288  |.  FEC2          |inc     dl
  0040128A  |.  02DA          |add     bl, dl
  0040128C  |.  80FB 5B       |cmp     bl, 5B
  0040128F  |.^ 75 C8         \jnz     short 00401259                  ;  此段循环把姓名中不含有的"A"~"Z"(不含"J")中的字符按顺序添加到姓名的后面
  
  接上例:"PEDIYABCIT"又处理成"PEDIYABCITFGHKLMNOPQRSUVWXZ"
  
  继续:
  0040129F  |.  68 C9000000   push    0C9                              ; /Count = C9 (201.)
  004012A4  |.  50            push    eax                              ; |Buffer
  004012A5  |.  68 E9030000   push    3E9                              ; |ControlID = 3E9 (1001.)
  004012AA  |.  51            push    ecx                              ; |hWnd
  004012AB  |.  FF15 AC504000 call    dword ptr [<&USER32.GetDlgItemTe>; \GetDlgItemTextA
  004012B1  |.  83F8 0E       cmp     eax, 0E                          ;  注册码长度必须为14位
  004012B4  |.  0F85 54010000 jnz     0040140E
  004012BA  |.  8D9424 140100>lea     edx, dword ptr [esp+114]
  004012C1  |.  50            push    eax
  004012C2  |.  52            push    edx
  004012C3  |.  E8 58010000   call    00401420                         ;  检查注册码是否含数字,含则挂,并且小写转大写
  004012C8  |.  83C4 08       add     esp, 8
  004012CB  |.  85C0          test    eax, eax
  004012CD  |.  0F84 3B010000 je      0040140E
  
  跟入004012C3处的Call:
  00401420  /$  53            push    ebx
  00401421  |.  8B5C24 0C     mov     ebx, dword ptr [esp+C]
  00401425  |.  56            push    esi
  00401426  |.  33F6          xor     esi, esi
  00401428  |.  85DB          test    ebx, ebx
  0040142A  |.  57            push    edi
  0040142B  |.  7E 4D         jle     short 0040147A
  0040142D  |.  8B7C24 10     mov     edi, dword ptr [esp+10]
  00401431  |>  833D FC624000>/cmp     dword ptr [4062FC], 1
  00401438  |.  7E 14         |jle     short 0040144E
  0040143A  |.  0FBE043E      |movsx   eax, byte ptr [esi+edi]
  0040143E  |.  68 03010000   |push    103
  00401443  |.  50            |push    eax
  00401444  |.  E8 DF010000   |call    00401628
  00401449  |.  83C4 08       |add     esp, 8
  0040144C  |.  EB 13         |jmp     short 00401461
  0040144E  |>  0FBE0C3E      |movsx   ecx, byte ptr [esi+edi]
  00401452  |.  8B15 F0604000 |mov     edx, dword ptr [4060F0]         ;  CrackMe_.004060FA
  00401458  |.  66:8B044A     |mov     ax, word ptr [edx+ecx*2]
  0040145C  |.  25 03010000   |and     eax, 103
  00401461  |>  85C0          |test    eax, eax
  00401463  |.  74 1E         |je      short 00401483
  00401465  |.  0FBE043E      |movsx   eax, byte ptr [esi+edi]
  00401469  |.  50            |push    eax
  0040146A  |.  E8 ED000000   |call    0040155C
  0040146F  |.  83C4 04       |add     esp, 4
  00401472  |.  88043E        |mov     byte ptr [esi+edi], al
  00401475  |.  46            |inc     esi
  00401476  |.  3BF3          |cmp     esi, ebx
  00401478  |.^ 7C B7         \jl      short 00401431
  0040147A  |>  5F            pop     edi
  0040147B  |.  5E            pop     esi
  0040147C  |.  B8 01000000   mov     eax, 1
  00401481  |.  5B            pop     ebx
  00401482  |.  C3            retn
  00401483  |>  5F            pop     edi
  00401484  |.  5E            pop     esi
  00401485  |.  33C0          xor     eax, eax
  00401487  |.  5B            pop     ebx
  00401488  \.  C3            retn
  
  这里要查一个表,把注册码的每一位用表中的数据替换,然后再跟103H做And,结果为0则失败。
  表在这里:
  004060FA  20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00   . . . . . . . .
  0040610A  20 00 28 00 28 00 28 00 28 00 28 00 20 00 20 00   .(.(.(.(.(. . .
  0040611A  20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00   . . . . . . . .
  0040612A  20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00   . . . . . . . .
  0040613A  48 00 10 00 10 00 10 00 10 00 10 00 10 00 10 00  H........
  0040614A  10 00 10 00 10 00 10 00 10 00 10 00 10 00 10 00  ........
  0040615A  84 00 84 00 84 00 84 00 84 00 84 00 84 00 84 00  ????????
  0040616A  84 00 84 00 10 00 10 00 10 00 10 00 10 00 10 00  ??......
  0040617A  10 00 81 00 81 00 81 00 81 00 81 00 81 00 01 00  .??????.
  0040618A  01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00  ........
  0040619A  01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00  ........
  004061AA  01 00 01 00 01 00 10 00 10 00 10 00 10 00 10 00  ........
  004061BA  10 00 82 00 82 00 82 00 82 00 82 00 82 00 02 00  .??????.
  004061CA  02 00 02 00 02 00 02 00 02 00 02 00 02 00 02 00  ........
  004061DA  02 00 02 00 02 00 02 00 02 00 02 00 02 00 02 00  ........
  004061EA  02 00 02 00 02 00 10 00 10 00 10 00 10 00 20 00  ....... .
  
  经计算可知:只有81、82、01、02与103H做And结果不为0,
  查看这四个数字在表中的位置,可知只有字母才可以通过。
  也就是说注册码只可以包含字母。
  
  下面是最复杂的注册码判断过程:
  004012D3  |.  8B5C24 10     mov     ebx, dword ptr [esp+10]
  004012D7  |.  896C24 1C     mov     dword ptr [esp+1C], ebp
  004012DB  |.  8B6C24 1C     mov     ebp, dword ptr [esp+1C]
  004012DF  |.  8B7C24 1C     mov     edi, dword ptr [esp+1C]
  004012E3  |>  8B4424 1C     /mov     eax, dword ptr [esp+1C]
  004012E7  |.  8A9404 140100>|mov     dl, byte ptr [esp+eax+114]
  004012EE  |.  8A8C04 150100>|mov     cl, byte ptr [esp+eax+115]
  004012F5  |.  8DB404 150100>|lea     esi, dword ptr [esp+eax+115]
  004012FC  |.  80FA 4A       |cmp     dl, 4A                          ;  4A="J"
  004012FF  |.  884C24 17     |mov     byte ptr [esp+17], cl
  00401303  |.  75 02         |jnz     short 00401307
  00401305  |.  B2 49         |mov     dl, 49                          ;  change "J" into "I"
  00401307  |>  33C9          |xor     ecx, ecx                                ;注:上面的变换只对该两位注册码的前一位有效,不对第二位做变换
  00401309  |.  8D7424 20     |lea     esi, dword ptr [esp+20]
  0040130D  |>  33C0          |/xor     eax, eax
  0040130F  |>  381406        ||/cmp     byte ptr [esi+eax], dl
  00401312  |.  75 0A         |||jnz     short 0040131E
  00401314  |.  8B5C24 10     |||mov     ebx, dword ptr [esp+10]
  00401318  |.  8BE9          |||mov     ebp, ecx                      ;  循环过后ebp中应保留了在第几个五字节段中发现了前1位注册码(注意开始为0)
  0040131A  |.  894424 18     |||mov     dword ptr [esp+18], eax       ;  esp+18中存放前一个注册码位于该五字节段的第几位(注意开始为0)
  0040131E  |>  40            |||inc     eax
  0040131F  |.  83F8 05       |||cmp     eax, 5
  00401322  |.^ 7C EB         ||\jl      short 0040130F
  00401324  |.  41            ||inc     ecx
  00401325  |.  83C6 05       ||add     esi, 5
  00401328  |.  83F9 05       ||cmp     ecx, 5
  0040132B  |.^ 7C E0         |\jl      short 0040130D
  0040132D  |.  33F6          |xor     esi, esi
  0040132F  |.  8D4C24 20     |lea     ecx, dword ptr [esp+20]
  00401333  |>  33C0          |/xor     eax, eax
  00401335  |>  8A5424 17     ||/mov     dl, byte ptr [esp+17]         ;  上个循环取的两位注册码的第二位
  00401339  |.  3811          |||cmp     byte ptr [ecx], dl
  0040133B  |.  75 04         |||jnz     short 00401341
  0040133D  |.  8BFE          |||mov     edi, esi                      ;  循环过后edi中保存了第几个五字节段取到后一位注册码
  0040133F  |.  8BD8          |||mov     ebx, eax                      ;  ebx中保留后一位注册码出现在五字节段的第几位
  00401341  |>  40            |||inc     eax
  00401342  |.  41            |||inc     ecx
  00401343  |.  83F8 05       |||cmp     eax, 5
  00401346  |.^ 7C ED         ||\jl      short 00401335
  00401348  |.  46            ||inc     esi
  00401349  |.  83FE 05       ||cmp     esi, 5
  0040134C  |.^ 7C E5         |\jl      short 00401333                 ;  注意:两个循环记录的都是最后一次出现注册码字节的信息!!
  0040134E  |.  3BEF          |cmp     ebp, edi                                ;这里判断xa和ya是否相等
  00401350  |.  895C24 10     |mov     dword ptr [esp+10], ebx
  00401354  |.  75 3A         |jnz     short 00401390
  00401356  |.  8B4424 18     |mov     eax, dword ptr [esp+18]
  0040135A  |.  85C0          |test    eax, eax
  0040135C  |.  75 0A         |jnz     short 00401368
  0040135E  |.  C74424 18 040>|mov     dword ptr [esp+18], 4
  00401366  |.  EB 04         |jmp     short 0040136C
  00401368  |>  FF4C24 18     |dec     dword ptr [esp+18]
  0040136C  |>  85DB          |test    ebx, ebx
  0040136E  |.  75 07         |jnz     short 00401377
  00401370  |.  BB 04000000   |mov     ebx, 4
  00401375  |.  EB 01         |jmp     short 00401378
  00401377  |>  4B            |dec     ebx
  00401378  |>  8B4424 18     |mov     eax, dword ptr [esp+18]
  0040137C  |.  8BD5          |mov     edx, ebp
  0040137E  |.  895C24 10     |mov     dword ptr [esp+10], ebx
  00401382  |.  8D0CA8        |lea     ecx, dword ptr [eax+ebp*4]
  00401385  |.  03D1          |add     edx, ecx
  00401387  |.  8D0CBB        |lea     ecx, dword ptr [ebx+edi*4]
  0040138A  |.  8A4414 20     |mov     al, byte ptr [esp+edx+20]                ;取字符1
  0040138E  |.  EB 46         |jmp     short 004013D6
  00401390  |>  8B4C24 18     |mov     ecx, dword ptr [esp+18]
  00401394  |.  3BCB          |cmp     ecx, ebx                                ;这里判断xb和yb是否相等
  00401396  |.  75 30         |jnz     short 004013C8
  00401398  |.  85ED          |test    ebp, ebp
  0040139A  |.  75 07         |jnz     short 004013A3
  0040139C  |.  BD 04000000   |mov     ebp, 4
  004013A1  |.  EB 01         |jmp     short 004013A4
  004013A3  |>  4D            |dec     ebp
  004013A4  |>  85FF          |test    edi, edi
  004013A6  |.  75 07         |jnz     short 004013AF
  004013A8  |.  BF 04000000   |mov     edi, 4
  004013AD  |.  EB 01         |jmp     short 004013B0
  004013AF  |>  4F            |dec     edi
  004013B0  |>  8D04A9        |lea     eax, dword ptr [ecx+ebp*4]
  004013B3  |.  8BCD          |mov     ecx, ebp
  004013B5  |.  03C8          |add     ecx, eax
  004013B7  |.  8D14BB        |lea     edx, dword ptr [ebx+edi*4]
  004013BA  |.  8A440C 20     |mov     al, byte ptr [esp+ecx+20]                ;取字符1
  004013BE  |.  8BCF          |mov     ecx, edi
  004013C0  |.  03CA          |add     ecx, edx
  004013C2  |.  8A4C0C 20     |mov     cl, byte ptr [esp+ecx+20]                ;取字符2
  004013C6  |.  EB 16         |jmp     short 004013DE
  004013C8  |>  8D14AB        |lea     edx, dword ptr [ebx+ebp*4]
  004013CB  |.  8BC5          |mov     eax, ebp
  004013CD  |.  03C2          |add     eax, edx
  004013CF  |.  8D0CB9        |lea     ecx, dword ptr [ecx+edi*4]
  004013D2  |.  8A4404 20     |mov     al, byte ptr [esp+eax+20]                ;取字符1
  004013D6  |>  8BD7          |mov     edx, edi
  004013D8  |.  03D1          |add     edx, ecx
  004013DA  |.  8A4C14 20     |mov     cl, byte ptr [esp+edx+20]                ;取字符2
  004013DE  |>  8B5424 1C     |mov     edx, dword ptr [esp+1C]                ;esp+1C里面存储的是计数器
  004013E2  |.  3A4414 3C     |cmp     al, byte ptr [esp+edx+3C]                ;与固定字符串的位比较
  004013E6  |.  75 26         |jnz     short 0040140E
  004013E8  |.  3A4C14 3D     |cmp     cl, byte ptr [esp+edx+3D]                ;与固定字符串的位比较
  004013EC  |.  75 20         |jnz     short 0040140E
  004013EE  |.  83C2 02       |add     edx, 2                                ;计数器增2
  004013F1  |.  83FA 0E       |cmp     edx, 0E                                ;是否已经到14
  004013F4  |.  895424 1C     |mov     dword ptr [esp+1C], edx
  004013F8  |.^ 0F8C E5FEFFFF \jl      004012E3
  
  这个过程的大概思想是:依次取注册码的两字节,然后根据这两字节在处理后的姓名中的位置,分解成xa*5+xb、ya*5+yb的形式,
  再根据xa=ya或xb=yb或都不相等这三种情况对xa、xb、ya、yb做相应的处理。再根据处理后变量,取姓名中相应位置的字符,
  判断与"CRACKINGFORFUN"字符串依次两位是否相同,不同则失败。
  
  我把这段代码翻译了一下,大致如下:
  
  sc="CRACKINGFORFUN"
  name="PEDIYABCITFGHKLMNOPQRSUVWXZ"
  sn="ABCDEFGHIJKLMN" '随意写的
  
  For scpos=1 To 14 Step 2
         
          snb=Mid(sn,k,2)
          If Left(snb,1)="J" Then snb="I" & Right(snb,1)
  
          pos=0
          For i=1 To 25
                  If Mid(name,i,1)=Left(snb) Then pos=i
          Next i
  
          If pos<>0 Then xa=(pos\5)-1:xb=(pos Mod 5)-1
  
          pos=0
          For i=1 To 25
                  If Mid(name,i,1)=Right(snb) Then pos=i
          Next i
  
          If pos<>0 Then ya=(pos\5)-1:yb=(pos Mod 5)-1
  
  
          If xa=ya Then
  
                  If xb=0 Then xb=4 Else xb=xb-1
                  If yb=0 Then yb=4 Else yb=yb-1
  
                  'eax=xb:edx=xa:ecx=xb+xa*4:edx=edx+ecx
                  edx=xa+xb+xa*4
                  'ecx=yb+ya*4
                  al=Mid(name,edx+1,1)
                  'edx=ya:edx=edx+ecx
                  edx=ya+yb+ya*4
                  cl=Mid(name,edx+1,1)
          Else
                  If xb=yb Then
                          If xa=0 Then xa=4 Else xa=xa-1
                          If ya=0 Then ya=4 Else ya=ya-1
                          'ecx=xb:eax=ecx+xa*4=xb+xa*4
                          'ecx=xa:edx=yb+ya*4:ecx=ecx+eax
                          ecx=xa+xb+xa*4
                          al=Mid(name,ecx+1,1)
                          'ecx=ya:ecx=ecx+edx
                          ecx=ya+yb+ya*4
                          cl=Mid(name,ecx+1,1)
                  Else
                          'edx=yb+xa*4:eax=xa:eax=eax+edx
                          eax=xa+yb+xa*4
                          'ecx=xb+ya*4
                          al=mid(name,eax+1,1)
                          'ecx=xb+ya*4:edx=ya:edx=edx+ecx
                          edx=ya+xb+ya*4
                          cl=mid(name,edx+1,1)
                  End if
          End If
  
          If al<>Mid(sc,scpos,1) Then die
          If cl<>Mid(sc,scpos+1,1) Then die
         
  Next scpos
  
  根据上述思想,逆向写出注册机(VB代码):
  
  Const SC = "CRACKINGFORFUN"
  Dim SN(14) As String
  Dim SNPos As Integer
  
  Private Sub CmdGen_Click()
  
  Dim Name As String
  Dim z As String
  Dim i As Integer
  Dim j As Integer
  Dim Succ As Boolean
  
  For i = 1 To 14: SN(i) = "": Next i
  TxtSN.Text = ""
  
  If Len(TxtName.Text) < 6 Or Len(TxtName.Text) > 16 Then MsgBox "姓名应在6~16个字符之间!", vbInformation + vbOKOnly, "数据输入错误": Exit Sub
  
  Name = NameProc(UCase(TxtName.Text))
  If Len(Name) < 6 Then MsgBox "该姓名无法注册,请更换!", vbInformation + vbOKOnly, "数据输入错误": Exit Sub
  
  For i = 65 To 90
      z = Chr(i): If z = "J" Then z = "I"
      If InStr(1, Name, z) = 0 Then Name = Name & z
  Next i
  Name = Left(Name, 25)
  
  For SNPos = 1 To 14 Step 2
      a = Mid(SC, SNPos, 1)
      b = Mid(SC, SNPos + 1, 1)
      For i = 25 To 1 Step -1
          If Mid(Name, i, 1) = a Then
              For j = 25 To 1 Step -1
                  If Mid(Name, j, 1) = b Then
                      Succ = Find(i, j, Name)
                      If Succ = True Then Exit For
                  End If
              Next j
              If Succ = True Then Exit For
          End If
      Next i
  Next SNPos
  
  For i = 1 To 14
      If SN(i) = "" Then MsgBox "该姓名无法注册,请更换!", vbInformation + vbOKOnly, "算法错误": Exit Sub
  Next i
  
  For i = 1 To 14
      TxtSN.Text = TxtSN.Text & SN(i)
  Next i
  
  End Sub
  
  Private Sub Form_Load()
  Me.Icon = LoadPicture("")
  End Sub
  
  Function NameProc(Name As String) As String
  
  Dim n As Integer
  For i = 2 To Len(Name)
      If i > Len(Name) Then n = Len(Name) Else n = i
      For k = 1 To n - 1
          If Mid(Name, k, 1) = Mid(Name, i, 1) Then
              If k <= i Then
                  Name = Left(Name, i - 1) & Right(Name, Len(Name) - i)
              Else
                  Name = Left(Name, Len(Name) - 1)
              End If
          End If
      Next k
  Next i
  
  NameProc = Name
  
  End Function
  
  Function Find(apos As Integer, bpos As Integer, Name As String) As Boolean
  
  Dim xa As Integer
  Dim xb As Integer
  Dim ya As Integer
  Dim yb As Integer
  Dim z As Integer
  Dim a As String
  Dim b As String
  
  xa = (apos - 1) \ 5: xb = apos Mod 5: If xb = 0 Then xb = 5
  xb = xb - 1
  ya = (bpos - 1) \ 5: yb = bpos Mod 5: If yb = 0 Then yb = 5
  yb = yb - 1
  If xa = ya Then
      If xb = 4 Then xb = 0 Else xb = xb + 1
      If yb = 4 Then yb = 0 Else yb = yb + 1
  Else
      If xb = yb Then
          If xa = 4 Then xa = 0 Else xa = xa + 1
          If ya = 4 Then ya = 0 Else ya = ya + 1
      Else
          z = xb: xb = yb: yb = z
      End If
  End If
  
  a = Mid(Name, xa * 5 + xb + 1, 1): If InStr(xa * 5 + xb + 2, Name, a) <> 0 Then Find = False: Exit Function
  b = Mid(Name, ya * 5 + yb + 1, 1): If InStr(ya * 5 + yb + 2, Name, b) <> 0 Then Find = False: Exit Function
  SN(SNPos) = a
  SN(SNPos + 1) = b
  Find = True
  
  End Function
  
--------------------------------------------------------------------------------
【经验总结】
  做分析是一件很辛苦的事情,需以持久的耐心和坚定的毅力才能成功。
  
  这篇文章看似简单,却耗费了我十几天的时间(中间有考试,而且自己水平不足是主要原因)
  
  希望能给大家一点帮助。
  
--------------------------------------------------------------------------------

                                                       2007年07月17日 14:37:50


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (3)
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
2
沙发``支持
2007-7-17 17:55
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
汗  ,
没占到沙发 也要前3啊   
打大菜的屁屁  这么快
2007-7-17 21:31
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
汗。。。过24小时。。又不能发贴。。哎。。限制真多
2007-7-20 15:53
0
游客
登录 | 注册 方可回帖
返回
//