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

注意到WinMain的这行0100234d e828130000 call winmine!StartGame (0100367a),估计在此启动游戏。

再次运行g,这次断在rand函数,查看堆栈如下。

ChildEBP RetAddr  Args to Child              
0007fea4 01003946 010036d2 00000009 00000000 msvcrt!rand (FPO: [0,0,0])
0007fea8 010036d2 00000009 00000000 01005aa0 winmine!Rnd+0x6 (FPO: [1,0,0])
0007febc 01002352 7c80b529 000a1eff 00000000 winmine!StartGame+0x58 (FPO: [0,0,3])
0007ff1c 01003f95 01000000 00000000 000a1eff winmine!WinMain+0x162 (FPO: [Non-Fpo])
0007ffc0 7c816d4f 00011970 7c9318f1 7ffd7000 winmine!WinMainCRTStartup+0x174 (FPO: [Non-Fpo])
0007fff0 00000000 01003e21 00000000 78746341 kernel32!BaseProcessStart+0x23 (FPO: [Non-Fpo])

果然,是StartGame调用了Rnd,Rnd调用了rand。先反汇编看看StartGame。

0:000> uf winmine!StartGame
winmine!StartGame:
0100367a a1ac560001      mov     eax,dword ptr [winmine!Preferences+0xc (010056ac)]
0100367f 8b0da8560001    mov     ecx,dword ptr [winmine!Preferences+0x8 (010056a8)]
01003685 53              push    ebx
01003686 56              push    esi
01003687 57              push    edi
01003688 33ff            xor     edi,edi
0100368a 3b0534530001    cmp     eax,dword ptr [winmine!xBoxMac (01005334)]
01003690 893d64510001    mov     dword ptr [winmine!fTimer (01005164)],edi
01003696 750c            jne     winmine!StartGame+0x2a (010036a4)

winmine!StartGame+0x1e:
01003698 3b0d38530001    cmp     ecx,dword ptr [winmine!yBoxMac (01005338)]
0100369e 7504            jne     winmine!StartGame+0x2a (010036a4)

winmine!StartGame+0x26:
010036a0 6a04            push    4
010036a2 eb02            jmp     winmine!StartGame+0x2c (010036a6)

winmine!StartGame+0x2a:
010036a4 6a06            push    6

winmine!StartGame+0x2c:
010036a6 5b              pop     ebx
010036a7 a334530001      mov     dword ptr [winmine!xBoxMac (01005334)],eax
010036ac 890d38530001    mov     dword ptr [winmine!yBoxMac (01005338)],ecx
010036b2 e81ef8ffff      call    winmine!ClearField (01002ed5)
010036b7 a1a4560001      mov     eax,dword ptr [winmine!Preferences+0x4 (010056a4)]
010036bc 893d60510001    mov     dword ptr [winmine!iButtonCur (01005160)],edi
010036c2 a330530001      mov     dword ptr [winmine!cBombStart (01005330)],eax

winmine!StartGame+0x4d:
010036c7 ff3534530001    push    dword ptr [winmine!xBoxMac (01005334)]
010036cd e86e020000      call    winmine!Rnd (01003940)
010036d2 ff3538530001    push    dword ptr [winmine!yBoxMac (01005338)]
010036d8 8bf0            mov     esi,eax
010036da 46              inc     esi
010036db e860020000      call    winmine!Rnd (01003940)
010036e0 40              inc     eax
010036e1 8bc8            mov     ecx,eax
010036e3 c1e105          shl     ecx,5
010036e6 f684314053000180 test    byte ptr winmine!rgBlk (01005340)[ecx+esi],80h
010036ee 75d7            jne     winmine!StartGame+0x4d (010036c7)

winmine!StartGame+0x76:
010036f0 c1e005          shl     eax,5
010036f3 8d843040530001  lea     eax,winmine!rgBlk (01005340)[eax+esi]
010036fa 800880          or      byte ptr [eax],80h
010036fd ff0d30530001    dec     dword ptr [winmine!cBombStart (01005330)]
01003703 75c2            jne     winmine!StartGame+0x4d (010036c7)

