在论坛潜水了好长时间,终于忍不住想发表点什么了。(不然良心不安啊!
)
这一篇算是偶的处女原创帖了,给大家带来的是一片关于《是男人就撑过20秒》这个游戏的分析和Patch。本人菜鸟一只,只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
先简单说说《是男人就撑过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了。(程序很简单,也没有什么注释~~
)
.386
.model flat , stdcall
option casemap : none
;--------------------------------------------------------------------------------
include windows.inc
include kernel32.inc
include user32.inc
include advapi32.inc
includelib kernel32.lib
includelib user32.lib
includelib advapi32.lib
;--------------------------------------------------------------------------------
IDD_DLG equ 1000
IDC_BTN equ 1001
IDC_STC equ 1002
;--------------------------------------------------------------------------------
.data?
hInstance dd ?
hToken dd ?
luid LUID <>
TokenPri TOKEN_PRIVILEGES <>
;--------------------------------------------------------------------------------
.data
szPriText db "提权失败",0
szFWText db "请先运行游戏程序",0
dwAddress dd 00403616h
bPatch db 0ebh
bRestore db 74h
szWindowName db "摿孭",0
szStart db "Start Cheat",0
szStop db "Stop Cheat",0
bCheat db 0
szDebug db "SeSecurityPrivilege",0
;--------------------------------------------------------------------------------
.code
_WriteProc proc hwndDlg,lpBuffer,dwSize
LOCAL pid,hHandle,tghwnd
invoke FindWindow,NULL,addr szWindowName
mov tghwnd,eax
.if eax == NULL
invoke MessageBox,hwndDlg,addr szFWText,NULL,MB_OK
mov eax,FALSE
ret
.endif
invoke GetWindowThreadProcessId,tghwnd,addr pid
invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,pid
mov hHandle,eax
invoke WriteProcessMemory,hHandle,dwAddress,lpBuffer,dwSize,NULL
ret
_WriteProc endp
_Privilege proc hwndDlg
invoke GetCurrentProcess
invoke OpenProcessToken,eax,TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY ,addr hToken
invoke LookupPrivilegeValue,NULL,addr szDebug,addr TokenPri.Privileges.Luid
mov TokenPri.PrivilegeCount,1
mov TokenPri.Privileges.Attributes,SE_PRIVILEGE_ENABLED
invoke AdjustTokenPrivileges,hToken,FALSE,addr TokenPri,sizeof TokenPri,NULL,NULL
.if eax == FALSE
invoke MessageBox,hwndDlg,addr szPriText,NULL,MB_OK
.endif
ret
_Privilege endp
_ProcDlg proc uses ebx edi esi hwndDlg,uMsg,wParam,lParam
mov eax,uMsg
.if eax == WM_CLOSE
invoke EndDialog,hwndDlg,NULL
.elseif eax == WM_INITDIALOG
invoke _Privilege,hwndDlg
.elseif eax == WM_COMMAND
mov eax,wParam
.if ax == IDC_BTN
.if bCheat == 0
invoke _WriteProc,hwndDlg,addr bPatch,1
.if eax == TRUE
invoke SetDlgItemText,hwndDlg,IDC_BTN,addr szStop
mov bCheat,1
.endif
.else
invoke _WriteProc,hwndDlg,addr bRestore,1
invoke SetDlgItemText,hwndDlg,IDC_BTN,addr szStart
mov bCheat,0
.endif
.endif
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
_ProcDlg endp
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke DialogBoxParam,hInstance,IDD_DLG,NULL,addr _ProcDlg,NULL
invoke ExitProcess,NULL
end start
这样,我们就随随便便撑过20秒了。o(∩_∩)o...哈哈!
程序的源码和游戏我都放在附件里了,有兴趣的朋友可以玩玩~~~
[课程]Android-CTF解题方法汇总!