经典扫雷游戏破解实现

查看 152|回复 11
作者:Nattevak   
自己对游戏方面挺感兴趣的,但是毕竟新手入门水平,想搞搞大型游戏还没有那水平,饭还得一口一口吃,先从经典的扫雷小游戏开始尝试
破解扫雷并不是说玩个扫雷都需要去使用作弊手段,只是为了学习思路和方法
扫雷游戏大家应该都玩过吧,我这里就不献丑演示游戏玩法了

扫雷.zip
(2.78 MB, 下载次数: 894)
2021-12-7 08:45 上传
点击文件名下载附件
扫雷
下载积分: 吾爱币 -1 CB

   其中包含 扫雷EXE源文件 以及 VS工程 (DLL文件在MFC -> Debug ->MFCSL.dll)
一、数据分析
1.雷的数量
添加后分别修改,最后发现地址为01005630的数值进行修改操作时游戏中的雷数会发生变化,故这里就确定的雷数的地址。


image.png (144.22 KB, 下载次数: 0)
下载附件
1.1
2021-12-6 18:20 上传

2.游戏时间
找到时间的地址,之后通过NOP时间可以实现0秒通关的效果。


image.png (118.78 KB, 下载次数: 0)
下载附件
1.2
2021-12-6 18:21 上传

3.雷区宽度
同样的搜索方法寻找到疑似雷区宽度的数据,之后仍进行修改验证测试。


image.png (122.78 KB, 下载次数: 0)
下载附件
1.3
2021-12-6 18:22 上传

4.雷区高度
同样的搜索方法寻找到疑似雷区高度的数据,之后仍进行修改验证测试。


image.png (148.38 KB, 下载次数: 0)
下载附件
1.4
2021-12-6 18:22 上传

5.数据汇总


image.png (64.36 KB, 下载次数: 0)
下载附件
1.5
2021-12-6 18:22 上传

二、游戏分析
1.遍历雷区
①创建DLL项目
使用Visual Studio创建MFC动态链接库项目,并选定DLL类型为静态链接(我这里使用的是Visual Studio2022)


image.png (102.31 KB, 下载次数: 0)
下载附件
2.1.1
2021-12-6 18:24 上传

②使用Spy++获取窗口信息(Visual Studio2022菜单栏 工具->Spy++  自带的工具)


image.png (71.64 KB, 下载次数: 0)
下载附件
2.1.2
2021-12-6 18:25 上传

③查看扫雷窗口信息


image.png (169.28 KB, 下载次数: 0)
下载附件
2.1.3
2021-12-6 18:26 上传

2.此处写了一个遍历雷区的测试代码,供大家参考
[C] 纯文本查看 复制代码    if (Msg == WM_KEYDOWN && wParam == VK_F5)
    {
        //一键秒杀
        OutputDebugString(L"F5");
        int nWidth = *g_pWidth;
        int nHeight = *g_pHeight;
        int nMineCount = *g_pMineCount;
        CString strString;
        strString.Format(L"宽度: %d,高度: %d,雷数:%d ", nWidth, nHeight, nMineCount);
        OutputDebugString(strString.GetBuffer());
    }
3.注入DLL
①使用CE 工具->注入DLL


image.png (291.17 KB, 下载次数: 0)
下载附件
3.1.1
2021-12-6 18:28 上传

②使用DebugView工具观察注入情况,对比游戏参数验证数值是否正确


image.png (81.53 KB, 下载次数: 0)
下载附件
3.1.2
2021-12-6 18:28 上传

4.反汇编代码调试
①将扫雷程序附加到OD中查看其内存情况,可以看出边界为10,雷为8F,标识为41,42…(无数字标识的地方为40)


image.png (230.17 KB, 下载次数: 0)
下载附件
4.1.1
2021-12-6 18:29 上传

②分析雷区数组的汇编代码部分



image.png (164.08 KB, 下载次数: 0)
下载附件
4.1.2
2021-12-6 18:30 上传

