扫雷游戏汇编分析手记(一)

最近几天闲来无事,便拿扫雷游戏来练练手。其实扫雷游戏挺简单,对汇编感兴趣的朋友不妨看看。

先做准备工作。

  1. 操作系统:Windows XP with SP2
  2. 调试工具:Windbg
  3. 开发工具:Visual Studio 2008
  4. Windows XP SP2 Symbols

先看winmine.exe细节情况。
用dumpbin看之,发现该程序导入表简单,没有使用MFC和C++的dll,估计是用C写成,呵呵,标准SDK程序。细察之,发现其使用了msvcrt.dll中srand和rand两个函数。估计是用来生成随机的地雷的,决定就从这着手了。另外,该程序只有三个section:.text,.data,.rsrc。果然是中规中矩,毕竟这种小游戏MS也没啥可费力弄的。

然后启动windbg,打开可执行文件C:/windows/system32/winmine.exe。windbg自动停在起始处。下断点,bp msvcrt!srand和bp msvcrt!rand。
g运行,断点msvcrt!srand命中,kv查看堆栈,发现其为

ChildEBP RetAddr  Args to Child              
0007fea4 01003ac4 0000a9b6 7c80b529 000a1eff msvcrt!srand (FPO: [Non-Fpo])
0007fee0 7c930970 7c99e4c0 7c8021b5 7c802011 winmine!InitConst+0x14 (FPO: [Uses EBP] [0,1,4])
0007fee8 7c8021b5 7c802011 7c80b529 000a1eff ntdll!RtlReleasePebLock+0xf (FPO: [0,0,0])
0007feec 7c802011 7c80b529 000a1eff 00000000 kernel32!GetStartupInfoA+0x2a7 (FPO: [Non-Fpo])
0007ff18 0007ffc0 01003f95 01000000 00000000 kernel32!GetStartupInfoA+0x2b9 (FPO: [Non-Fpo])
WARNING: Frame IP not in any known module. Following frames may be wrong.
0007ffc0 7c816d4f 00011970 7c9318f1 7ffd7000 0x7ffc0
0007ffe0 7c8399f2 7c816d58 00000000 00000000 kernel32!BaseProcessStart+0x23 (FPO: [Non-Fpo])
0007ffe8 00000000 00000000 00000000 01003e21 kernel32!TerminateProcess+0x9 (FPO: [Non-Fpo])

可知winmine的WinMain中调用InitConst函数(从名称猜测可能为初始化常量),InitConst又调用了srand。
反汇编WinMain,

0:000> uf winmine!WinMain
winmine!WinMain:
010021f0 55              push    ebp
010021f1 8bec            mov     ebp,esp
010021f3 83ec4c          sub     esp,4Ch
010021f6 8b4508          mov     eax,dword ptr [ebp+8]
010021f9 53              push    ebx
010021fa 56              push    esi
010021fb 57              push    edi
010021fc a3305b0001      mov     dword ptr [winmine!hInst (01005b30)],eax
01002201 e8aa180000      call    winmine!InitConst (01003ab0)
01002206 33db            xor     ebx,ebx
01002208 43              inc     ebx
01002209 33ff            xor     edi,edi
0100220b 837d1407        cmp     dword ptr [ebp+14h],7
0100220f 740c            je      winmine!WinMain+0x2d (0100221d)

winmine!WinMain+0x21:
01002211 837d1402        cmp     dword ptr [ebp+14h],2
01002215 893d385b0001    mov     dword ptr [winmine!bInitMinimized (01005b38)],edi
0100221b 7506            jne     winmine!WinMain+0x33 (01002223)

winmine!WinMain+0x2d:
0100221d 891d385b0001    mov     dword ptr [winmine!bInitMinimized (01005b38)],ebx

