解密windows自带游戏"纸牌"的胜利效果
 
       还记得刚刚接触计算机的时候,最先玩的游戏就数"纸牌",不过感觉挺有难度的,现在也一直这么觉得.这是个非常经典的游戏,以至于到现在还有人会用它来打发时间,这也就是为什么我们的系统中会带有它的缘故了.我觉得"纸牌"的胜利效果做得很不错,可是难得一见啊(为什么?就是因为很难取得胜利,至少我没有胜利几次).现在有机会分析一下这个程序,看看这个"效果"隐藏在哪里,而后是"让我一次看个够".
       但是不好入手啊,你先想一想应该从哪里开始?下什么断点?我分析的是这样的:触发胜利效果的条件是,当把最后一张牌移动到顶端区域时,胜利效果就会出现.也就是说当我们把最后一张牌拖放至顶端区域然后"松开鼠标",
目标区域接受并判断是合法牌且为"胜利状态",则调用相应的过程显示胜利效果.所以,我们可以下消息断点:WM_LBUTTONUP,目标窗体是主窗体.
下面开始.
1.获取窗体的回调函数地址
       通常的做法是给RegisterClassExW,RegisterClassW这两个函数下断,通过堆栈提示得到回调函数的地址.
OD载入,
bp RegisterClassW
bp RegisterClassExW
完了之后F9运行.
 
