游戏分析之控制处理
继续分析示例游戏的控制处理流程,围绕背景星星、子弹运动、飞机移动及碰撞判断展开,并结合反汇编代码说明各部分的执行关系。
分析消息循环后面的一个最重要的call 00403400,它处理游戏中子弹,背景星星,飞机的运动,和它们的碰撞等。理解了这些做外挂就不成问题了(比如:炸不死的飞机,甚至可以让飞机自动躲子弹)。
流程概述
- 显示一闪一闪的星星
- 控制子弹的运行,控制子弹和飞机的碰撞
- 飞机位移,方向,姿势的控制。
流程分析
004034C1 |. 8B3D FC694000 mov edi, dword ptr [4069FC]
004034C7 |. 8BD0 mov edx, eax
004034C9 |. C1E2 06 shl edx, 6
004034CC |. 8D1492 lea edx, dword ptr [edx+edx*4]
004034CF |. 8B0D 006A4000 mov ecx, dword ptr [406A00]
004034D5 |. 03D1 add edx, ecx
004034D7 |. B9 F0000000 mov ecx, 0F0
004034DC |. 2BC8 sub ecx, eax
004034DE |. 8BC1 mov eax, ecx
004034E0 |. C1E0 06 shl eax, 6
004034E3 |. 8D0480 lea eax, dword ptr [eax+eax*4]
004034E6 |. 85C0 test eax, eax
004034E8 |. 7E 0B jle short 004034F5
004034EA |> 8A0A /mov cl, byte ptr [edx]
004034EC |. 880F |mov byte ptr [edi], cl
004034EE |. 42 |inc edx
004034EF |. 47 |inc edi
004034F0 |. 48 |dec eax
004034F1 |. 85C0 |test eax, eax
004034F3 |.^ 7F F5 \jg short 004034EA4069FC里面放的变量就是前面CreateDIBSection创建的可绘图内存的首地址,上面的操作就是把计算好的星星的位置放入这个可给图内存里(这个内存的DC可以用BitBlt直接贴到前台游戏画面上去)。
004035FB |> \BA 002C0100 mov edx, 12C00
00403600 |. A1 FC694000 mov eax, dword ptr [4069FC]
00403605 |. E8 4AEBFFFF call 00402154
0040360A |> E8 ADF9FFFF call 00402FBC4069FC->可绘图内存,call 00402154是用来清除屏幕的,如果没这个函数的话我们看到的子弹(还有飞机)将的一条线状的慢慢地被拉的很长。
call 00402FBC是用来控制子弹的
跟进去:00402FD2 |. C70424 106E40>mov dword ptr [esp], 00406E10把子弹信息数组的首地址传给了局部变量。
00403040 |> \8B1424 |mov edx, dword ptr [esp]
00403043 |. 8B0424 |mov eax, dword ptr [esp]
00403046 |. 8B0D 806D4000 |mov ecx, dword ptr [406D80]
0040304C |. 8B1A |mov ebx, dword ptr [edx]
0040304E |. 8B50 04 |mov edx, dword ptr [eax+4]
00403051 |. C1EA 06 |shr edx, 6
00403054 |. C1EB 06 |shr ebx, 6
00403057 |. 83EA 04 |sub edx, 4
0040305A |. 83EB 04 |sub ebx, 4
0040305D |. 85C9 |test ecx, ecx
0040305F |. 895424 04 |mov dword ptr [esp+4], edx
00403063 /0F85 D0000000 jnz 00403139把子弹的坐标信息提取出来。mov ebx, dword ptr [edx]提取X坐标,mov edx, dword ptr [eax+4]提取Y坐标。这里的坐标信息是压缩的。通过位移来还原。
00403046 |. 8B0D 806D4000 |mov ecx, dword ptr [406D80]是把全局变量的标识传给了ecx在下面做了判断。这个变量就是用来标识飞机是否死的。如果把上面的jnz改为jmp这个飞机就永远死不了了。我们顺带把子弹的信息格式说一下:
一共15个字节:前4个是X坐标信息,接着4个字节是Y坐标信息,接着1个字节是方向信息。
在下面也会判断飞机是否死亡然后给死亡标识变量,赋值:
00403115 |. /73 12 |jnb short 00403129
00403117 |. |FF05 0C6E4000 |inc dword ptr [406E0C]
0040311D |. |EB 0A |jmp short 00403129
0040311F |> |C705 0C6E4000>|mov dword ptr [406E0C], 1_______________________________________________________________________________
004030D9 |. 8B1424 |mov edx, dword ptr [esp]
004030DC |. C642 09 00 |mov byte ptr [edx+9], 0
004030E0 |. FF0D B46D4000 |dec dword ptr [406DB4]
004030E6 |. A1 B46D4000 |mov eax, dword ptr [406DB4]
004030EB |. 85C0 |test eax, eax
004030ED |. 74 4A |je short 00403139
004030EF |. 0105 B86D4000 |add dword ptr [406DB8], eax
004030F5 |. C705 046E4000>|mov dword ptr [406E04], 64
004030FF |. 8B5424 0C |mov edx, dword ptr [esp+C]
00403103 |. 8B0D 086E4000 |mov ecx, dword ptr [406E08]
00403109 |. 3BD1 |cmp edx, ecx
0040310B |. 73 12 |jnb short 0040311F
0040310D |. A1 0C6E4000 |mov eax, dword ptr [406E0C]
00403112 |. 83F8 0A |cmp eax, 0A
00403115 |. 73 12 |jnb short 00403129
00403117 |. FF05 0C6E4000 |inc dword ptr [406E0C]
0040311D |. EB 0A |jmp short 00403129上面拿飞机和子弹的坐标进行对比。碰撞就在全局标识里赋值了。
这里子弹的运动就是程序上面在子弹信息数组里完成的。
0040328E |. 8B35 FC694000 |mov esi, dword ptr [4069FC]
00403294 |. C1E0 06 |shl eax, 6
00403297 |. 03F3 |add esi, ebx
00403299 |. 8D5424 10 |lea edx, dword ptr [esp+10]
0040329D |. 8D0480 |lea eax, dword ptr [eax+eax*4]
004032A0 |. 03F0 |add esi, eax
004032A2 |. 33FF |xor edi, edi
004032A4 |> 8B4424 04 |/mov eax, dword ptr [esp+4]
004032A8 |. 03C7 ||add eax, edi
004032AA |. 85C0 ||test eax, eax
004032AC |. 72 33 ||jb short 004032E1
004032AE |. 3D F0000000 ||cmp eax, 0F0
004032B3 |. 73 2C ||jnb short 004032E1
004032B5 |. 33C0 ||xor eax, eax
004032B7 |> 8A0A ||/mov cl, byte ptr [edx]
004032B9 |. 84C9 |||test cl, cl
004032BB |. 74 14 |||je short 004032D1
004032BD |. 8BC8 |||mov ecx, eax
004032BF |. 03CB |||add ecx, ebx
004032C1 |. 85C9 |||test ecx, ecx
004032C3 |. 72 0C |||jb short 004032D1
004032C5 |. 81F9 40010000 |||cmp ecx, 140
004032CB |. 73 04 |||jnb short 004032D1
004032CD |. 8A0A |||mov cl, byte ptr [edx]
004032CF |. 880E |||mov byte ptr [esi], cl
004032D1 |> 46 |||inc esi
004032D2 |. 42 |||inc edx
004032D3 |. 40 |||inc eax
004032D4 |. 83F8 04 |||cmp eax, 4
004032D7 |.^ 7C DE ||\jl short 004032B7
004032D9 |. 81C6 3C010000 ||add esi, 13C[4069FC]是游戏的可绘图内存。这样就把子弹的信息画到了内存位图里去了
00403659 |. A1 7C6D4000 mov eax, dword ptr [406D7C]
0040365E |. A8 08 test al, 8
00403660 |. 0F95C2 setne dl
00403663 |. 83E2 01 and edx, 1前面在消息循环里说明了当收到方向按键的时候会操作406D7C里面的变量。在这里把它取出来用于控制飞机的运动和姿势。。。。。。下面代码又有一个switch….case用来根据按键方向来选择飞机的姿势的。可以在OD数据区里查看一下00405b20里的东西会发现可以看到各种飞机飞行或爆炸的姿势
00403775 |> \0115 6C6D4000 add dword ptr [406D6C], edx Default case of switch 0040368A
0040377B |. 0105 706D4000 add dword ptr [406D70], eax
00403781 |. A1 6C6D4000 mov eax, dword ptr [406D6C]将控制方向偏移量(固定的)与飞机当前坐标合成。
004037E5 |> \8B0D 706D4000 mov ecx, dword ptr [406D70]
004037EB |. 8B3D FC694000 mov edi, dword ptr [4069FC]
004037F1 |. C1E1 06 shl ecx, 6
004037F4 |. A1 6C6D4000 mov eax, dword ptr [406D6C]
004037F9 |. 03F8 add edi, eax
004037FB |. 8D0C89 lea ecx, dword ptr [ecx+ecx*4]
004037FE |. 03F9 add edi, ecx
00403800 |. 33F6 xor esi, esi
00403802 |> 33C0 /xor eax, eax
00403804 |> 8A0A |/mov cl, byte ptr [edx]
00403806 |. 84C9 ||test cl, cl
00403808 |. 74 02 ||je short 0040380C
0040380A |. 880F ||mov byte ptr [edi], cl
0040380C |> 47 ||inc edi
0040380D |. 42 ||inc edx
0040380E |. 40 ||inc eax
0040380F |. 83F8 10 ||cmp eax, 10
00403812 |.^ 7C F0 |\jl short 00403804
00403814 |. 81C7 30010000 |add edi, 130
0040381A |. 46 |inc esi
0040381B |. 83FE 10 |cmp esi, 10
0040381E |.^ 7C E2 \jl short 00403802
00403820 |. 33F6 xor esi, esi4069FC是可绘图内存首地址。就这样把飞机的姿势按飞机坐标复制到绘图内存中去了。
00403A87 |> \68 2000CC00 push 0CC0020 /ROP = SRCCOPY
00403A8C |. 6A 00 push 0 |YSrc = 0
00403A8E |. 6A 00 push 0 |XSrc = 0
00403A90 |. 8B0D E0694000 mov ecx, dword ptr [4069E0] |
00403A96 |. 51 push ecx |hSrcDC => NULL
00403A97 |. 68 F0000000 push 0F0 |Height = F0 (240.)
00403A9C |. 68 40010000 push 140 |Width = 140 (320.)
00403AA1 |. 6A 00 push 0 |YDest = 0
00403AA3 |. 6A 00 push 0 |XDest = 0
00403AA5 |. 53 push ebx |hDestDC
00403AA6 |. E8 3D0E0000 call <jmp.&GDI32.BitBlt> \BitBlt最后BitBlt一下就把所有信息画到了游戏前台了。
分析完。