③测试遍历雷区代码,并重新注入进行测试
[C] 纯文本查看 复制代码        for (size_t y = 1; y
④再次使用DebugView工具观察注入情况


image.png (170.13 KB, 下载次数: 0)
下载附件
4.1.4
2021-12-6 18:31 上传

5.坐标转换
我们希望完成一键扫雷的操作,那我们就应该有模拟点击的操作,但是我现在并不知道雷区的坐标是什么样的,所以我们需要先进行坐标的转换
①获取回调函数
找到窗口回调函数的位置,仍然通过Spy++查看,使用Spy++获取窗口信息再点击确定就会弹出该窗口


image.png (54.58 KB, 下载次数: 0)
下载附件
5.1.1
2021-12-6 18:33 上传

6.反汇编代码调试
①在汇编代码中找到窗口回调函数的位置,并设置假定参数,再设置消息断点


image.png (126.54 KB, 下载次数: 0)
下载附件
6.1.1
2021-12-6 18:35 上传

②分析鼠标事件坐标转换的汇编代码部分


image.png (76.18 KB, 下载次数: 0)
下载附件
6.1.2
2021-12-6 18:35 上传

③获取鼠标位置,反馈窗口信息
[C] 纯文本查看 复制代码        x = LOWORD(lParam);
        y = HIWORD(lParam);
        x = (x + 4) >> 4;
        y = (y - 0x27) >> 4;
        BYTE byCode = *(PBYTE)((DWORD)g_pBase + x + y * 32);
        if (byCode == MINE){
            SetWindowText(hWnd, L"此处有雷");
        }
        else{
            SetWindowText(hWnd, L"扫雷");
        }
④通过模拟点击事件把所有非雷区域点击,实现一键通关
[C] 纯文本查看 复制代码xPos = (x
⑤游戏效果
按下F5后实现一秒钟自动扫雷并通关游戏


image.png (229.84 KB, 下载次数: 0)
下载附件
6.1.5
2021-12-6 18:36 上传

7.NOP游戏时间
①获取地址
在CE中找出是什么访问了这个地址,再显示反汇编程序,可以观察到时间的变化


image.png (166.76 KB, 下载次数: 0)
下载附件
7.1
2021-12-7 08:41 上传

②反汇编代码调试
由CE可以看到01002FF5处的指令代码实现时间的自增,如果想要时间不增加,就需要把这里给NOP掉,即将FF 05 9C570001 这六个字节都填充为NOP


image.png (24.73 KB, 下载次数: 0)
下载附件
7.2.1
2021-12-7 08:41 上传

当我们第一次按下时,01003830会自增1,所以导致之前无法实现0秒完成扫雷,故我们应该把01003830的数据也NOP掉


image.png (39.64 KB, 下载次数: 0)
下载附件
7.2.2
2021-12-7 08:42 上传

③将时间自增语句使用NOP填充
[C] 纯文本查看 复制代码    //获取扫雷进程ID
    GetWindowThreadProcessId(g_Wnd, &Pid);
    //获取扫雷进程句柄
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);
    //将时间自增的语句使用NOP填充
    result1 = WriteProcessMemory(hProcess, (LPVOID)g_pTime1, &szInc, 6, 0);
    result2 = WriteProcessMemory(hProcess, (LPVOID)g_pTime2, &szInc, 6, 0);
④游戏效果


image.png (217.56 KB, 下载次数: 0)
下载附件
7.4
2021-12-7 08:42 上传

三、完整代码
[C] 纯文本查看 复制代码// MFCSL.cpp: 定义 DLL 的初始化例程。
//
#include "pch.h"
#include "framework.h"
#include "MFCSL.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 唯一的 CMFCSLApp 对象
CMFCSLApp theApp;
HWND g_Wnd;//窗口句柄
WNDPROC g_OldProc;//老的窗口回调函数
PDWORD g_pHeight = (PDWORD)0x01005338;//雷区高度
PDWORD g_pWidth = (PDWORD)0x01005334;//雷区宽度
PDWORD g_pMineCount = (PDWORD)0x01005330;//雷的数量
PBYTE g_pBase = (PBYTE)0x1005340;//雷区基地址
#define MINE 0x8F//雷区中的元素标识
DWORD Pid = 0;//进程ID
HANDLE hProcess = 0;//进程句柄
PDWORD g_pTime1 = (PDWORD)0x01002FF5;//时间自增
PDWORD g_pTime2 = (PDWORD)0x01003830;//时间首次自增
char szInc[6] = { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 };//保存NOP指令
DWORD result1, result2;//保存结果
// CMFCSLApp 初始化
LRESULT CALLBACK WindowProc(
    _In_ HWND hWnd,
    _In_ UINT Msg,
    _In_ WPARAM wParam,
    _In_ LPARAM lParam)
{
    //获取扫雷进程ID
    GetWindowThreadProcessId(g_Wnd, &Pid);
    //获取扫雷进程句柄
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);
    //将时间自增的语句使用NOP填充
    result1 = WriteProcessMemory(hProcess, (LPVOID)g_pTime1, &szInc, 6, 0);
    result2 = WriteProcessMemory(hProcess, (LPVOID)g_pTime2, &szInc, 6, 0);
    if (Msg == WM_KEYDOWN && wParam == VK_F5)
    {
        //一键秒杀
        OutputDebugString(L"F5");
        int nWidth = *g_pWidth;
        int nHeight = *g_pHeight;
        int nMineCount = *g_pMineCount;
        CString strString;
        strString.Format(L"宽度: %d,高度: %d,雷数:%d ", nWidth, nHeight, nMineCount);
        OutputDebugString(strString.GetBuffer());
        int nFindCount = 0;
        for (size_t y = 1; y > 4;
        y = (y - 0x27) >> 4;
        BYTE byCode = *(PBYTE)((DWORD)g_pBase + x + y * 32);
        if (byCode == MINE)
        {
            SetWindowText(hWnd, L"此处有雷");
        }
        else
        {
            SetWindowText(hWnd, L"扫雷");
        }
    }
    return CallWindowProc(g_OldProc, hWnd, Msg, wParam, lParam);
}
BOOL CMFCSLApp::InitInstance()
{
        CWinApp::InitInstance();
        //1.通过查找窗口,获取窗口句柄
        g_Wnd = ::FindWindow(L"扫雷", L"扫雷");//FindWindowW(_In_opt_ LPCWSTR lpClassName,_In_opt_ LPCWSTR lpWindowName);
    if (g_Wnd == NULL)
    {
        OutputDebugString(L"无法找到 扫雷窗口");
        return FALSE;
    }
    //2.设置窗口回调函数
    g_OldProc = (WNDPROC)SetWindowLong(g_Wnd, GWL_WNDPROC, (LONG)WindowProc);
    if (g_OldProc == NULL)
    {
        OutputDebugString(L"设置窗口回调函数失败");
        return FALSE;
    }
    return TRUE;
}

下载次数, 下载附件

ACEcode   

WINDOWS自带的扫雷游戏作弊方法!绝对实用~
打开windows附带的扫雷游戏后
输入[x][y][z][z][y][Enter][Shift]
注意,shift要按2秒以上
然后当你的鼠标移动到有地雷的那个小方块时
桌面左上角的一个dot会变成黑色(转)
sd952202   

可以自己制作地狱级扫雷了
yinlin   

厉害,人脑还是比电脑强
迈克老狼   

这个都能破解厉害了
Demo   

win7以上的更有挑战性
arssswcr   

啊这,本来就是活跃思维的
tiancaiashuai   

厉害厉害,实在是佩服啊
githubi   

优秀,有时间学习一下,谢谢
yzice   

以后都不能吹嘘会玩扫雷游戏了
您需要登录后才可以回帖 登录 | 立即注册

返回顶部