断下一个:
01001D3A  |.  FF15 44110001 call    dword ptr [<&USER32.RegisterClas>; \RegisterClassExW
 
查看堆栈提示:
0007FE28   0007FE9C  \pWndClassEx = 0007FE9C
 
数据跟随0007FE9C
0007FE9C  00000030
0007FEA0  00002008
0007FEA4  010016BD  sol.010016BD
0007FEA8  00000000
......
 
010016BD就是回调过程.
 
F9再运行,又断下一个:
01005F6E  |.  FF15 C8100001 call    dword ptr [<&USER32.RegisterClas>; \RegisterClassW
 
查看堆栈提示:
0007FDF0   0007FDF8  \pWndClass = 0007FDF8
 
数据跟随0007FDF8:
0007FDF8  00000000
0007FDFC  01005EBF  sol.01005EBF
0007FE00  00000000
......
 
01005EBF就是回调过程.
 
 
2.在回调函数里查看处理代码,找到关键点.
 
首先转到:010016BD查看处理函数代码,可以找到对202消息的处理.
 
01001A66  |.  2D 02020000   sub     eax, 202                         ;  Switch (cases 202..204)
01001A6B  |.  0F84 AD000000 je      01001B1E
 
Enter跟随到01001B1E:
 
01001B1E  |> \FF15 FC100001 call    dword ptr [<&USER32.ReleaseCapture>]          ; [ReleaseCapture; Case 202 (WM_LBUTTONUP) of switch 01001A66
01001B24  |.  6A 04         push    4
01001B26  |.  59            pop     ecx
01001B27  \.^ E9 5CFDFFFF   jmp     01001888
 
就对01001B27下断,F9运行,在游戏主界面单击一下,中断在01001B27.
 
跟随至:
01001888  |> /A1 70710001   mov     eax, dword ptr [1007170]              ;  Case 200 (WM_MOUSEMOVE) of switch 01001866
0100188D  |. |3970 4C       cmp     dword ptr [eax+4C], esi
01001890  |. |74 1C         je      short 010018AE
01001892  |> |0FBF55 14     movsx   edx, word ptr [ebp+14]
01001896  |. |8955 F8       mov     dword ptr [ebp-8], edx
01001899  |. |8B55 14       mov     edx, dword ptr [ebp+14]
0100189C  |. |C1EA 10       shr     edx, 10
0100189F  |. |0FBFD2        movsx   edx, dx
010018A2  |. |8955 FC       mov     dword ptr [ebp-4], edx
010018A5  |. |56            push    esi
010018A6  |. |8D55 F8       lea     edx, dword ptr [ebp-8]
010018A9  |. |52            push    edx
010018AA  |. |51            push    ecx
010018AB  |> |50            push    eax
010018AC  |.  FF10          call    dword ptr [eax]                       ;  sol.010054A2
010018AE  |> |FF75 14       push    dword ptr [ebp+14]                    ; /lParam; Default case of switch 01001A8A
010018B1  |. |FF75 10       push    dword ptr [ebp+10]                    ; |wParam
010018B4  |. |57            push    edi                                   ; |Message
010018B5  |. |FF75 08       push    dword ptr [ebp+8]                     ; |hWnd
010018B8  |. |FF15 14110001 call    dword ptr [<&USER32.DefWindowProcW>]  ; \DefWindowProcW
010018BE  |> |5F            pop     edi
010018BF  |. |5E            pop     esi
010018C0  |. |C9            leave
010018C1  |. |C2 1000       retn    10
 
有个关键call: "call    dword ptr [eax]",跟进:
 
010054A2  /$  55            push    ebp
010054A3  |.  8BEC          mov     ebp, esp
010054A5  |.  8B4D 0C       mov     ecx, dword ptr [ebp+C]
010054A8  |.  83F9 0E       cmp     ecx, 0E                               ;  Switch (cases 3..12)
010054AB  |.  7F 7A         jg      short 01005527
010054AD  |.  74 68         je      short 01005517
010054AF  |.  8BC1          mov     eax, ecx
010054B1  |.  83E8 03       sub     eax, 3
010054B4  |.  74 54         je      short 0100550A
010054B6  |.  83E8 03       sub     eax, 3
010054B9  |.  74 36         je      short 010054F1
010054BB  |.  48            dec     eax
010054BC  |.  48            dec     eax
010054BD  |.  74 22         je      short 010054E1
010054BF  |.  83E8 04       sub     eax, 4
010054C2  |.  74 10         je      short 010054D4
010054C4  |.  48            dec     eax
010054C5  |.  75 70         jnz     short 01005537
010054C7  |.  FF75 08       push    dword ptr [ebp+8]                     ;  Case D of switch 010054A8
010054CA  |.  E8 21F9FFFF   call    01004DF0
010054CF  |.  E9 A9000000   jmp     0100557D
010054D4  |>  FF75 08       push    dword ptr [ebp+8]                     ;  Case C of switch 010054A8
010054D7  |.  E8 42F8FFFF   call    01004D1E
010054DC  |.  E9 9C000000   jmp     0100557D
010054E1  |>  FF75 10       push    dword ptr [ebp+10]                    ; /Arg2; Case 8 of switch 010054A8
010054E4  |.  FF75 08       push    dword ptr [ebp+8]                     ; |Arg1
010054E7  |.  E8 90F5FFFF   call    01004A7C                              ; \sol.01004A7C
010054EC  |.  E9 8C000000   jmp     0100557D
010054F1  |>  FF75 14       push    dword ptr [ebp+14]                    ; /Arg4; Case 6 of switch 010054A8
010054F4  |.  FF75 10       push    dword ptr [ebp+10]                    ; |Arg3
010054F7  |.  6A 06         push    6                                     ; |Arg2 = 00000006
010054F9  |.  FF75 08       push    dword ptr [ebp+8]                     ; |Arg1
010054FC  |.  E8 F8DBFFFF   call    010030F9                              ; \sol.010030F9
01005501  |.  85C0          test    eax, eax
01005503  |.  74 05         je      short 0100550A
01005505  |.  33C0          xor     eax, eax
01005507  |.  40            inc     eax
01005508  |.  EB 73         jmp     short 0100557D
0100550A  |>  FF75 10       push    dword ptr [ebp+10]                    ;  Case 3 of switch 010054A8
0100550D  |.  FF75 08       push    dword ptr [ebp+8]
01005510  |.  E8 C8F6FFFF   call    01004BDD
01005515  |.  EB 66         jmp     short 0100557D
01005517  |>  FF75 14       push    dword ptr [ebp+14]                    ;  Case E of switch 010054A8
0100551A  |.  FF75 10       push    dword ptr [ebp+10]
0100551D  |.  FF75 08       push    dword ptr [ebp+8]
01005520  |.  E8 3AFBFFFF   call    0100505F
01005525  |.  EB 56         jmp     short 0100557D
01005527  |>  8BC1          mov     eax, ecx
01005529  |.  83E8 0F       sub     eax, 0F
0100552C  |.  74 41         je      short 0100556F
0100552E  |.  48            dec     eax
0100552F  |.  74 31         je      short 01005562
01005531  |.  48            dec     eax
01005532  |.  74 1E         je      short 01005552
01005534  |.  48            dec     eax
01005535  |.  74 11         je      short 01005548
01005537  |>  FF75 14       push    dword ptr [ebp+14]                    ; /Arg4; Default case of switch 010054A8
0100553A  |.  FF75 10       push    dword ptr [ebp+10]                    ; |Arg3
0100553D  |.  51            push    ecx                                   ; |Arg2
0100553E  |.  FF75 08       push    dword ptr [ebp+8]                     ; |Arg1
01005541  |.  E8 B3DBFFFF   call    010030F9                              ; \sol.010030F9
01005546  |.  EB 35         jmp     short 0100557D
01005548  |>  FF75 08       push    dword ptr [ebp+8]                     ;  Case 12 of switch 010054A8
0100554B  |.  E8 66FAFFFF   call    01004FB6
01005550  |.  EB 2B         jmp     short 0100557D
01005552  |>  FF75 14       push    dword ptr [ebp+14]                    ;  Case 11 of switch 010054A8
01005555  |.  FF75 10       push    dword ptr [ebp+10]
01005558  |.  FF75 08       push    dword ptr [ebp+8]
0100555B  |.  E8 29FCFFFF   call    01005189
01005560  |.  EB 1B         jmp     short 0100557D
01005562  |>  FF75 10       push    dword ptr [ebp+10]                    ;  Case 10 of switch 010054A8
01005565  |.  FF75 08       push    dword ptr [ebp+8]
01005568  |.  E8 96FCFFFF   call    01005203
0100556D  |.  EB 0E         jmp     short 0100557D
0100556F  |>  FF75 14       push    dword ptr [ebp+14]                    ; /Arg3; Case F of switch 010054A8
01005572  |.  FF75 10       push    dword ptr [ebp+10]                    ; |Arg2
01005575  |.  FF75 08       push    dword ptr [ebp+8]                     ; |Arg1
01005578  |.  E8 42FBFFFF   call    010050BF                              ; \sol.010050BF
0100557D  |>  5D            pop     ebp
0100557E  \.  C2 1000       retn    10
 
主要代码就在这里了,经过我分析发现
......
010054C5     /74 70         je      short 01005537
010054C7  |. |FF75 08       push    dword ptr [ebp+8]                     ;  Case D of switch 010054A8
010054CA  |. |E8 21F9FFFF   call    01004DF0
010054CF  |. |E9 A9000000   jmp     0100557D
......
这几句就是关键,跟进call    01004DF0 :
 
 
01004DF0  /$  55            push    ebp
01004DF1  |.  8D6C24 8C     lea     ebp, dword ptr [esp-74]
01004DF5  |.  81EC D8000000 sub     esp, 0D8
01004DFB  |.  A1 70710001   mov     eax, dword ptr [1007170]
01004E00  |.  53            push    ebx
01004E01  |.  56            push    esi
01004E02  |.  57            push    edi
01004E03  |.  33FF          xor     edi, edi
01004E05  |.  57            push    edi
01004E06  |.  6A 07         push    7
01004E08  |.  33F6          xor     esi, esi
01004E0A  |.  6A 0F         push    0F
01004E0C  |.  46            inc     esi
01004E0D  |.  50            push    eax
01004E0E  |.  8935 CC710001 mov     dword ptr [10071CC], esi
01004E14  |.  FF10          call    dword ptr [eax]
01004E16  |.  8B5D 7C       mov     ebx, dword ptr [ebp+7C]
01004E19  |.  897B 04       mov     dword ptr [ebx+4], edi
01004E1C  |.  897B 24       mov     dword ptr [ebx+24], edi
01004E1F  |.  8973 2C       mov     dword ptr [ebx+2C], esi
01004E22  |.  813D 28700001>cmp     dword ptr [1007028], 12E
01004E2C  |.  8945 70       mov     dword ptr [ebp+70], eax
01004E2F  |.  75 33         jnz     short 01004E64
01004E31  |.  6A 54         push    54
01004E33  |.  6A 6B         push    6B
01004E35  |.  8D45 9C       lea     eax, dword ptr [ebp-64]
01004E38  |.  50            push    eax
01004E39  |.  E8 BAD5FFFF   call    010023F8
01004E3E  |.  FF75 70       push    dword ptr [ebp+70]                    ; /Arg2
01004E41  |.  8BF0          mov     esi, eax                              ; |
01004E43  |.  8D7C75 9C     lea     edi, dword ptr [ebp+esi*2-64]         ; |
01004E47  |.  57            push    edi                                   ; |Arg1
01004E48  |.  E8 DED4FFFF   call    0100232B                              ; \sol.0100232B
01004E4D  |.  8D0C47        lea     ecx, dword ptr [edi+eax*2]
01004E50  |.  66:C701 2000  mov     word ptr [ecx], 20
01004E55  |.  41            inc     ecx
01004E56  |.  41            inc     ecx
01004E57  |.  66:C701 2000  mov     word ptr [ecx], 20
01004E5C  |.  41            inc     ecx
01004E5D  |.  41            inc     ecx
01004E5E  |.  8D4406 02     lea     eax, dword ptr [esi+eax+2]
01004E62  |.  EB 05         jmp     short 01004E69
01004E64  |>  8D4D 9C       lea     ecx, dword ptr [ebp-64]
01004E67  |.  33C0          xor     eax, eax
01004E69  |>  83F8 54       cmp     eax, 54
01004E6C  |.  73 0E         jnb     short 01004E7C
01004E6E  |.  6A 54         push    54
01004E70  |.  5A            pop     edx
01004E71  |.  2BD0          sub     edx, eax
01004E73  |.  52            push    edx
01004E74  |.  6A 6A         push    6A
01004E76  |.  51            push    ecx
01004E77  |.  E8 7CD5FFFF   call    010023F8
01004E7C  |>  8D45 9C       lea     eax, dword ptr [ebp-64]
01004E7F  |.  50            push    eax                                   ; /Arg1
01004E80  |.  E8 680F0000   call    01005DED                              ; \sol.01005DED
01004E85  |.  E8 44C5FFFF   call    010013CE
01004E8A  |.  85C0          test    eax, eax
01004E8C  |.  0F84 FA000000 je      01004F8C
01004E92  |.  8D45 44       lea     eax, dword ptr [ebp+44]
01004E95  |.  50            push    eax                                   ; /pRect
01004E96  |.  FF35 3C730001 push    dword ptr [100733C]                   ; |hWnd = 00C30290 ('纸牌',class='Solitaire')
01004E9C  |.  FF15 24110001 call    dword ptr [<&USER32.GetClientRect>]   ; \GetClientRect
01004EA2  |.  8B45 4C       mov     eax, dword ptr [ebp+4C]
01004EA5  |.  8945 5C       mov     dword ptr [ebp+5C], eax
01004EA8  |.  8B45 50       mov     eax, dword ptr [ebp+50]
01004EAB  |.  2B05 0C730001 sub     eax, dword ptr [100730C]
01004EB1  |.  C745 7C B4000>mov     dword ptr [ebp+7C], 0B4
01004EB8  |.  8945 60       mov     dword ptr [ebp+60], eax
01004EBB  |>  8D43 74       /lea     eax, dword ptr [ebx+74]
01004EBE  |.  C745 70 02000>|mov     dword ptr [ebp+70], 2
01004EC5  |.  8945 64       |mov     dword ptr [ebp+64], eax
01004EC8  |>  8B35 F8110001 |/mov     esi, dword ptr [<&msvcrt.rand>]     ;  msvcrt.rand
01004ECE  |.  FFD6          ||call    esi                                 ; [rand
01004ED0  |.  99            ||cdq
01004ED1  |.  6A 6E         ||push    6E
01004ED3  |.  59            ||pop     ecx
01004ED4  |.  F7F9          ||idiv    ecx
01004ED6  |.  8BC2          ||mov     eax, edx
01004ED8  |.  83E8 41       ||sub     eax, 41
01004EDB  |.  8945 54       ||mov     dword ptr [ebp+54], eax
01004EDE  |.  99            ||cdq
01004EDF  |.  33C2          ||xor     eax, edx
01004EE1  |.  2BC2          ||sub     eax, edx
01004EE3  |.  83F8 0F       ||cmp     eax, 0F
01004EE6  |.  7D 07         ||jge     short 01004EEF
01004EE8  |.  C745 54 ECFFF>||mov     dword ptr [ebp+54], -14
01004EEF  |>  FFD6          ||call    esi
01004EF1  |.  99            ||cdq
01004EF2  |.  6A 6E         ||push    6E
01004EF4  |.  59            ||pop     ecx
01004EF5  |.  F7F9          ||idiv    ecx
01004EF7  |.  8B45 64       ||mov     eax, dword ptr [ebp+64]
01004EFA  |.  8B30          ||mov     esi, dword ptr [eax]
01004EFC  |.  8BFA          ||mov     edi, edx
01004EFE  |.  83EF 4B       ||sub     edi, 4B
01004F01  |.  0375 7C       ||add     esi, dword ptr [ebp+7C]
01004F04  |.  8B46 04       ||mov     eax, dword ptr [esi+4]
01004F07  |.  8945 68       ||mov     dword ptr [ebp+68], eax
01004F0A  |.  8B4E 08       ||mov     ecx, dword ptr [esi+8]
01004F0D  |.  894D 6C       ||mov     dword ptr [ebp+6C], ecx
01004F10  |.  EB 4A         ||jmp     short 01004F5C
01004F12  |>  3B45 5C       ||/cmp     eax, dword ptr [ebp+5C]
01004F15  |.  7D 51         |||jge     short 01004F68
01004F17  |.  8D45 68       |||lea     eax, dword ptr [ebp+68]
01004F1A  |.  50            |||push    eax
01004F1B  |.  56            |||push    esi
01004F1C  |.  E8 61D1FFFF   |||call    01002082
01004F21  |.  8B45 54       |||mov     eax, dword ptr [ebp+54]
01004F24  |.  99            |||cdq
01004F25  |.  6A 0A         |||push    0A
01004F27  |.  59            |||pop     ecx
01004F28  |.  F7F9          |||idiv    ecx
01004F2A  |.  0145 68       |||add     dword ptr [ebp+68], eax
01004F2D  |.  8BC7          |||mov     eax, edi
01004F2F  |.  99            |||cdq
01004F30  |.  F7F9          |||idiv    ecx
01004F32  |.  83C7 03       |||add     edi, 3
01004F35  |.  0145 6C       |||add     dword ptr [ebp+6C], eax
01004F38  |.  8B45 6C       |||mov     eax, dword ptr [ebp+6C]
01004F3B  |.  3B45 60       |||cmp     eax, dword ptr [ebp+60]
01004F3E  |.  7E 10         |||jle     short 01004F50
01004F40  |.  85FF          |||test    edi, edi
01004F42  |.  7E 0C         |||jle     short 01004F50
01004F44  |.  8BC7          |||mov     eax, edi
01004F46  |.  F7D8          |||neg     eax
01004F48  |.  C1E0 03       |||shl     eax, 3
01004F4B  |.  99            |||cdq
01004F4C  |.  F7F9          |||idiv    ecx
01004F4E  |.  8BF8          |||mov     edi, eax
01004F50  |>  E8 EEFDFFFF   |||call    01004D43
01004F55  |.  85C0          |||test    eax, eax
01004F57  |.  75 2E         |||jnz     short 01004F87
01004F59  |.  8B45 68       |||mov     eax, dword ptr [ebp+68]
01004F5C  |>  8B0D 08730001 || mov     ecx, dword ptr [1007308]
01004F62  |.  F7D9          |||neg     ecx
01004F64  |.  3BC1          |||cmp     eax, ecx
01004F66  |.^ 7F AA         ||\jg      short 01004F12
01004F68  |>  FF45 70       ||inc     dword ptr [ebp+70]
01004F6B  |.  8345 64 04    ||add     dword ptr [ebp+64], 4
01004F6F  |.  837D 70 06    ||cmp     dword ptr [ebp+70], 6
01004F73  |.^ 0F8C 4FFFFFFF |\jl      01004EC8
01004F79  |.  836D 7C 0C    |sub     dword ptr [ebp+7C], 0C
01004F7D  |.  837D 7C 24    |cmp     dword ptr [ebp+7C], 24
01004F81  |.^ 0F8D 34FFFFFF \jge     01004EBB
01004F87  |>  E8 79C4FFFF   call    01001405
01004F8C  |>  68 FF1F0000   push    1FFF                                  ; /Arg1 = 00001FFF
01004F91  |.  E8 F80E0000   call    01005E8E                              ; \sol.01005E8E
01004F96  |.  E8 0FD2FFFF   call    010021AA
01004F9B  |.  33C0          xor     eax, eax
01004F9D  |.  50            push    eax                                   ; /Arg4 => 00000000
01004F9E  |.  50            push    eax                                   ; |Arg3 => 00000000
01004F9F  |.  6A 0D         push    0D                                    ; |Arg2 = 0000000D
01004FA1  |.  53            push    ebx                                   ; |Arg1
01004FA2  |.  A3 CC710001   mov     dword ptr [10071CC], eax              ; |
01004FA7  |.  E8 4DE1FFFF   call    010030F9                              ; \sol.010030F9
01004FAC  |.  5F            pop     edi
01004FAD  |.  5E            pop     esi
01004FAE  |.  5B            pop     ebx
01004FAF  |.  83C5 74       add     ebp, 74
01004FB2  |.  C9            leave
01004FB3  \.  C2 0400       retn    4
 
        关键代码就在这里了,我就不分析了(有点吃力哦),当然另外一个回调函数也不必看了.看下胜利截图: