掃雷遊戲作弊逆向菜文
標 題: 掃雷遊戲作弊逆向菜文
發帖人:qINGfENG
時 間: 2005-01-14 21:10
詳細資訊:
【目標程式】:Win2000的 Winmine.exe
【作者宣告】:只是感興趣,沒有其他目的。失誤之處敬請諸位大俠賜教!
【除錯環境】:Win2000、Ollydbg1.10、ExeScope
【逆向原因】:我有一舍友,十分精於掃雷遊戲,閒暇之時與其比試,總是敗多勝少,遂逆
向一熱鍵作弊(本文改成了選單)功能,後常勝 ^_^ 。今日無事,逆向菜
文一篇,希望能對剛入門的菜鳥朋友們有些許幫助。
【逆向過程】:
――――――――――――――――――――――――――――――――――――――――
一、分析
1、弄清程式的流程,將自己的處理程式碼,掛在訊息響應流程中。
// 用DefWindowProcW下斷,然後向上翻看,即可看到訊息響應流程
// 點選選單後,會來到如下程式碼處
010019AD > \8B4D 10 mov ecx, dword ptr ss:[ebp+10] ; 點選的選單ID
010019B0 . 0FB7C1 movzx eax, cx
010019B3 . 3D 0B020000 cmp eax, 20B
010019B8 . 7F 76 jg short winmine.01001A30 ; 大於 0x20B 跳到後邊
010019BA . 3D 09020000 cmp eax, 209
010019BF . 7D 2D jge short winmine.010019EE
010019C1 . 2D FE010000 sub eax, 1FE
010019C6 . 74 1C je short winmine.010019E4
010019C8 . 48 dec eax
010019C9 . 48 dec eax
010019CA . 0F85 7C030000 jnz winmine.01001D4C
010019D0 . 33FF xor edi, edi ; Case 200 of switch 010019B3
010019D2 . 57 push edi ; /ShowState => SW_HIDE
010019D3 . FF35 A8520001 push dword ptr ds:[10052A8] ; |hWnd = NULL
010019D9 . FF15 EC100001 call dword ptr ds:[<&USER32.ShowWi>; \ShowWindow
010019DF . E9 A2000000 jmp winmine.01001A86
010019E4 > E8 26190000 call winmine.0100330F ; Case 1FE of switch 010019B3
010019E9 . E9 5E030000 jmp winmine.01001D4C
010019EE > 8D81 F7FDFFFF lea eax, dword ptr ds:[ecx-209] ; Cases 209,20A,20B of switch 010019B3
010019F4 . 66:A3 C0520001 mov word ptr ds:[10052C0], ax
010019FA . 0FB7C0 movzx eax, ax
010019FD . 8D0440 lea eax, dword ptr ds:[eax+eax*2]
01001A00 . C1E0 02 shl eax, 2
01001A03 . 8B88 28500001 mov ecx, dword ptr ds:[eax+100502>
01001A09 . 890D C4520001 mov dword ptr ds:[10052C4], ecx
01001A0F . 8B88 2C500001 mov ecx, dword ptr ds:[eax+100502>
01001A15 . 8B80 30500001 mov eax, dword ptr ds:[eax+100503>
01001A1B . 890D C8520001 mov dword ptr ds:[10052C8], ecx
01001A21 . A3 CC520001 mov dword ptr ds:[10052CC], eax
01001A26 . E8 E4180000 call winmine.0100330F
01001A30 > \B9 4E020000 mov ecx, 24E ;大於 0x20B 跳到這裡
01001A35 > 3BC1 cmp eax, ecx
01001A37 . 0F8F D3000000 jg winmine.01001B10
01001A3D . 0F84 C7000000 je winmine.01001B0A
01001A43 . 2D 0C020000 sub eax, 20C
根據上邊的程式碼,可知,只要從01001A30處(其它地方也可以)跳到我們新增的程式碼中,就可以對訊息進行響應了。
2、如何實現作弊?
// 開局,點選一下,到如下程式碼處,(第一次用PlaySoundW下斷,很容易就能來到這裡)
01003772 |. 833D F4560001 00 cmp dword ptr ds:[10056F4], 0 ; //開始掃雷了麼?
01003779 |. 6A 01 push 1
0100377B |. 5B pop ebx
0100377C |. 75 4A jnz short winmine.010037C8 ; 第一點選?
0100377E |. 833D F0560001 00 cmp dword ptr ds:[10056F0], 0
01003785 |. 75 41 jnz short winmine.010037C8
01003787 |. 53 push ebx
01003788 |. E8 ED050000 call winmine.01003D7A
0100378D |. FF05 F0560001 inc dword ptr ds:[10056F0]
01003793 |. E8 1FF4FFFF call winmine.01002BB7
01003798 |. 6A 00 push 0 ; /Timerproc = NULL
0100379A |. 68 E8030000 push 3E8 ; |Timeout = 1000. ms
0100379F |. 53 push ebx ; |TimerID
010037A0 |. 891D 84510001 mov dword ptr ds:[1005184], ebx ; |
010037A6 |. FF35 A8520001 push dword ptr ds:[10052A8] ; |hWnd = NULL
010037AC |. FF15 6C110001 call dword ptr ds:[<&USER32.SetTim>; \ 設定計時間隔1秒,修改這裡進行時間作弊
// 透過跟蹤發現,對相應行、列對應的記憶體中的一個位元組進行變換,變換後的值高位為1(0x80),
// 表示該位置是雷,GAME OVER, 如果不是雷,則顯示該位置的數字
01003144 /$ 8B4424 08 mov eax, dword ptr ss:[esp+8] ; 行
01003148 |. 53 push ebx
01003149 |. 55 push ebp
0100314A |. 8BC8 mov ecx, eax
0100314C |. 56 push esi
0100314D |. 8B7424 10 mov esi, dword ptr ss:[esp+10] ; 列
01003151 |. C1E1 05 shl ecx, 5
01003154 |. F68431 00570001 80 test byte ptr ds:[ecx+esi+1005700], 80 ; 是雷麼
0100315C |. 8D9431 00570001 lea edx, dword ptr ds:[ecx+esi+1005700]
01003163 |. 57 push edi
01003164 |. 74 6B je short winmine.010031D1 ; 不是雷,跳
01003166 |. 833D F4560001 00 cmp dword ptr ds:[10056F4], 0
0100316D |. 75 55 jnz short winmine.010031C4
0100316F |. 8B2D 685A0001 mov ebp, dword ptr ds:[1005A68]
01003175 |. 6A 01 push 1
01003177 |. 58 pop eax
01003178 |. 3BE8 cmp ebp, eax
0100317A |. 7E 70 jle short winmine.010031EC
0100317C |. 8B1D F8560001 mov ebx, dword ptr ds:[10056F8]
01003182 |. BF 20570001 mov edi, winmine.01005720
01003187 |> 6A 01 /push 1
01003189 |. 59 |pop ecx
0100318A |. 3BD9 |cmp ebx, ecx
0100318C |. 7E 0B |jle short winmine.01003199
0100318E |> F60439 80 |/test byte ptr ds:[ecx+edi], 80
01003192 |. 74 0F ||je short winmine.010031A3
01003194 |. 41 ||inc ecx
01003195 |. 3BCB ||cmp ecx, ebx
01003197 |.^ 7C F5 |\jl short winmine.0100318E
01003199 |> 40 |inc eax
0100319A |. 83C7 20 |add edi, 20
0100319D |. 3BC5 |cmp eax, ebp
0100319F |.^ 7C E6 \jl short winmine.01003187
010031A1 |. EB 49 jmp short winmine.010031EC
010031A3 |> FF7424 18 push dword ptr ss:[esp+18] ; /Arg2
010031A7 |. C602 0F mov byte ptr ds:[edx], 0F ; |
010031AA |. C1E0 05 shl eax, 5 ; |
010031AD |. 56 push esi ; |Arg1
010031AE |. 808C08 00570001 80 or byte ptr ds:[eax+ecx+1005700], 80 ; |
010031B6 |. 8D8408 00570001 lea eax, dword ptr ds:[eax+ecx+1005700] ; |
010031BD |. E8 EDFEFFFF call winmine.010030AF ; \winmine.010030AF
010031C2 |. EB 28 jmp short winmine.010031EC
010031C4 |> 6A 4C push 4C
010031C6 |. 50 push eax
010031C7 |. 56 push esi
010031C8 |. E8 53FCFFFF call winmine.01002E20
010031CD |. 6A 00 push 0
010031CF |. EB 16 jmp short winmine.010031E7
// 不是雷跳到這裡
010031D1 |> 50 push eax ; 行
010031D2 |. 56 push esi ; 列
010031D3 |. E8 D7FEFFFF call winmine.010030AF ; 顯示該位置的數字
010031D8 |. A1 F4560001 mov eax, dword ptr ds:[10056F4] ;
010031DD |. 3B05 FC560001 cmp eax, dword ptr ds:[10056FC]
010031E3 |. 75 07 jnz short winmine.010031EC ; 雷掃完了麼
010031E5 |. 6A 01 push 1
010031E7 |> E8 86FDFFFF call winmine.01002F72 ; 遊戲成功結束
010031EC |> 5F pop edi ; 沒掃完,繼續
010031ED |. 5E pop esi
010031EE |. 5D pop ebp
010031EF |. 5B pop ebx
010031F0 \. C2 0800 retn 8
//根據行、列,呼叫下面過程計算,記憶體中的值如果高位是1(0x80)就是雷
010033E9 /$ 8B4424 08 mov eax, dword ptr ss:[esp+8] //行
010033ED |. 8B4C24 04 mov ecx, dword ptr ss:[esp+4] //列
010033F1 |. C1E0 05 shl eax, 5
010033F4 |. 8D9408 00570001 lea edx, dword ptr ds:[eax+ecx+1005700] //位置
010033FB |. 8A8408 00570001 mov al, byte ptr ds:[eax+ecx+1005700]
01003402 |. 8AC8 mov cl, al
01003404 |. 83E1 1F and ecx, 1F
01003407 |. 83F9 0D cmp ecx, 0D
0100340A |. 75 05 jnz short winmine.01003411
0100340C |. 6A 09 push 9
0100340E |. 59 pop ecx
0100340F |. EB 07 jmp short winmine.01003418
01003411 |> 83F9 0F cmp ecx, 0F
01003414 |. 75 02 jnz short winmine.01003418
01003416 |. 33C9 xor ecx, ecx
01003418 |> 24 E0 and al, 0E0
0100341A |. 0AC1 or al, cl
0100341C |. 8802 mov byte ptr ds:[edx], al
0100341E \. C2 0800 retn 8
//根據行、列,將上面過程變換後記憶體中的值恢復
01003421 /$ 8B4424 08 mov eax, dword ptr ss:[esp+8]
01003425 |. 8B4C24 04 mov ecx, dword ptr ss:[esp+4]
01003429 |. C1E0 05 shl eax, 5
0100342C |. 8D9408 00570001 lea edx, dword ptr ds:[eax+ecx+1005700]
01003433 |. 8A8408 00570001 mov al, byte ptr ds:[eax+ecx+1005700]
0100343A |. 8AC8 mov cl, al
0100343C |. 83E1 1F and ecx, 1F
0100343F |. 83F9 09 cmp ecx, 9
01003442 |. 75 04 jnz short winmine.01003448
01003444 |. 6A 0D push 0D
01003446 |. EB 06 jmp short winmine.0100344E
01003448 |> 85C9 test ecx, ecx
0100344A |. 75 03 jnz short winmine.0100344F
0100344C |. 6A 0F push 0F
0100344E |> 59 pop ecx
0100344F |> 24 E0 and al, 0E0
01003451 |. 0AC1 or al, cl
01003453 |. 8802 mov byte ptr ds:[edx], al
01003455 \. C2 0800 retn 8
――――――――――――――――――――――――――――――――――――――――
二、逆向
1、用ExeScope為Winmine.exe新增一個選單項:ID=0x259=601(大於0x20B),Name="過關"。
2、在Winmine.exe的訊息迴圈中作如下修改,使自己的新增的選單選項能夠被響應。
01001A30 > \B9 4E020000 mov ecx, 24E
01001A35 . 3BC1 cmp eax, ecx
==〉 修改成
01001A30 /E9 4B2F0000 jmp winmine.01004980 //跳轉到自己的處理程式碼處
01001A35 . |3BC1 cmp eax, ecx
3、在01004980處寫入如下程式碼:
下面的程式碼是在Winmine.exe中找了一段全為零的地方寫入的,也可以新增一個節後寫入節中。
01004980 3D 58020000 cmp eax, 258 ;
01004985 7F 0A jg short winmine.01004991 ; > 0x258
01004987 B9 4E020000 mov ecx, 24E ; 恢復原來的程式碼
0100498C ^ E9 A4D0FFFF jmp winmine.01001A35 ; 跳回
01004991 3D 59020000 cmp eax, 259 ; 是否選擇了“過關”
01004996 7F 40 jg short winmine.010049D8 ; > 0x259 ?跳 繼續處理其它
// 下面是過關程式碼
01004998 B8 01000000 mov eax, 1 ; 雙重迴圈遍歷;
0100499D B9 01000000 mov ecx, 1
010049A2 50 push eax
010049A3 51 push ecx
010049A4 50 push eax
010049A5 51 push ecx
010049A6 50 push eax
010049A7 51 push ecx
010049A8 E8 3CEAFFFF call winmine.010033E9 ; 變換
010049AD A8 80 test al, 80 ; 是否為雷
010049AF 75 07 jnz short winmine.010049B8 ;
010049B1 E8 F9E6FFFF call winmine.010030AF ; 不是雷,點開
010049B6 EB 05 jmp short winmine.010049BD
010049B8 E8 64EAFFFF call winmine.01003421 ; 是雷,恢復
010049BD 59 pop ecx
010049BE 58 pop eax
010049BF 41 inc ecx ; 列數增1
010049C0 3B0D CC520001 cmp ecx, dword ptr ds:[10052CC] ; 遍歷完該行的所有列?
010049C6 ^ 7E DA jle short winmine.010049A2
010049C8 40 inc eax ; 行數增1
010049C9 3B05 C8520001 cmp eax, dword ptr ds:[10052C8] ; 遍歷完所有行?
010049CF ^ 7E CC jle short winmine.0100499D
010049D1 6A 01 push 1
010049D3 E8 9AE5FFFF call winmine.01002F72 ; 遊戲過關
010049D8 ^ E9 58D3FFFF jmp winmine.01001D35 ; 返回到原來的訊息迴圈結束處
在OD中寫入程式碼後,複製到可執行檔案,儲存即可!
4、執行Winmine.exe,選擇選單中的“過關”即可!
――――――――――――――――――――――――――――――――――――――――
【完】
qINGfENG
2005-01-14
相關文章
- java掃雷遊戲程式碼2012-11-10Java遊戲
- 《魔窟掃雷》給掃雷遊戲指明瞭一個進化的方向2019-12-31遊戲
- 掃雷小遊戲-網頁版2019-06-14遊戲網頁
- 經典掃雷遊戲Web版2021-09-09遊戲Web
- win10有掃雷嗎?Win10系統掃雷遊戲在哪裡2020-03-02Win10遊戲
- Java Swing掃雷遊戲demo分享2017-06-11Java遊戲
- 安全測試之探索 windows 遊戲掃雷2023-03-27Windows遊戲
- win10如何安裝掃雷遊戲_win10系統怎麼玩掃雷2020-08-10Win10遊戲
- win10沒有掃雷遊戲怎麼辦_win10自帶遊戲沒有掃雷如何解決2020-03-02Win10遊戲
- python之掃雷小遊戲(附程式碼)2020-12-08Python遊戲
- 探秘掃雷遊戲的C語言實現2023-12-16遊戲C語言
- 厲害了,一個自動掃雷遊戲專案!2019-01-08遊戲
- Linux下的6個掃雷遊戲的翻版2014-11-24Linux遊戲
- JS實現掃雷2020-12-12JS
- 自動掃雷程式2006-10-26
- 通過編寫掃雷遊戲提高你的 Bash 技巧2019-10-07遊戲
- vb.net使用GDI+實現掃雷小遊戲2018-08-09遊戲
- Win10系統開啟掃雷遊戲的方法2015-12-16Win10遊戲
- 用ncurses庫寫掃雷2020-09-27
- 無聊的週末用Java寫個掃雷小遊戲2022-01-17Java遊戲
- C語言陣列應用例項2: 掃雷遊戲2020-11-03C語言陣列遊戲
- 遊戲安全入門-掃雷分析&遠端執行緒注入2024-08-13遊戲執行緒
- 生成一個掃雷矩陣2020-08-20矩陣
- 掃雷--C語言實現2018-05-28C語言
- 掃雷程式思想講解 (轉)2008-01-05
- go語言實現掃雷2024-03-02Go
- 被世界遺忘的掃雷遊戲,只有中國人還在沉迷2019-09-20遊戲
- python寫的自動掃雷2010-10-11Python
- win10掃雷怎麼換主題 如何更換win10的掃雷主題2020-11-26Win10
- Python:遊戲:寫一個和 XP 上一模一樣的“掃雷”2019-03-27Python遊戲
- Win7系統下怎麼在掃雷遊戲介面輸入xyzzy2016-09-08Win7遊戲
- Qt學習- (掃雷專案初學)2016-12-26QT
- CSS3雷達掃描效果2017-02-20CSSS3
- 比「掃雷」還古老的遊戲,6000 萬歐美使用者玩瘋了2021-03-04遊戲
- 天了嚕,小時候玩的掃雷遊戲竟然有了VR版本2018-03-01遊戲VR
- J2ME偽高手先鋒開講:掃雷遊戲的設計(轉)2007-08-12遊戲
- Android自定義View 雷達掃描效果2018-05-16AndroidView
- 軟體開發其實就像工兵掃雷2008-06-04