日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

逆向扫雷(2)

發(fā)布時(shí)間:2025/3/21 编程问答 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 逆向扫雷(2) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

緊接著 掃雷(1)博客,我們接著說(shuō),接下來(lái)我們需要找到存放寬和高的內(nèi)存地址,一般肯定也是立即數(shù)地址,這種小游戲不會(huì)存在那種太難的偏移。

第一步:拿到游戲的窗口句柄:

HWND hwnd = ::FindWindowA("掃雷", "掃雷");//獲取游戲的窗口句柄

第二步:通過(guò)窗口句柄拿到進(jìn)程ID:

GetWindowThreadProcessId(hwnd, &pid);

這個(gè)pid是上面提前定義好的DWORD類(lèi)型

第三步:通過(guò)進(jìn)程ID拿到進(jìn)程句柄:

HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid)

第四步:隨便找個(gè)基地址讀取一下,觀(guān)察進(jìn)程是否存在(打開(kāi)):

這里的0x1005361是通過(guò)CE觀(guān)察出來(lái)的,大家可以自行嘗試

if (!ReadProcessMemory(hProcess, (LPCVOID)0x1005361, &gamedata, 32 * 24, &pid)){::MessageBoxA(NULL, "掃雷游戲未打開(kāi)", "錯(cuò)誤", MB_OK);return 0;}

第五步(綜合講解所需要的一些值計(jì)算):把每格的大小,以及坐標(biāo)利用VS自帶的SPY++計(jì)算一下:

a.這里我算出來(lái)是(20,60);

short gamex = 20; short gamey = 60;

每格大小的話(huà),利用兩個(gè)點(diǎn)計(jì)算一下就好,這里用圖表示一下:

這是點(diǎn)擊了雷區(qū)的左上角


這是點(diǎn)擊了雷區(qū)的右上角

然后兩個(gè)相減,最后再來(lái)除以格子數(shù)量,就可以得到長(zhǎng)度了,既可以找到鼠標(biāo)點(diǎn)擊的位置坐標(biāo)。

b.至于雷區(qū)的寬度和高度利用CE立即數(shù)搜索就可以搜索到它們的立即數(shù)地址,即不變的地址,就可以找到

c.通過(guò)觀(guān)察,高度最大可以24,長(zhǎng)度最大可為32,如何判斷終止的地方呢?

通過(guò)觀(guān)察,遇到0x10后它就停止了一行的有效區(qū),這就是掃雷模式的改變,雷區(qū)所放的地方是不變的,它只需要改變一下一行結(jié)尾。每行的起始位置是不變的,它只改變終止位置。這就改變了掃雷模式的寬度和高度。所以一行的長(zhǎng)度是不變的,如何控制呢?我們只需要找到0x10地點(diǎn),高度呢?高度只需要讀取一下CE里面找出來(lái)的立即數(shù)不就行嘍,思路就是這樣

根據(jù)上述我們即可 初始化一個(gè)雷區(qū)數(shù)組unsigned char gamedata[24][32] = { 0 };

第六步:遍歷之后判斷并用鼠標(biāo)點(diǎn)擊:

unsigned short xypos[2] = { 0 };for (int i = 0; i < dwHight;++i) {for (int j = 0; j < 32;++j) {if (0x10 == gamedata[i][j])break;xypos[0] = gamex + j * 16;xypos[1] = gamey + i * 16;if (0x8F != gamedata[i][j]) {::PostMessage(hwnd, WM_LBUTTONDOWN,MK_LBUTTON,*(int *)xypos);::PostMessage(hwnd, WM_LBUTTONUP,0, *(int*)xypos);}}}

完整代碼如下

閱讀下面的c++代碼需要一點(diǎn)點(diǎn)的windows核心編程基礎(chǔ),掃雷程序的話(huà)可以參照模仿一下就行

#include<iostream> #include<windows.h> using namespace std; int main() {DWORD pid;HWND hwnd = ::FindWindowA("掃雷", "掃雷");//獲取游戲的窗口句柄if (NULL == hwnd){MessageBoxA(NULL, "掃雷游戲未打開(kāi)", "錯(cuò)誤", MB_OK);return 0;}GetWindowThreadProcessId(hwnd, &pid);//通過(guò)窗口句柄拿到進(jìn)程IDHANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);//通過(guò)進(jìn)程ID拿到進(jìn)程句柄if (NULL == hProcess) {::MessageBoxA(NULL, "掃雷游戲未打開(kāi)","錯(cuò)誤", MB_OK);return 0;}//掃雷基址:0x1005361 炸彈:0x8F //掃雷的高 0x01005338 //掃雷的寬 0x01005334unsigned char gamedata[24][32] = { 0 };if (!ReadProcessMemory(hProcess, (LPCVOID)0x1005361, &gamedata, 32 * 24, &pid)){::MessageBoxA(NULL, "掃雷游戲未打開(kāi)", "錯(cuò)誤", MB_OK);return 0;}DWORD dwHight = 0;if (!ReadProcessMemory(hProcess, (LPCVOID)0x01005338, &dwHight, sizeof(dwHight), &pid)){::MessageBoxA(NULL, "讀取掃雷進(jìn)程未打開(kāi)", "錯(cuò)誤", MB_OK);return 0;}short gamex = 20;short gamey = 60;unsigned short xypos[2] = { 0 };for (int i = 0; i < dwHight;++i) {for (int j = 0; j < 32;++j) {if (0x10 == gamedata[i][j])break;xypos[0] = gamex + j * 16;xypos[1] = gamey + i * 16;if (0x8F != gamedata[i][j]) {::PostMessage(hwnd, WM_LBUTTONDOWN,MK_LBUTTON,*(int *)xypos);::PostMessage(hwnd, WM_LBUTTONUP,0, *(int*)xypos);}}}cout << "彪哥出品,必為廢品";CloseHandle(hProcess); }

運(yùn)行結(jié)果圖:



前三步總結(jié)也就是
通過(guò)窗口的標(biāo)題拿到窗口的句柄,FindWindowA
然后通過(guò)窗口的句柄拿到進(jìn)程的ID,GetWindowThreadProcessId
最后通過(guò)進(jìn)程的ID拿到進(jìn)程的句柄
OpenProcess

插入一個(gè)提示(vs如何打開(kāi)MSDN幫助文檔)

比如要查看float的特征。
在vs中輸入float,然后按F1鍵,會(huì)在默認(rèn)瀏覽器上打開(kāi)幫助文檔。

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專(zhuān)家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的逆向扫雷(2)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。