【文章标题】: 有点数学的易解软体
【文章作者】: P_O_K_E_R
【作者邮箱】: p_o_k_e_r@sohu.com
【软件名称】: Chesses V1.01
【下载地址】: http://chinesecheckers.vegard2.no/chesses_execute.exe
【保护方式】: 序列号
【编写语言】: C++
【使用工具】: OllyICE
【操作平台】: WinXP
【软件介绍】: 黑白连珠跳中国际象棋五合一
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  很快定位于:
  00417FE0  |.  FF15 0CB34100 call    dword ptr [<&USER32.GetWindowTextA>]
  往外跳几下就看到:
  0040305F   .  E8 C5130100   call    00414429
  00403064   .  8B47 60       mov     eax, dword ptr [edi+60]
  00403067   .  50            push    eax
  00403068   .  E8 F3110000   call    00404260
  0040306D   .  83C4 04       add     esp, 4
  00403070   .  85C0          test    eax, eax
  00403072   .  0F84 90000000 je      00403108                 ;爆点
  注册判断位置很明显:
  00404260  /$  83EC 50         sub     esp, 50
  00404263  |.  83C9 FF         or      ecx, FFFFFFFF
  00404266  |.  33C0            xor     eax, eax
  00404268  |.  8D5424 00       lea     edx, dword ptr [esp]
  0040426C  |.  56              push    esi
  0040426D  |.  57              push    edi
  0040426E  |.  8B7C24 5C       mov     edi, dword ptr [esp+5C]
  堆栈 ss:[0012C8A0]=003F72F8, (ASCII "12345678")
  00404272  |.  F2:AE           repne   scas byte ptr es:[edi]
  00404274  |.  F7D1            not     ecx
  00404276  |.  2BF9            sub     edi, ecx
  00404278  |.  8BC1            mov     eax, ecx
  0040427A  |.  8BF7            mov     esi, edi
  0040427C  |.  8BFA            mov     edi, edx
  0040427E  |.  C1E9 02         shr     ecx, 2
  00404281  |.  F3:A5           rep     movs dword ptr es:[edi], dword ptr [esi]
  00404283  |.  8BC8            mov     ecx, eax
  00404285  |.  33C0            xor     eax, eax
  00404287  |.  83E1 03         and     ecx, 3
  0040428A  |.  F3:A4           rep     movs byte ptr es:[edi], byte ptr [esi]
  将字符串转到临时位置:003F72F8->0012C84C
  0040428C  |.  8D7C24 08       lea     edi, dword ptr [esp+8]
  00404290  |.  83C9 FF         or      ecx, FFFFFFFF
  00404293  |.  F2:AE           repne   scas byte ptr es:[edi]
  00404295  |.  F7D1            not     ecx
  00404297  |.  49              dec     ecx
  00404298  |.  83F9 08         cmp     ecx, 8
  0040429B  |.  74 06           je      short 004042A3
  要求字符串为八字节长
  0040429D  |.  5F              pop     edi
  0040429E  |.  5E              pop     esi
  0040429F  |.  83C4 50         add     esp, 50
  004042A2  |.  C3              retn
  004042A3  |>  8D4C24 0C       lea     ecx, dword ptr [esp+C]
  004042A7  |.  C64424 10 00    mov     byte ptr [esp+10], 0
  004042AC  |.  51              push    ecx
  004042AD  |.  E8 481D0000     call    00405FFA
  跟入:
  00405FFA  /$  FF7424 04       push    dword ptr [esp+4]
  00405FFE  |.  E8 6CFFFFFF     call    00405F6F
  00406003  |.  59              pop     ecx
  00406004  \.  C3              retn
  压进的是炼码后半边'5678'。再入:
  00405F6F  /$  53              push    ebx
  00405F70  |.  55              push    ebp
  00405F71  |.  56              push    esi
  00405F72  |.  57              push    edi
  00405F73  |.  8B7C24 14       mov     edi, dword ptr [esp+14]
  堆栈 ss:[0012C838]=0012C850, (ASCII "5678")
  00405F77  |>  833D DC244200 0>/cmp     dword ptr [4224DC], 1
  数据 ds:[004224DC]=1
  00405F7E  |.  7E 0F           |jle     short 00405F8F
  00405F80  |.  0FB607          |movzx   eax, byte ptr [edi]
  00405F83  |.  6A 08           |push    8
  00405F85  |.  50              |push    eax
  00405F86  |.  E8 0D360000     |call    00409598
  00405F8B  |.  59              |pop     ecx
  00405F8C  |.  59              |pop     ecx
  00405F8D  |.  EB 0F           |jmp     short 00405F9E
  00405F8F  |>  0FB607          |movzx   eax, byte ptr [edi]
  00405F92  |.  8B0D D0224200   |mov     ecx, dword ptr [4222D0]         ;  chesses.004222DA
  00405F98  |.  8A0441          |mov     al, byte ptr [ecx+eax*2]
  这是比较有意思的地方,查表转换:
  比如第一个:
  ds:[00422344]=84
  al=35 ('5')
  表格如下:
  004222DA    0020   0020   0020   0020   0020   0020   0020   0020
  004222EA    0020   0028   0028   0028   0028   0028   0020   0020
  004222FA    0020   0020   0020   0020   0020   0020   0020   0020
  0042230A    0020   0020   0020   0020   0020   0020   0020   0020
  0042231A    0048   0010   0010   0010   0010   0010   0010   0010
  0042232A    0010   0010   0010   0010   0010   0010   0010   0010
  0042233A    0084   0084   0084   0084   0084   0084   0084   0084
  0042234A    0084   0084   0010   0010   0010   0010   0010   0010
  0042235A    0010   0081   0081   0081   0081   0081   0081   0001
  0042236A    0001   0001   0001   0001   0001   0001   0001   0001
  0042237A    0001   0001   0001   0001   0001   0001   0001   0001
  0042238A    0001   0001   0001   0010   0010   0010   0010   0010
  0042239A    0010   0082   0082   0082   0082   0082   0082   0002
  004223AA    0002   0002   0002   0002   0002   0002   0002   0002
  004223BA    0002   0002   0002   0002   0002   0002   0002   0002
  004223CA    0002   0002   0002   0010   0010   0010   0010   0020
  004223DA    0000   0000   0000   0000   0000   0000   0000   0000
  004223EA    0000   0000   0000   0000   0000   0000   0000   0000
  表格再下面部分都是零。
  00405F9B  |.  83E0 08         |and     eax, 8
  00405F9E  |>  85C0            |test    eax, eax
  00405FA0  |.  74 03           |je      short 00405FA5
  00405FA2  |.  47              |inc     edi
  00405FA3  |.^ EB D2           \jmp     short 00405F77
  00405FA5  |>  0FB637          movzx   esi, byte ptr [edi]
  00405FA8  |.  47              inc     edi
  00405FA9  |.  83FE 2D         cmp     esi, 2D
  00405FAC  |.  8BEE            mov     ebp, esi
  00405FAE  |.  74 05           je      short 00405FB5
  00405FB0  |.  83FE 2B         cmp     esi, 2B
  00405FB3  |.  75 04           jnz     short 00405FB9
  00405FB5  |>  0FB637          movzx   esi, byte ptr [edi]
  00405FB8  |.  47              inc     edi
  00405FB9  |>  33DB            xor     ebx, ebx
  00405FBB  |>  833D DC244200 0>/cmp     dword ptr [4224DC], 1
  00405FC2  |.  7E 0C           |jle     short 00405FD0
  00405FC4  |.  6A 04           |push    4
  00405FC6  |.  56              |push    esi
  00405FC7  |.  E8 CC350000     |call    00409598
  00405FCC  |.  59              |pop     ecx
  00405FCD  |.  59              |pop     ecx
  00405FCE  |.  EB 0B           |jmp     short 00405FDB
  00405FD0  |>  A1 D0224200     |mov     eax, dword ptr [4222D0]
  00405FD5  |.  8A0470          |mov     al, byte ptr [eax+esi*2]
  00405FD8  |.  83E0 04         |and     eax, 4
  00405FDB  |>  85C0            |test    eax, eax
  00405FDD  |.  74 0D           |je      short 00405FEC
  00405FDF  |.  8D049B          |lea     eax, dword ptr [ebx+ebx*4]
  00405FE2  |.  8D5C46 D0       |lea     ebx, dword ptr [esi+eax*2-30]
  第一次经过寄存器为:
  EAX 00000000
  ECX 004222DA
  EDX 0012C84C ASCII "12345678"
  EBX 00000000
  ESP 0012C824
  EBP 00000035
  ESI 00000035
  EDI 0012C851 ASCII "678"
  EIP 00405FE2 chesses.00405FE2
  上面两句合起来是ebx=esi+5*2*ebx-30h......
  00405FE6  |.  0FB637          |movzx   esi, byte ptr [edi]
  00405FE9  |.  47              |inc     edi
  00405FEA  |.^ EB CF           \jmp     short 00405FBB
  00405FEC  |>  83FD 2D         cmp     ebp, 2D
  00405FEF  |.  8BC3            mov     eax, ebx
  00405FF1  |.  75 02           jnz     short 00405FF5
  00405FF3  |.  F7D8            neg     eax
  00405FF5  |>  5F              pop     edi
  00405FF6  |.  5E              pop     esi
  00405FF7  |.  5D              pop     ebp
  00405FF8  |.  5B              pop     ebx
  00405FF9  \.  C3              retn
  虽然很有意思,但一见乘十便不免偷了懒,跳出看一看。
  略略一算,就知是把四个数字字符转成十六进制数,结果为 eax=162Eh=5678.
  004042B2  |.  8D5424 0C       lea     edx, dword ptr [esp+C]
  004042B6  |.  8BF0            mov     esi, eax
  004042B8  |.  52              push    edx
  压入的是后半部转换结果。
  004042B9  |.  C64424 14 00    mov     byte ptr [esp+14], 0
  004042BE  |.  E8 371D0000     call    00405FFA
  同样,将前半部转得eax=04D2h=1234.
  这个转换方法很特别,有空一下要看看。
  004042C3  |.  6A 61           push    61
  004042C5  |.  56              push    esi
  004042C6  |.  8BF8            mov     edi, eax
  004042C8  |.  E8 230B0000     call    00404DF0
  对后半部转换结果的处理,跟入:
  00404DF0  /$  56            push    esi
  00404DF1  |.  8B7424 0C     mov     esi, dword ptr [esp+C]
  00404DF5  |.  56            push    esi
  00404DF6  |.  E8 C5FFFFFF   call    00404DC0
  再跟入:
  00404DC0  /$  53            push    ebx
  00404DC1  |.  56            push    esi
  00404DC2  |.  57            push    edi
  00404DC3  |.  8B7C24 10     mov     edi, dword ptr [esp+10]
  00404DC7  |.  33F6          xor     esi, esi
  00404DC9  |.  33C9          xor     ecx, ecx
  00404DCB  |>  03CF          add     ecx, edi
  00404DCD  |.  BB C01E0000   mov     ebx, 1EC0
  00404DD2  |.  8BC1          mov     eax, ecx
  00404DD4  |.  46            inc     esi
  00404DD5  |.  99            cdq
  00404DD6  |.  F7FB          idiv    ebx
  00404DD8  |.  83FA 01       cmp     edx, 1
  00404DDB  |.^ 75 EE         jnz     short 00404DCB
  00404DDD  |.  8BC6          mov     eax, esi
  00404DDF  |.  5F            pop     edi
  00404DE0  |.  5E            pop     esi
  00404DE1  |.  5B            pop     ebx
  00404DE2  \.  C3            retn
  上面这个函数只是判断61h这个数能不能符合:
  存在整数 k 使得 (61h*k)%(1EC0h)=1 
  看看后面语句处理就发现,好像上面那函数无所谓。
  00404DFB  |.  83C4 04       add     esp, 4
  00404DFE  |.  B8 01000000   mov     eax, 1
  00404E03  |.  85F6          test    esi, esi
  00404E05  |.  7E 19         jle     short 00404E20
  00404E07  |.  8BCE          mov     ecx, esi
  00404E09  |.  8B7424 08     mov     esi, dword ptr [esp+8]
  00404E0D  |.  57            push    edi
  00404E0E  |>  0FAFC6        /imul    eax, esi
  00404E11  |.  33D2          |xor     edx, edx
  00404E13  |.  BF 731F0000   |mov     edi, 1F73
  00404E18  |.  F7F7          |div     edi
  00404E1A  |.  49            |dec     ecx
  00404E1B  |.  8BC2          |mov     eax, edx
  00404E1D  |.^ 75 EF         \jnz     short 00404E0E
  00404E1F  |.  5F            pop     edi
  00404E20  |>  5E            pop     esi
  00404E21  \.  C3            retn
  这个循环蛮妙的,结果是某数的61h次方除以1F73h的余数。返回:
  004042CD  |.  33D2            xor     edx, edx
  004042CF  |.  B9 64000000     mov     ecx, 64                 ;就是一百
  004042D4  |.  F7F1            div     ecx
  004042D6  |.  83C4 10         add     esp, 10
  004042D9  |.  83FA 02         cmp     edx, 2
  004042DC  |.  74 08           je      short 004042E6
  上面是对后半部转换处理结果的要求。
  004042DE  |.  5F              pop     edi
  004042DF  |.  33C0            xor     eax, eax
  004042E1  |.  5E              pop     esi
  004042E2  |.  83C4 50         add     esp, 50
  004042E5  |.  C3              retn
  下面对前半部转换结果的处理:
  004042E6  |>  6A 61           push    61
  004042E8  |.  57              push    edi
  004042E9  |.  E8 020B0000     call    00404DF0
  下面是对前半部转换处理结果的要求:
  004042EE  |.  33D2            xor     edx, edx
  004042F0  |.  B9 64000000     mov     ecx, 64
  004042F5  |.  F7F1            div     ecx
  004042F7  |.  83C4 08         add     esp, 8
  004042FA  |.  33C0            xor     eax, eax
  004042FC  |.  5F              pop     edi
  004042FD  |.  5E              pop     esi
  004042FE  |.  83FA 03         cmp     edx, 3
  如果两个要求都满足就到达这。
  00404301  |.  0F94C0          sete    al
  00404304  |.  83C4 50         add     esp, 50
  00404307  \.  C3              retn
  综上所述,序列号 XY 的要求就是:
  ((X^97)%8051)%100=3
  ((Y^97)%8051)%100=2
  (0<X,Y<=9999)
  解方程便得序列号,好,完成。注册机我已写好在附件中了。
  
--------------------------------------------------------------------------------
【经验总结】
  回顾一下:这些过程中使得一看的是查表进制转换 00405F6F 及似没啥用的那个 00404DC0 。
  补充一下:序列号存在 [HKEY_CURRENT_USER\Software\Lzly] ;已使用次数存在 chesses.cfg 。
  软件作者是数学系毕业的,所以算法也有了点数学的痕迹,对于我等数学肓也算是一好练习吧。
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       20XX年01月02日 1:28:12

上传的附件 kengen.7z