winmine!StartGame+0x8b:
01003705 8b0d38530001    mov     ecx,dword ptr [winmine!yBoxMac (01005338)]
0100370b 0faf0d34530001  imul    ecx,dword ptr [winmine!xBoxMac (01005334)]
01003712 a1a4560001      mov     eax,dword ptr [winmine!Preferences+0x4 (010056a4)]
01003717 2bc8            sub     ecx,eax
01003719 57              push    edi
0100371a 893d9c570001    mov     dword ptr [winmine!cSec (0100579c)],edi
01003720 a330530001      mov     dword ptr [winmine!cBombStart (01005330)],eax
01003725 a394510001      mov     dword ptr [winmine!cBombLeft (01005194)],eax
0100372a 893da4570001    mov     dword ptr [winmine!cBoxVisit (010057a4)],edi
01003730 890da0570001    mov     dword ptr [winmine!cBoxVisitMac (010057a0)],ecx
01003736 c7050050000101000000 mov dword ptr [winmine!fStatus (01005000)],1
01003740 e825fdffff      call    winmine!UpdateBombCount (0100346a)
01003745 53              push    ebx
01003746 e805e2ffff      call    winmine!AdjustWindow (01001950)
0100374b 5f              pop     edi
0100374c 5e              pop     esi
0100374d 5b              pop     ebx
0100374e c3              ret

该函数先判断当前雷区的高度和宽度是否和用户的所选高度和宽度一致,如果不一致就让winmine!xBoxMac = winmine!Preferences+0xc,winmine!yBoxMac = winmine!Preferences+0x8

然后该函数清扫雷区010036b2 e81ef8ffff call winmine!ClearField (01002ed5)。反汇编ClearField函数

0:000> uf winmine!ClearField
winmine!ClearField:
01002ed5 b860030000      mov     eax,360h

winmine!ClearField+0x5:
01002eda 48              dec     eax
01002edb c680405300010f  mov     byte ptr winmine!rgBlk (01005340)[eax],0Fh
01002ee2 75f6            jne     winmine!ClearField+0x5 (01002eda)

winmine!ClearField+0xf:
01002ee4 8b0d34530001    mov     ecx,dword ptr [winmine!xBoxMac (01005334)]
01002eea 8b1538530001    mov     edx,dword ptr [winmine!yBoxMac (01005338)]
01002ef0 8d4102          lea     eax,[ecx+2]
01002ef3 85c0            test    eax,eax
01002ef5 56              push    esi
01002ef6 7419            je      winmine!ClearField+0x3c (01002f11)

winmine!ClearField+0x23:
01002ef8 8bf2            mov     esi,edx
01002efa c1e605          shl     esi,5
01002efd 8db660530001    lea     esi,winmine!rgBlk+0x20 (01005360)[esi]

winmine!ClearField+0x2e:
01002f03 48              dec     eax
01002f04 c6804053000110  mov     byte ptr winmine!rgBlk (01005340)[eax],10h
01002f0b c6040610        mov     byte ptr [esi+eax],10h
01002f0f 75f2            jne     winmine!ClearField+0x2e (01002f03)

winmine!ClearField+0x3c:
01002f11 8d7202          lea     esi,[edx+2]
01002f14 85f6            test    esi,esi
01002f16 7421            je      winmine!ClearField+0x64 (01002f39)

winmine!ClearField+0x43:
01002f18 8bc6            mov     eax,esi
01002f1a c1e005          shl     eax,5
01002f1d 8d9040530001    lea     edx,winmine!rgBlk (01005340)[eax]
01002f23 8d840841530001  lea     eax,winmine!rgBlk+0x1 (01005341)[eax+ecx]

winmine!ClearField+0x55:
01002f2a 83ea20          sub     edx,20h
01002f2d 83e820          sub     eax,20h
01002f30 4e              dec     esi
01002f31 c60210          mov     byte ptr [edx],10h
01002f34 c60010          mov     byte ptr [eax],10h
01002f37 75f1            jne     winmine!ClearField+0x55 (01002f2a)

winmine!ClearField+0x64:
01002f39 5e              pop     esi
01002f3a c3              ret

现在可看到雷场起始于winmine!rgBlk (01005340),它先把雷场全部填0Fh,然后在所选雷区范围填10h。StartGame清完雷场后,调用Rnd来生成地雷。两次Rnd函数调用的参数分别为winmine!xBoxMac和winmine!yBoxMac。来看看Rnd的情况。

0:000> uf winmine!Rnd
winmine!Rnd:
01003940 ff15b0110001    call    dword ptr [winmine!_imp__rand (010011b0)]
01003946 99              cdq
01003947 f77c2404        idiv    eax,dword ptr [esp+4]
0100394b 8bc2            mov     eax,edx
0100394d c20400          ret     4

很明显,Rnd把rand的返回值变换到winmine!xBoxMac和winmine!yBoxMac的范围中,这样每两次调用Rnd就生成了一个地雷的坐标。然后StartGame测试该坐标是否为80h,如果不是就跳过该坐标(因为该坐标已经标注了),如果是,就把该坐标置成8Fh,表示是雷。StartGame循环这个过程共winmine!cBombStart(winmine!cBombStart初始值为winmine!Preferences+0x4)次。然后StartGame设置一些状态,启动游戏。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值