请选择 进入手机版 | 继续访问电脑版

逆向扫雷(2)

[复制链接]
孤单 发表于 2021-1-2 19:47:10 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
紧接着 扫雷(1)博客,我们接着说,接下来我们需要找到存放宽和高的内存地点,一般肯定也是立刻数地点,这种小游戏不会存在那种太难的偏移。
第一步:拿到游戏的窗口句柄:

  1. HWND hwnd = ::FindWindowA("扫雷", "扫雷");//获取游戏的窗口句柄
复制代码
第二步:通过窗口句柄拿到进程ID:

  1. GetWindowThreadProcessId(hwnd, &pid);
复制代码
这个pid是上面提前界说好的DWORD范例
第三步:通过进程ID拿到进程句柄:

  1. HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid)
复制代码
第四步:随便找个基地点读取一下,观察进程是否存在(打开):

这里的0x1005361是通过CE观察出来的,各人可以自行实验
  1. if (!ReadProcessMemory(hProcess, (LPCVOID)0x1005361, &gamedata, 32 * 24, &pid))        {                ::MessageBoxA(NULL, "扫雷游戏未打开", "错误", MB_OK);                return 0;        }
复制代码
第五步(综合教学所需要的一些值盘算):把每格的巨细,以及坐标使用VS自带的SPY++盘算一下:

a.这里我算出来是(20,60);
  1. short gamex = 20;short gamey = 60;
复制代码
每格巨细的话,使用两个点盘算一下就好,这里用图体现一下:

这是点击了雷区的左上角

这是点击了雷区的右上角
然后两个相减,最后再来除以格子数量,就可以得到长度了,既可以找到鼠标点击的位置坐标。
b.至于雷区的宽度和高度使用CE立刻数搜索就可以搜索到它们的立刻数地点,即稳定的地点,就可以找到
c.通过观察,高度最大可以24,长度最大可为32,如何判定终止的地方呢?

通过观察,遇到0x10后它就停止了一行的有效区,这就是扫雷模式的改变,雷区所放的地方是稳定的,它只需要改变一下一行末了。每行的起始位置是稳定的,它只改变终止位置。这就改变了扫雷模式的宽度和高度。所以一行的长度是稳定的,如何控制呢?我们只需要找到0x10所在,高度呢?高度只需要读取一下CE内里找出来的立刻数不就行喽,思路就是这样
根据上述我们即可 初始化一个雷区数组unsigned char gamedata[24][32] = { 0 };
第六步:遍历之后判定并用鼠标点击:

  1.         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++代码需要一点点的windows核心编程根本,扫雷步调的话可以参照模仿一下就行
[code]#include#includeusing namespace std;int main() {        DWORD pid;        HWND hwnd = ::FindWindowA("扫雷", "扫雷");//获取游戏的窗口句柄        if (NULL == hwnd)        {                MessageBoxA(NULL, "扫雷游戏未打开", "错误", MB_OK);                return 0;        }        GetWindowThreadProcessId(hwnd, &pid);//通过窗口句柄拿到进程ID        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);//通过进程ID拿到进程句柄        if (NULL == hProcess) {                ::MessageBoxA(NULL, "扫雷游戏未打开","错误", MB_OK);                return 0;        }//扫雷基址:0x1005361  炸弹:0x8F//扫雷的高  0x01005338//扫雷的宽  0x01005334        unsigned char gamedata[24][32] = { 0 };        if (!ReadProcessMemory(hProcess, (LPCVOID)0x1005361, &gamedata, 32 * 24, &pid))        {                ::MessageBoxA(NULL, "扫雷游戏未打开", "错误", MB_OK);                return 0;        }        DWORD dwHight = 0;        if (!ReadProcessMemory(hProcess, (LPCVOID)0x01005338, &dwHight, sizeof(dwHight), &pid))        {                ::MessageBoxA(NULL, "读取扫雷进程未打开", "错误", 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[j])                                break;                        xypos[0] = gamex + j * 16;                        xypos[1] = gamey + i * 16;                        if (0x8F != gamedata[j]) {                                ::PostMessage(hwnd, WM_LBUTTONDOWN,MK_LBUTTON,*(int *)xypos);                                ::PostMessage(hwnd, WM_LBUTTONUP,0, *(int*)xypos);                        }                }        }        cout
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

发布主题

专注素材教程免费分享
全国免费热线电话

18768367769

周一至周日9:00-23:00

反馈建议

27428564@qq.com 在线QQ咨询

扫描二维码关注我们

Powered by Discuz! X3.4© 2001-2013 Comsenz Inc.( 蜀ICP备2021001884号-1 )