是男人就撑过20秒的游戏分析+无敌Patch的实现

来源:互联网 发布:中国足球国家队 知乎 编辑:程序博客网 时间:2024/04/19 14:40

先简单说说《是男人就撑过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了。(程序很简单,也没有什么注释~~ )

 

Ring0
  1. .386
  2. .model flat , stdcall
  3. option casemap : none
  4. ;--------------------------------------------------------------------------------
  5. includewindows.inc
  6. includekernel32.inc
  7. includeuser32.inc
  8. includeadvapi32.inc
  9. includelibkernel32.lib
  10. includelibuser32.lib
  11. includelibadvapi32.lib
  12. ;--------------------------------------------------------------------------------
  13. IDD_DLG equ1000
  14. IDC_BTN equ1001
  15. IDC_STC equ1002
  16. ;--------------------------------------------------------------------------------
  17. .data?
  18. hInstancedd?
  19. hTokendd?
  20. luidLUID<>
  21. TokenPriTOKEN_PRIVILEGES<>
  22. ;--------------------------------------------------------------------------------
  23. .data
  24. szPriTextdb"提权失败",0
  25. szFWTextdb"请先运行游戏程序",0
  26. dwAddressdd00403616h
  27. bPatchdb0ebh
  28. bRestoredb74h
  29. szWindowNamedb"摿孭",0
  30. szStartdb"Start Cheat",0
  31. szStopdb"Stop Cheat",0
  32. bCheatdb0
  33. szDebugdb"SeSecurityPrivilege",0
  34. ;--------------------------------------------------------------------------------
  35. .code
  36. _WriteProcprochwndDlg,lpBuffer,dwSize
  37. LOCALpid,hHandle,tghwnd
  38. invokeFindWindow,NULL,addr szWindowName
  39. movtghwnd,eax
  40. .ifeax == NULL
  41. invokeMessageBox,hwndDlg,addr szFWText,NULL,MB_OK
  42. moveax,FALSE
  43. ret
  44. .endif
  45. invokeGetWindowThreadProcessId,tghwnd,addr pid
  46. invokeOpenProcess,PROCESS_ALL_ACCESS,FALSE,pid
  47. movhHandle,eax
  48. invokeWriteProcessMemory,hHandle,dwAddress,lpBuffer,dwSize,NULL
  49. ret
  50. _WriteProc endp
  51. _PrivilegeprochwndDlg
  52. invokeGetCurrentProcess
  53. invokeOpenProcessToken,eax,TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY ,addr hToken
  54. invokeLookupPrivilegeValue,NULL,addr szDebug,addr TokenPri.Privileges.Luid
  55. movTokenPri.PrivilegeCount,1
  56. movTokenPri.Privileges.Attributes,SE_PRIVILEGE_ENABLED
  57. invokeAdjustTokenPrivileges,hToken,FALSE,addr TokenPri,sizeof TokenPri,NULL,NULL
  58. .ifeax == FALSE
  59. invokeMessageBox,hwndDlg,addr szPriText,NULL,MB_OK
  60. .endif
  61. ret
  62. _Privilege endp
  63. _ProcDlgprocuses ebx edi esi hwndDlg,uMsg,wParam,lParam
  64. moveax,uMsg
  65. .ifeax == WM_CLOSE
  66. invokeEndDialog,hwndDlg,NULL
  67. .elseifeax == WM_INITDIALOG
  68. invoke_Privilege,hwndDlg
  69. .elseif eax == WM_COMMAND
  70. moveax,wParam
  71. .ifax == IDC_BTN
  72. .ifbCheat == 0
  73. invoke_WriteProc,hwndDlg,addr bPatch,1
  74. .ifeax == TRUE
  75. invoke SetDlgItemText,hwndDlg,IDC_BTN,addr szStop
  76. movbCheat,1
  77. .endif
  78. .else
  79. invoke_WriteProc,hwndDlg,addr bRestore,1
  80. invokeSetDlgItemText,hwndDlg,IDC_BTN,addr szStart
  81. movbCheat,0
  82. .endif
  83. .endif
  84. .else
  85. moveax,FALSE
  86. ret
  87. .endif
  88. moveax,TRUE
  89. ret
  90. _ProcDlgendp
  91. start:
  92. invokeGetModuleHandle,NULL
  93. movhInstance,eax
  94. invokeDialogBoxParam,hInstance,IDD_DLG,NULL,/addr _ProcDlg,NULL
  95. invokeExitProcess,NULL
  96. endstart

 

这样,我们就随随便便撑过20秒了。o(∩_∩)o...哈哈!

程序的源码和游戏我都放在附件里了,有兴趣的朋友可以玩玩~~~

原创粉丝点击