本文配套源碼
注意:以下是在WinXP SP2+VC 6.0下調試通過的,別的版本的Windows沒有經過驗證.
最近閒暇時間迷上了掃雷,有的時候經常遇到模稜兩可的地方,很容易死到.於是就在想,要是我一開始 就知道哪個地方有雷就好了.遂打開OllyDBG,對掃雷程序(WinMine.exe),進行了一番跟蹤.好在 WinMine.exe沒有加殼,直接看它的IMPORT TABLE,在兩個可疑的API上下斷點,一個就是GDI.BitBlt,這個 是程序來畫地圖的,另一個就是User32.GetDlgItemInt,這個用來獲得掃雷地圖大小,和雷的個數的.
下完斷點,運行.隨便點一下地圖,調到斷點處. 分析如下
01002657 |. push 0CC0020 ;//BitBlt第九個參數,是SRCCOPY
0100265C |. mov esi,eax ;
0100265E |. mov eax,dword ptr ss:[esp+C] ;//eax存放點擊的方塊的橫坐標
01002662 |. mov edx,ecx ;//ecx存放點擊方塊的縱坐標
01002664 |. push 0 ;//nYSrc=0,BitBlt第八個參數
01002666 |. shl edx,5 ; //縱坐標左移5位
01002669 |. movsx edx,byte ptr ds:[edx+eax+1005340] ; //獲得地圖上的值
01002671 |. push 0 ; //nXSrc = 0,BitBlt第七個參數
01002673 |. and edx,1F ;
01002676 |. push dword ptr ds:[edx*4+1005A20] ; //nXSrc = 0,BitBlt第六個參數
0100267D |. shl ecx,4 ;
01002680 |. push 10 ; //nHeight = 10 (16.),BitBlt第五個參數
01002682 |. push 10 ; //nWidth = 10 (16.),BitBlt第四個參數
01002684 |. add ecx,27 ;
01002687 |. shl eax,4 ;
0100268A |. push ecx ; //nYDest,BitBlt第三個參數
0100268B |. sub eax,4 ;
0100268E |. push eax ; //nXDest,BitBlt第二個參數
0100268F |. push esi ; //hDestDC,BitBlt第一個參數
01002690 |. call dword ptr ds:[<&GDI32.BitBlt>] ;
關鍵部分就在byte ptr ds:[edx+eax+1005340] ,由於Winmine的方塊是從左上角坐標位(1,1)算起的, 所以這個地址的初始位置在0x1<<5+0x1+0x1005340=0x1005361處,顯示內存內容,經過幾次分析,發 現0f代表沒雷,8f代表有雷,10代表邊界,通過驗證,結果得到證實.
下面說獲得地圖的大小,和雷的個數.
下斷點User32.GetDlgItemInt,點菜單中的自定義,然後確定,中斷後,往下走幾步,來到:
010015ED |. push 18 ; /Arg4= 00000018
010015EF |. push 9 ; |Arg3 = 00000009
010015F1 |. push 8D ; |Arg2 = 0000008D
010015F6 |. push esi ; |Arg1
010015F7 |. call winmine.01003DF6 ; \winmine.01003DF6
010015FC |. push 1E ; /Arg4 = 0000001E
010015FE |. push 9 ; |Arg3 = 00000009
01001600 |. push 8E ; |Arg2 = 0000008E
01001605 |. push esi ; |Arg1
01001606 |. mov dword ptr ds:[10056A8],eax ; |地圖的高度的地址
0100160B |. call winmine.01003DF6 ; \winmine.01003DF6
01001610 |. mov ecx,dword ptr ds:[10056A8]
01001616 |. mov dword ptr ds:[10056AC],eax; //地圖的寬度的地址
0100161B |. dec eax
0100161C |. dec ecx
0100161D |. imul eax,ecx
01001620 |. mov ecx,3E7
01001625 |. cmp eax,ecx
01001627 |. jle short winmine.0100162B
01001629 |. mov eax,ecx
0100162B |. push eax ; /Arg4
0100162C |. push 0A ; |Arg3 = 0000000A
0100162E |. push 8F ; |Arg2 = 0000008F
01001633 |. push esi ; |Arg1
01001634 |. call winmine.01003DF6 ; \winmine.01003DF6
01001639 |. mov dword ptr ds:[10056A4],eax //存放雷的個數的地址
這個通過幾次試驗,分析岀:
0x10056a8是存放地圖的高度的地址
0x10056ac是存放地圖的寬度的地址
0x10056a4是存放雷的個數的地址
有了以上的分析,很容易寫出一個Loader,來進行作弊,其實這個Loader就是CreateProcess一個掃雷進 程,獲得它的Process句柄而已,而不是用枚舉進程來獲得句柄,覺得後者有點麻煩.打開後,單擊Crack,就 會顯示地圖的情況,''0''代表沒雷,''x''代表有雷,可以對初級,中級,高級按地圖大小進行處理,自定義 的就沒有做了,哪位有時間的話,可以繼續下去.代碼用到的思想很簡單,就是用ReadProcessMemory來讀取 掃雷進程指定位置的內存內容,具體不多說了,還是見代碼吧!
結束語
還有就是注冊表HKEY_CURRENT_USER\Software\Microsoft\winmine下面的幾個選項,哈哈,改一改你就 是掃雷達人了.