winmine!WinMain+0x33:
01002223 8d45f8          lea     eax,[ebp-8]
01002226 50              push    eax
01002227 c745f808000000  mov     dword ptr [ebp-8],8
0100222e c745fcfd160000  mov     dword ptr [ebp-4],16FDh
01002235 ff151c100001    call    dword ptr [winmine!_imp__InitCommonControlsEx (0100101c)]
0100223b 6a64            push    64h
0100223d ff35305b0001    push    dword ptr [winmine!hInst (01005b30)]
01002243 ff15ac100001    call    dword ptr [winmine!_imp__LoadIconW (010010ac)]
01002249 8b0d305b0001    mov     ecx,dword ptr [winmine!hInst (01005b30)]
0100224f 68007f0000      push    7F00h
01002254 57              push    edi
01002255 a3285b0001      mov     dword ptr [winmine!hIconMain (01005b28)],eax
0100225a 897db4          mov     dword ptr [ebp-4Ch],edi
0100225d c745b8c91b0001  mov     dword ptr [ebp-48h],offset winmine!MainWndProc (01001bc9)
01002264 897dbc          mov     dword ptr [ebp-44h],edi
01002267 897dc0          mov     dword ptr [ebp-40h],edi
0100226a 894dc4          mov     dword ptr [ebp-3Ch],ecx
0100226d 8945c8          mov     dword ptr [ebp-38h],eax
01002270 ff15bc100001    call    dword ptr [winmine!_imp__LoadCursorW (010010bc)]
01002276 53              push    ebx
01002277 8945cc          mov     dword ptr [ebp-34h],eax
0100227a ff1560100001    call    dword ptr [winmine!_imp__GetStockObject (01001060)]
01002280 8945d0          mov     dword ptr [ebp-30h],eax
01002283 8d45b4          lea     eax,[ebp-4Ch]
01002286 bea05a0001      mov     esi,offset winmine!szClass (01005aa0)
0100228b 50              push    eax
0100228c 897dd4          mov     dword ptr [ebp-2Ch],edi
0100228f 8975d8          mov     dword ptr [ebp-28h],esi
01002292 ff15cc100001    call    dword ptr [winmine!_imp__RegisterClassW (010010cc)]
01002298 6685c0          test    ax,ax
0100229b 0f849a000000    je      winmine!WinMain+0x14b (0100233b)

winmine!WinMain+0xb1:
010022a1 68f4010000      push    1F4h
010022a6 ff35305b0001    push    dword ptr [winmine!hInst (01005b30)]
010022ac ff15d4100001    call    dword ptr [winmine!_imp__LoadMenuW (010010d4)]
010022b2 68f5010000      push    1F5h
010022b7 ff35305b0001    push    dword ptr [winmine!hInst (01005b30)]
010022bd a3945a0001      mov     dword ptr [winmine!hMenu (01005a94)],eax
010022c2 ff1560110001    call    dword ptr [winmine!_imp__LoadAcceleratorsW (01001160)]
010022c8 894514          mov     dword ptr [ebp+14h],eax
010022cb e8f2080000      call    winmine!ReadPreferences (01002bc2)
010022d0 a1885b0001      mov     eax,dword ptr [winmine!dypAdjust (01005b88)]
010022d5 8b0d205b0001    mov     ecx,dword ptr [winmine!dyWindow (01005b20)]
010022db 8b152c5b0001    mov     edx,dword ptr [winmine!dxWindow (01005b2c)]
010022e1 57              push    edi
010022e2 ff35305b0001    push    dword ptr [winmine!hInst (01005b30)]
010022e8 03c8            add     ecx,eax
010022ea 57              push    edi
010022eb 57              push    edi
010022ec 51              push    ecx
010022ed 8b0d905a0001    mov     ecx,dword ptr [winmine!dxpBorder (01005a90)]
010022f3 03d1            add     edx,ecx
010022f5 52              push    edx
010022f6 8b15b4560001    mov     edx,dword ptr [winmine!Preferences+0x14 (010056b4)]
010022fc 2bd0            sub     edx,eax
010022fe a1b0560001      mov     eax,dword ptr [winmine!Preferences+0x10 (010056b0)]
01002303 52              push    edx
01002304 2bc1            sub     eax,ecx
01002306 50              push    eax
01002307 680000ca00      push    0CA0000h
0100230c 56              push    esi
0100230d 56              push    esi
0100230e 57              push    edi
0100230f ff155c110001    call    dword ptr [winmine!_imp__CreateWindowExW (0100115c)]
01002315 3bc7            cmp     eax,edi
01002317 a3245b0001      mov     dword ptr [winmine!hwndMain (01005b24)],eax
0100231c 7507            jne     winmine!WinMain+0x135 (01002325)

