先简单说说《是男人就撑过20秒》这个游戏,就是操纵一架飞机躲避飞来的N多子弹,看你能支撑多长时间。(真的很变态)
好,言归正传。
首先,观察游戏,发现一点,那就是每当进入游戏后鼠标就会消失。当游戏结束之后,显示你支撑的时间时,鼠标又出现了。OK,这是一个很好的线索。
用OllyDBG加载游戏,在函数ShowCursor下断。运行游戏后,游戏第一次断这里
004042F0 /$ 53 push ebx
004042F1 |. 56 push esi
004042F2 |. 57 push edi
004042F3 |. 55 push ebp
004042F4 |. 83C4 D0 add esp, -30
004042F7 |. 6A 00 push 0 ; /Show = FALSE
004042F9 |. E8 24050000 call <jmp.&USER32.ShowCursor> ;
/ShowCursor
004042FE |. E8 5D030000 call 00404660
00404303 |. A1 C86D4000 mov eax, dword ptr [406DC8]
那么,这里就应该是游戏开始,鼠标消失用的那个ShowCursor,他的参数为FALSE说明分析没错。好,继续运行,开始游戏,当游戏结束时,不出所料,游戏断下来了。
00404590 /$ 53 push ebx
00404591 |. 83C4 E4 add esp, -1C
00404594 |. 8BD8 mov ebx, eax
00404596 |. 6A 01 push 1 ; /Show = TRUE
00404598 |. E8 85020000 call <jmp.&USER32.ShowCursor> ; /ShowCursor
0040459D |. 833D CC6D4000>cmp dword ptr [406DCC], 0
跟我想的一样,参数为TRUE,鼠标显示出来,这样应该离目标不远了。接着我们看看是哪来在CALL 00404590 。
00403614 |. 85C0 test eax, eax
00403616 |. 74 3B je short 00403653
00403618 |. 83F8 11 cmp eax, 11
0040361B |. 75 17 jnz short 00403634
0040361D |. 33D2 xor edx, edx
0040361F |. 8915 906D4000 mov dword ptr [406D90], edx
00403625 |. A1 DC694000 mov eax, dword ptr [4069DC]
0040362A |. E8 610F0000 call 00404590 ; 就是这里
0040362F |. E9 83040000 jmp 00403AB7
00403634 |> 8B15 806D4000 mov edx, dword ptr [406D80]
0040363A |. 0FB71455 125C>movzx edx, word ptr [edx*2+405C12]
00403642 |. 81C2 00504000 add edx, 00405000
00403648 |. FF05 806D4000 inc dword ptr [406D80]
于是,我将这个函数段跑了一遍,其中有个大循环,应该是初始化子弹的工作(由于那段代码太多,就不贴上来了)。其实上面的代码就是游戏是否结束的关键。我想大家也都看出来了。看这代码的头两句。
00403614 |. 85C0 test eax, eax
00403616 |. 74 3B je short 00403653 ; 很可疑的跳转!
这个跳转刚好跳过我们的结束代码地址00404590,所以不妨吧je改为jmp。保存后,运行游戏。发现飞机已经能够遨游在子弹群之中!!!
好了,既然已经将关键的地方找出来了,接下来就是写一个程序Patch了。(程序很简单,也没有什么注释~~ )