姓名:
电话:
QQ:
学历:

游戏分析之消息处理

发布时间:2010-02-01 18:32   内容发布:武汉科锐软件安全教育机构
从上篇中的注册窗口类的时候可以看出消息处理函数的地址为00402318。从这里也可以看出不太像VC,je,jl的一大堆。
流程概述
1.    WM_CREATE消息,申请空间创建内存图像和游戏绘图DC,以及画出开场的画面。
2.    WM_DESTORY消息,释放空间恢复和释放游戏绘图DC,发送退出消息。
3.    WM_ACTIVATE消息,调整程序的优先级。
4.    WM_PAINT消息,及时刷新屏幕。
5.    WM_KEYDOWN,根据不同的按键调用不同的功能,比如控制游戏
6.    WM_KEYUP,和WM_KEYDOWN相反,主要用来平衡WM_KEYDOWN的控制游戏
流程分析
1.    WM_CREATE
进入事件call
004025BF  |.  68 28040000   push    428                               /HeapSize = 428 (1064.)
004025C4  |.  6A 00         push    0                                 |Flags = 0
004025C6  |.  E8 21220000   call    <jmp.&KERNEL32.GetProcessHeap>    |[GetProcessHeap
004025CB  |.  50            push    eax                               |hHeap
004025CC  |.  E8 15220000   call    <jmp.&KERNEL32.HeapAlloc>         \HeapAlloc
004025D1  |.  8BF0          mov     esieax
004025D3  |.  BA 28000000   mov     edx, 28
004025D8  |.  8BC6          mov     eaxesi
004025DA  |.  E8 75FBFFFF   call    00402154
004025DF  |.  C706 28000000 mov     dword ptr [esi], 28
004025E5  |.  33C9          xor     ecxecx
004025E7  |.  C746 04 40010>mov     dword ptr [esi+4], 140
004025EE  |.  C746 08 F0000>mov     dword ptr [esi+8], 0F0
004025F5  |.  66:C746 0C 01>mov     word ptr [esi+C], 1
004025FB  |.  66:C746 0E 08>mov     word ptr [esi+E], 8
00402601  |.  894E 10       mov     dword ptr [esi+10], ecx
00402604  |.  33DB          xor     ebxebx
00402606  |.  C746 20 10000>mov     dword ptr [esi+20], 10
0040260D  |.  8D46 2A       lea     eaxdword ptr [esi+2A]
00402610  |>  8BD3          mov     edxebx
00402612  |.  8BCA          mov     ecxedx
00402614  |.  80E1 01       and     cl, 1
00402617  |.  C1E1 07       shl     ecx, 7
0040261A  |.  8808          mov     byte ptr [eax], cl
0040261C  |.  8BCB          mov     ecxebx
0040261E  |.  83E1 01       and     ecx, 1
00402621  |.  8BE9          mov     ebpecx
00402623  |.  C1E1 08       shl     ecx, 8
00402626  |.  2BCD          sub     ecxebp
00402628  |.  8848 20       mov     byte ptr [eax+20], cl
0040262B  |.  8BCA          mov     ecxedx
0040262D  |.  80E1 02       and     cl, 2
00402630  |.  80E2 04       and     dl, 4
00402633  |.  C1E1 07       shl     ecx, 7
00402636  |.  8848 FF       mov     byte ptr [eax-1], cl
00402639  |.  8BCB          mov     ecxebx
0040263B  |.  83E1 02       and     ecx, 2
0040263E  |.  8BE9          mov     ebpecx
00402640  |.  C1E1 08       shl     ecx, 8
00402643  |.  2BCD          sub     ecxebp
00402645  |.  C1E2 07       shl     edx, 7
00402648  |.  8848 1F       mov     byte ptr [eax+1F], cl
0040264B  |.  8850 FE       mov     byte ptr [eax-2], dl
0040264E  |.  8BD3          mov     edxebx
00402650  |.  83E2 04       and     edx, 4
00402653  |.  43            inc     ebx
00402654  |.  8BCA          mov     ecxedx
00402656  |.  C1E1 08       shl     ecx, 8
00402659  |.  2BCA          sub     ecxedx
0040265B  |.  8848 1E       mov     byte ptr [eax+1E], cl
0040265E  |.  83C0 04       add     eax, 4
00402661  |.  83FB 08       cmp     ebx, 8
00402664  |.^\7C AA         jl      short 00402610
00402666  |.  C646 46 C0    mov     byte ptr [esi+46], 0C0
0040266A  |.  C646 45 C0    mov     byte ptr [esi+45], 0C0
0040266E  |.  C646 44 C0    mov     byte ptr [esi+44], 0C0
00402672  |.  C646 4A 80    mov     byte ptr [esi+4A], 80
00402676  |.  C646 49 80    mov     byte ptr [esi+49], 80
0040267A  |.  C646 48 80    mov     byte ptr [esi+48], 80
申请堆空间,并在堆空间里写入了bitmap的头信息。
00402681  |.  50            push    eax                               /hWnd
00402682  |.  E8 CB210000   call    <jmp.&USER32.GetDC>               \GetDC
00402687  |.  8BE8          mov     ebpeax
00402689  |.  6A 00         push    0                                 /Offset = 0
0040268B  |.  6A 00         push    0                                 |hSection = NULL
0040268D  |.  68 FC694000   push    004069FC                          |ppBits = game.004069FC
00402692  |.  6A 00         push    0                                 |Usage = DIB_RGB_COLORS
00402694  |.  56            push    esi                               |pBitmapInfo
00402695  |.  55            push    ebp                               |hDC
00402696  |.  E8 3B220000   call    <jmp.&GDI32.CreateDIBSection>     \CreateDIBSection
0040269B  |.  A3 EC694000   mov     dword ptr [4069EC], eax
004026A0  |.  68 F0000000   push    0F0                               /Height = F0 (240.)
004026A5  |.  68 40010000   push    140                               |Width = 140 (320.)
004026AA  |.  55            push    ebp                               |hDC
004026AB  |.  E8 32220000   call    <jmp.&GDI32.CreateCompatibleBitm> \CreateCompatibleBitmap
004026B0  |.  A3 F4694000   mov     dword ptr [4069F4], eax
004026B5  |.  56            push    esi                               /pMemory
004026B6  |.  6A 00         push    0                                 |Flags = 0
004026B8  |.  E8 2F210000   call    <jmp.&KERNEL32.GetProcessHeap>    |[GetProcessHeap
004026BD  |.  50            push    eax                               |hHeap
004026BE  |.  E8 1D210000   call    <jmp.&KERNEL32.HeapFree>          \HeapFree
根据以上的头信息创建内存的位图,绘图的内存首地址指针放在0x004069F4
|||||||||||||||||||||||||||||||||||||||
在游戏开场画面上写上文字、贴上位图。
2.    WM_DESTORY
00402986  |.  50            push    eax                               /pMemory => NULL
00402987  |.  6A 00         push    0                                 |Flags = 0
00402989  |.  E8 5E1E0000   call    <jmp.&KERNEL32.GetProcessHeap>    |[GetProcessHeap
0040298E  |.  50            push    eax                               |hHeap
0040298F  |.  E8 4C1E0000   call    <jmp.&KERNEL32.HeapFree>          \HeapFree
00402994  |.  33D2          xor     edxedx
00402996  |.  8915 006A4000 mov     dword ptr [406A00], edx
0040299C  |>  6A FF         push    -1                                /nSavedDC = FFFFFFFF (-1.)
0040299E  |.  8B0D E0694000 mov     ecxdword ptr [4069E0]           |
004029A4  |.  51            push    ecx                               |hDC => NULL
004029A5  |.  E8 081F0000   call    <jmp.&GDI32.RestoreDC>            \RestoreDC
004029AA  |.  6A FF         push    -1                                /nSavedDC = FFFFFFFF (-1.)
004029AC  |.  A1 E4694000   mov     eaxdword ptr [4069E4]           |
004029B1  |.  50            push    eax                               |hDC => NULL
004029B2  |.  E8 FB1E0000   call    <jmp.&GDI32.RestoreDC>            \RestoreDC
004029B7  |.  6A FF         push    -1                                /nSavedDC = FFFFFFFF (-1.)
004029B9  |.  8B15 E8694000 mov     edxdword ptr [4069E8]           |
004029BF  |.  52            push    edx                               |hDC => NULL
004029C0  |.  E8 ED1E0000   call    <jmp.&GDI32.RestoreDC>            \RestoreDC
释放所申请的堆空间和游戏绘图DC
、、、、、、、、、、、、、、、、、、、、、、、、、、、、
00402A1F  |.  6A 00         push    0                                 /ExitCode = 0
00402A21  |.  8915 906D4000 mov     dword ptr [406D90], edx           |
00402A27  |.  E8 081E0000   call    <jmp.&USER32.PostQuitMessage>     \PostQuitMessage
发送消息通知退出
3.    WM_ACTIVATE
00402394  |> \B8 01000000   mov     eax, 1
00402399  |.  E8 2E230000   call    004046CC
注意上面有为eax传参的操作,跟进call 004046CC会发现:
004046DA  |.  85C0          test    eaxeax
004046DC  |.  74 6D         je      short 0040474B
首先判断eax,然后有分支:
004046F5  |.  6A 01         push    1                                 /Show = TRUE
004046F7  |.  E8 26010000   call    <jmp.&USER32.ShowCursor>          \ShowCursor
004046FC  |.  8B0D CC6D4000 mov     ecxdword ptr [406DCC]
00404702  |.  85C9          test    ecxecx
00404704  |.  74 0D         je      short 00404713
00404706  |.  6A 20         push    20                                /Priority = NORMAL_PRIORITY_CLASS
00404708  |.  E8 F1000000   call    <jmp.&KERNEL32.GetCurrentProcess> |[GetCurrentProcess
0040470D  |.  50            push    eax                               |hProcess
0040470E  |.  E8 C7000000   call    <jmp.&KERNEL32.SetPriorityClass>  \SetPriorityClass
00404713  |>  6A 00         push    0                                 /Priority = THREAD_PRIORITY_NORMAL
00404715  |.  E8 DE000000   call    <jmp.&KERNEL32.GetCurrentThread>  |[GetCurrentThread
0040471A  |.  50            push    eax                               |hThread
0040471B  |.  E8 B4000000   call    <jmp.&KERNEL32.SetThreadPriority> \SetThreadPriority
00404720  |.  68 2000CC00   push    0CC0020                           /ROP = SRCCOPY
00404725  |.  6A 00         push    0                                 |YSrc = 0
00404727  |.  6A 00         push    0                                 |XSrc = 0
00404729  |.  A1 E0694000   mov     eaxdword ptr [4069E0]           |
0040472E  |.  50            push    eax                               |hSrcDC => NULL
0040472F  |.  68 F0000000   push    0F0                               |Height = F0 (240.)
00404734  |.  68 40010000   push    140                               |Width = 140 (320.)
00404739  |.  6A 00         push    0                                 |YDest = 0
0040473B  |.  6A 00         push    0                                 |XDest = 0
0040473D  |.  8B15 E4694000 mov     edxdword ptr [4069E4]           |
00404743  |.  52            push    edx                               |hDestDC => NULL
00404744  |.  E8 9F010000   call    <jmp.&GDI32.BitBlt>               \BitBlt
这些代码的意思是把鼠标显示出来然后把游戏进程的优先级调低(比如说游戏暂停或窗口失去焦点的时候),另一个分支和此完全相反,而本消息适合于另一分支。后面调用这个函数的时候很多。
4.    WM_PAINT
用BeginPaint和EndPaint做了简单的刷新。
5.    WM_KEYDOWN
提取按键信息,比如游戏控制按键,将按键和全局变量[406D7C]以不同的变量作或运算。
如果按键为ESC的话
00402431  |> \B8 01000000   mov     eax, 1                             Case 1B of switch 004023C2
00402436  |.  E8 91220000   call    004046CC
0040243B  |.  6A 06         push    6                                 /ShowState = SW_MINIMIZE
0040243D  |.  8B55 08       mov     edxdword ptr [ebp+8]            |
00402440  |.  52            push    edx                               |hWnd
00402441  |.  E8 D6230000   call    <jmp.&USER32.ShowWindow>          \ShowWindow
就降低游戏程序的优先级,并最小化。
如果按键为ENTER
0040244B  |> \8B0D 846D4000 mov     ecxdword ptr [406D84]            Cases D,20 of switch 004023C2
00402451  |.  83E9 01       sub     ecx, 1                             Switch (cases 0..6)
00402454  |.  72 33         jb      short 00402489
00402456  |.  74 0D         je      short 00402465
这里会把一个全局变量减1并判断,这个全局变量是用来做回车暂停的计数的,从下文的程序里可以看出当暂停11次后就自动死亡,同时它也是用来判断游戏的当前状态的(活动中还是暂停)
进去:
004042F7  |.  6A 00         push    0                                 /Show = FALSE
004042F9  |.  E8 24050000   call    <jmp.&USER32.ShowCursor>          \ShowCursor
把鼠标隐藏。
继续call    00404660进去:
    00404660  /$  B8 106E4000   mov     eax, 00406E10
00404665  |.  33D2          xor     edxedx
00404667  |>  C640 08 FF    /mov     byte ptr [eax+8], 0FF
0040466B  |.  83C0 0F       |add     eax, 0F
0040466E  |.  42            |inc     edx
0040466F  |.  81FA 2C010000 |cmp     edx, 12C
00404675  |.^ 7C F0         \jl      short 00404667
00404677  |.  8B0D C06D4000 mov     ecxdword ptr [406DC0]
把00406E10为首地址的内存每15个字节在偏移为8的位置上写入FF。
其实这个内存就是来存储子弹的信息的。
00404677  |.  8B0D C06D4000 mov     ecxdword ptr [406DC0]
0040467D  |.  83E9 01       sub     ecx, 1                             Switch (cases 0..3)
00404680  |. /72 0A         jb      short 0040468C
00404682  |. |74 14         je      short 00404698
00404684  |. |49            dec     ecx
00404685  |. |74 1D         je      short 004046A4
00404687  |. |49            dec     ecx
00404688  |. |74 26         je      short 004046B0
0040468A  |. |EB 0C         jmp     short 00404698
0040468C  |> \C705 A86D4000>mov     dword ptr [406DA8], 1E
00404696  |.  EB 22         jmp     short 004046BA
00404698  |>  C705 A86D4000>mov     dword ptr [406DA8], 32             Default case of switch 0040467D
004046A2  |.  EB 16         jmp     short 004046BA
004046A4  |>  C705 A86D4000>mov     dword ptr [406DA8], 64             Case 2 of switch 0040467D
004046AE  |.  EB 0A         jmp     short 004046BA
004046B0  |>  C705 A86D4000>mov     dword ptr [406DA8], 0C8            Case 3 of switch 0040467D
根据406DC0里的数据来给406DA8赋予不同的值。其实在后面的程序中可以看出406DC0里的东西就是子弹数量(可能也是难度的一个标识)的标识。而地址406DA8里放的是子弹的数量。
最后是对一些全局变量的初始化
返回(这个函数可以看作为游戏的初始化过程)
往后是对游戏各个地方的初始化,包括场景,各种标记常量。
Copyright©2007-2015 武汉市科锐软件技术有限公司.
公司地址:武汉市东湖新技术开发区关南园一路当代光谷梦工场5号楼十层
鄂ICP备17007538号-1