winmine!WinMain+0x12e:
0100231e 68e8030000      push    3E8h
01002323 eb11            jmp     winmine!WinMain+0x146 (01002336)

winmine!WinMain+0x135:
01002325 53              push    ebx
01002326 e825f6ffff      call    winmine!AdjustWindow (01001950)
0100232b e8e4070000      call    winmine!FInitLocal (01002b14)
01002330 85c0            test    eax,eax
01002332 750e            jne     winmine!WinMain+0x152 (01002342)

winmine!WinMain+0x144:
01002334 6a05            push    5

winmine!WinMain+0x146:
01002336 e815160000      call    winmine!ReportErr (01003950)

winmine!WinMain+0x14b:
0100233b 33c0            xor     eax,eax
0100233d e984000000      jmp     winmine!WinMain+0x1d6 (010023c6)

winmine!WinMain+0x152:
01002342 ff35c4560001    push    dword ptr [winmine!Preferences+0x24 (010056c4)]
01002348 e898190000      call    winmine!SetMenuBar (01003ce5)
0100234d e828130000      call    winmine!StartGame (0100367a)
01002352 53              push    ebx
01002353 ff35245b0001    push    dword ptr [winmine!hwndMain (01005b24)]
01002359 ff1534110001    call    dword ptr [winmine!_imp__ShowWindow (01001134)]
0100235f ff35245b0001    push    dword ptr [winmine!hwndMain (01005b24)]
01002365 ff1558110001    call    dword ptr [winmine!_imp__UpdateWindow (01001158)]
0100236b 8b3554110001    mov     esi,dword ptr [winmine!_imp__GetMessageW (01001154)]
01002371 893d385b0001    mov     dword ptr [winmine!bInitMinimized (01005b38)],edi
01002377 eb2b            jmp     winmine!WinMain+0x1b4 (010023a4)

winmine!WinMain+0x189:
01002379 8d45dc          lea     eax,[ebp-24h]
0100237c 50              push    eax
0100237d ff7514          push    dword ptr [ebp+14h]
01002380 ff35245b0001    push    dword ptr [winmine!hwndMain (01005b24)]
01002386 ff1550110001    call    dword ptr [winmine!_imp__TranslateAcceleratorW (01001150)]
0100238c 85c0            test    eax,eax
0100238e 7514            jne     winmine!WinMain+0x1b4 (010023a4)

winmine!WinMain+0x1a0:
01002390 8d45dc          lea     eax,[ebp-24h]
01002393 50              push    eax
01002394 ff154c110001    call    dword ptr [winmine!_imp__TranslateMessage (0100114c)]
0100239a 8d45dc          lea     eax,[ebp-24h]
0100239d 50              push    eax
0100239e ff1548110001    call    dword ptr [winmine!_imp__DispatchMessageW (01001148)]

winmine!WinMain+0x1b4:
010023a4 57              push    edi
010023a5 57              push    edi
010023a6 8d45dc          lea     eax,[ebp-24h]
010023a9 57              push    edi
010023aa 50              push    eax
010023ab ffd6            call    esi
010023ad 85c0            test    eax,eax
010023af 75c8            jne     winmine!WinMain+0x189 (01002379)

winmine!WinMain+0x1c1:
010023b1 e886020000      call    winmine!CleanUp (0100263c)
010023b6 393d5c510001    cmp     dword ptr [winmine!fUpdateIni (0100515c)],edi
010023bc 7405            je      winmine!WinMain+0x1d3 (010023c3)

winmine!WinMain+0x1ce:
010023be e8e8090000      call    winmine!WritePreferences (01002dab)

winmine!WinMain+0x1d3:
010023c3 8b45e4          mov     eax,dword ptr [ebp-1Ch]

winmine!WinMain+0x1d6:
010023c6 5f              pop     edi
010023c7 5e              pop     esi
010023c8 5b              pop     ebx
010023c9 c9              leave
010023ca c21000          ret     10h

可看到其主要作各种初始化工作,呵呵,套路了,比如InitCommonControlsEx,load各种资源,创建窗口,建消息循环等。
有意思的是这行01002201 e8aa180000 call winmine!InitConst (01003ab0),调用InitConst。

另外发现winmine!Preferences,从其使用方法来看,猜测winmine!Preferences为一个用户参数的结构。
程序开始时调用010022cb e8f2080000 call winmine!ReadPreferences (01002bc2)读用户参数。程序结束时调用010023be e8e8090000 call winmine!WritePreferences (01002dab)写用户参数。

0:000> uf winmine!InitConst
winmine!InitConst:
01003ab0 51              push    ecx
01003ab1 55              push    ebp
01003ab2 56              push    esi
01003ab3 57              push    edi
01003ab4 ff1584100001    call    dword ptr [winmine!_imp__GetTickCount (01001084)]
01003aba 0fb7c0          movzx   eax,ax
01003abd 50              push    eax
01003abe ff15ac110001    call    dword ptr [winmine!_imp__srand (010011ac)]
01003ac4 59              pop     ecx
01003ac5 6a20            push    20h
01003ac7 33ed            xor     ebp,ebp
01003ac9 68a05a0001      push    offset winmine!szClass (01005aa0)
01003ace 45              inc     ebp
01003acf 55              push    ebp
01003ad0 e812ffffff      call    winmine!LoadSz (010039e7)
01003ad5 6a20            push    20h
01003ad7 68e05a0001      push    offset winmine!szTime (01005ae0)
01003adc 6a07            push    7
01003ade e804ffffff      call    winmine!LoadSz (010039e7)
01003ae3 6a20            push    20h
01003ae5 68405b0001      push    offset winmine!szDefaultName (01005b40)
01003aea 6a08            push    8
01003aec e8f6feffff      call    winmine!LoadSz (010039e7)
01003af1 8b350c110001    mov     esi,dword ptr [winmine!_imp__GetSystemMetrics (0100110c)]
01003af7 6a04            push    4
01003af9 ffd6            call    esi
01003afb 40              inc     eax
01003afc 6a0f            push    0Fh
01003afe a3805b0001      mov     dword ptr [winmine!dypCaption (01005b80)],eax
01003b03 ffd6            call    esi
01003b05 40              inc     eax
01003b06 6a06            push    6
01003b08 a3345b0001      mov     dword ptr [winmine!dypMenu (01005b34)],eax
01003b0d ffd6            call    esi
01003b0f 40              inc     eax
01003b10 6a05            push    5
01003b12 a3845b0001      mov     dword ptr [winmine!dypBorder (01005b84)],eax
01003b17 ffd6            call    esi
01003b19 40              inc     eax
01003b1a a3905a0001      mov     dword ptr [winmine!dxpBorder (01005a90)],eax
01003b1f 8d44240c        lea     eax,[esp+0Ch]
01003b23 50              push    eax
01003b24 6850590001      push    offset winmine!g_hReg (01005950)
01003b29 33ff            xor     edi,edi
01003b2b 57              push    edi
01003b2c 6819000200      push    20019h
01003b31 57              push    edi
01003b32 57              push    edi
01003b33 57              push    edi
01003b34 6840130001      push    offset winmine!`string' (01001340)
01003b39 6801000080      push    80000001h
01003b3e ff1510100001    call    dword ptr [winmine!_imp__RegCreateKeyExW (01001010)]
01003b44 85c0            test    eax,eax
01003b46 7520            jne     winmine!InitConst+0xb8 (01003b68)

winmine!InitConst+0x98:
01003b48 55              push    ebp
01003b49 57              push    edi
01003b4a 57              push    edi
01003b4b 6a11            push    11h
01003b4d e8d5efffff      call    winmine!ReadInt (01002b27)
01003b52 ff3550590001    push    dword ptr [winmine!g_hReg (01005950)]
01003b58 8bf0            mov     esi,eax
01003b5a ff1514100001    call    dword ptr [winmine!_imp__RegCloseKey (01001014)]
01003b60 3bf7            cmp     esi,edi
01003b62 0f8557010000    jne     winmine!InitConst+0x20f (01003cbf)

winmine!InitConst+0xb8:
01003b68 53              push    ebx
01003b69 6a19            push    19h
01003b6b 6a09            push    9
01003b6d 5e              pop     esi
01003b6e 56              push    esi
01003b6f 56              push    esi
01003b70 6a02            push    2
01003b72 e89bfeffff      call    winmine!ReadIniInt (01003a12)
01003b77 6a1e            push    1Eh
01003b79 56              push    esi
01003b7a 56              push    esi
01003b7b 6a03            push    3
01003b7d a3a8560001      mov     dword ptr [winmine!Preferences+0x8 (010056a8)],eax
01003b82 e88bfeffff      call    winmine!ReadIniInt (01003a12)
01003b87 6a03            push    3
01003b89 57              push    edi
01003b8a 57              push    edi
01003b8b 57              push    edi
01003b8c a3ac560001      mov     dword ptr [winmine!Preferences+0xc (010056ac)],eax
01003b91 e87cfeffff      call    winmine!ReadIniInt (01003a12)
01003b96 bee7030000      mov     esi,3E7h
01003b9b 56              push    esi
01003b9c 6a0a            push    0Ah
01003b9e 6a0a            push    0Ah
01003ba0 55              push    ebp
01003ba1 66a3a0560001    mov     word ptr [winmine!Preferences (010056a0)],ax
01003ba7 e866feffff      call    winmine!ReadIniInt (01003a12)
01003bac bb00040000      mov     ebx,400h
01003bb1 53              push    ebx
01003bb2 57              push    edi
01003bb3 6a50            push    50h
01003bb5 6a04            push    4
01003bb7 a3a4560001      mov     dword ptr [winmine!Preferences+0x4 (010056a4)],eax
01003bbc e851feffff      call    winmine!ReadIniInt (01003a12)
01003bc1 53              push    ebx
01003bc2 57              push    edi
01003bc3 6a50            push    50h
01003bc5 6a05            push    5
01003bc7 a3b0560001      mov     dword ptr [winmine!Preferences+0x10 (010056b0)],eax
01003bcc e841feffff      call    winmine!ReadIniInt (01003a12)
01003bd1 6a03            push    3
01003bd3 57              push    edi
01003bd4 57              push    edi
01003bd5 6a06            push    6
01003bd7 a3b4560001      mov     dword ptr [winmine!Preferences+0x14 (010056b4)],eax
01003bdc e831feffff      call    winmine!ReadIniInt (01003a12)
01003be1 55              push    ebp
01003be2 57              push    edi
01003be3 55              push    ebp
01003be4 6a07            push    7
01003be6 a3b8560001      mov     dword ptr [winmine!Preferences+0x18 (010056b8)],eax
01003beb e822feffff      call    winmine!ReadIniInt (01003a12)
01003bf0 55              push    ebp
01003bf1 57              push    edi
01003bf2 57              push    edi
01003bf3 6a09            push    9
01003bf5 a3bc560001      mov     dword ptr [winmine!Preferences+0x1c (010056bc)],eax
01003bfa e813feffff      call    winmine!ReadIniInt (01003a12)
01003bff 6a02            push    2
01003c01 57              push    edi
01003c02 57              push    edi
01003c03 6a08            push    8
01003c05 a3c0560001      mov     dword ptr [winmine!Preferences+0x20 (010056c0)],eax
01003c0a e803feffff      call    winmine!ReadIniInt (01003a12)
01003c0f 56              push    esi
01003c10 57              push    edi
01003c11 56              push    esi
01003c12 6a0b            push    0Bh
01003c14 a3c4560001      mov     dword ptr [winmine!Preferences+0x24 (010056c4)],eax
01003c19 e8f4fdffff      call    winmine!ReadIniInt (01003a12)
01003c1e 56              push    esi
01003c1f 57              push    edi
01003c20 56              push    esi
01003c21 6a0d            push    0Dh
01003c23 a3cc560001      mov     dword ptr [winmine!Preferences+0x2c (010056cc)],eax
01003c28 e8e5fdffff      call    winmine!ReadIniInt (01003a12)
01003c2d 56              push    esi
01003c2e 57              push    edi
01003c2f 56              push    esi
01003c30 a3d0560001      mov     dword ptr [winmine!Preferences+0x30 (010056d0)],eax
01003c35 6a0f            push    0Fh
01003c37 e8d6fdffff      call    winmine!ReadIniInt (01003a12)
01003c3c 68d8560001      push    offset winmine!Preferences+0x38 (010056d8)
01003c41 6a0c            push    0Ch
01003c43 a3d4560001      mov     dword ptr [winmine!Preferences+0x34 (010056d4)],eax
01003c48 e83afeffff      call    winmine!ReadIniSz (01003a87)
01003c4d 6818570001      push    offset winmine!Preferences+0x78 (01005718)
01003c52 6a0e            push    0Eh
01003c54 e82efeffff      call    winmine!ReadIniSz (01003a87)
01003c59 6858570001      push    offset winmine!Preferences+0xb8 (01005758)
01003c5e 6a10            push    10h
01003c60 e822feffff      call    winmine!ReadIniSz (01003a87)
01003c65 8b35b0100001    mov     esi,dword ptr [winmine!_imp__GetDesktopWindow (010010b0)]
01003c6b ffd6            call    esi
01003c6d 50              push    eax
01003c6e ff152c110001    call    dword ptr [winmine!_imp__GetDC (0100112c)]
01003c74 55              push    ebp
01003c75 57              push    edi
01003c76 8bd8            mov     ebx,eax
01003c78 6a18            push    18h
01003c7a 53              push    ebx
01003c7b ff1530100001    call    dword ptr [winmine!_imp__GetDeviceCaps (01001030)]
01003c81 33c9            xor     ecx,ecx
01003c83 83f802          cmp     eax,2
01003c86 0f95c1          setne   cl
01003c89 51              push    ecx
01003c8a 6a0a            push    0Ah
01003c8c e881fdffff      call    winmine!ReadIniInt (01003a12)
01003c91 53              push    ebx
01003c92 a3c8560001      mov     dword ptr [winmine!Preferences+0x28 (010056c8)],eax
01003c97 ffd6            call    esi
01003c99 50              push    eax
01003c9a ff1528110001    call    dword ptr [winmine!_imp__ReleaseDC (01001128)]
01003ca0 833db856000103  cmp     dword ptr [winmine!Preferences+0x18 (010056b8)],3
01003ca7 5b              pop     ebx
01003ca8 750a            jne     winmine!InitConst+0x204 (01003cb4)

winmine!InitConst+0x1fa:
01003caa e813fcffff      call    winmine!FInitTunes (010038c2)
01003caf a3b8560001      mov     dword ptr [winmine!Preferences+0x18 (010056b8)],eax

winmine!InitConst+0x204:
01003cb4 5f              pop     edi
01003cb5 5e              pop     esi
01003cb6 5d              pop     ebp
01003cb7 83c404          add     esp,4
01003cba e9ecf0ffff      jmp     winmine!WritePreferences (01002dab)

winmine!InitConst+0x20f:
01003cbf 5f              pop     edi
01003cc0 5e              pop     esi
01003cc1 5d              pop     ebp
01003cc2 59              pop     ecx
01003cc3 c3              ret

可发现其就是从注册表中读取各种参数,
重要的是三组值
雷场宽度:winmine!xBoxMac和winmine!Preferences+0xc
雷场高度:winmine!yBoxMac和winmine!Preferences+0x8
雷场雷数:winmine!Preferences+0x4

好,下面就要看看它是如何初始化雷场的了

(待续)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值