吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 22646|回复: 396
收起左侧

[原创] 经典扫雷游戏破解实现

    [复制链接]
Nattevak 发表于 2021-12-6 18:41
本帖最后由 Nattevak 于 2021-12-7 08:48 编辑

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

扫雷.zip (2.78 MB, 下载次数: 1093)    其中包含 扫雷EXE源文件 以及 VS工程 (DLL文件在MFC -> Debug ->MFCSL.dll)

一、数据分析

1.雷的数量
添加后分别修改,最后发现地址为01005630的数值进行修改操作时游戏中的雷数会发生变化,故这里就确定的雷数的地址。

1.1

1.1


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

1.2

1.2


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

1.3

1.3


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

1.4

1.4


5.数据汇总

1.5

1.5


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

2.1.1

2.1.1


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

2.1.2

2.1.2


③查看扫雷窗口信息

2.1.3

2.1.3


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

3.1.1

3.1.1


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

3.1.2

3.1.2


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

4.1.1

4.1.1


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

4.1.2

4.1.2


③测试遍历雷区代码,并重新注入进行测试
[C] 纯文本查看 复制代码
        for (size_t y = 1; y < nHeight + 1; y++)
        {
            CString strLine;
            for (size_t x = 1; x < nWidth + 1; x++)
            {
                //数组基地址+(y+1)*32+x+1(y=0到高度)
                BYTE byCode = *(PBYTE)((DWORD)g_pBase + x + y * 32);
                if (byCode == MINE)
                {
                    nFindCount++;
                }
                CString strCode;
                strCode.Format(L"%02x ", byCode);
                strLine += strCode;
            }
            OutputDebugString(strLine.GetBuffer());
        }


④再次使用DebugView工具观察注入情况

4.1.4

4.1.4


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

5.1.1

5.1.1


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

6.1.1

6.1.1


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

6.1.2

6.1.2


③获取鼠标位置,反馈窗口信息
[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 << 4) - 4;
yPos = (y << 4) + 0x27;
SendMessage(hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(xPos, yPos));
SendMessage(hWnd, WM_LBUTTONUP, 0, MAKELPARAM(xPos, yPos));


⑤游戏效果
按下F5后实现一秒钟自动扫雷并通关游戏

6.1.5

6.1.5


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

7.1

7.1


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

7.2.1

7.2.1


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

7.2.2

7.2.2


③将时间自增语句使用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);


④游戏效果

7.4

7.4


三、完整代码
[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 < nHeight + 1; y++)
        {
            CString strLine;
            for (size_t x = 1; x < nWidth + 1; x++)
            {
                //数组基地址+(y+1)*32+x+1(y=0到高度)
                BYTE byCode = *(PBYTE)((DWORD)g_pBase + x + y * 32);
                if (byCode == MINE)
                {
                    nFindCount++;
                }
                else
                {
                    int xPos, yPos;
                    xPos = (x << 4) - 4;
                    yPos = (y << 4) + 0x27;
                    SendMessage(hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(xPos, yPos));
                    SendMessage(hWnd, WM_LBUTTONUP, 0, MAKELPARAM(xPos, yPos));
                }
                CString strCode;
                strCode.Format(L"%02x ", byCode);
                strLine += strCode;
            }
            OutputDebugString(strLine.GetBuffer());
        }
        CString strCode;
        strCode.Format(L"找到的雷数 %d ", nFindCount);
        OutputDebugString(strCode.GetBuffer());
    }
    else if (Msg == WM_MOUSEMOVE)
    {
        //鼠标移动
        int x, y;
        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"扫雷");
        }
    }
    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;
}

免费评分

参与人数 120威望 +1 吾爱币 +125 热心值 +107 收起 理由
adam666 + 1 用心讨论,共获提升!
tiddler + 1 + 1 我很赞同!
quiter53 + 1 + 1 我很赞同!
vcax + 1 热心回复!
寂雨 + 1 热心回复!
daihao49 + 1 + 1 我很赞同!
Hqbhbw + 1 我很赞同!
lin1567 + 1 + 1 谢谢@Thanks!
maiwens + 1 + 1 谢谢@Thanks!
yaoxingwei + 1 + 1 我很赞同!
chanshizhe + 1 + 1 谢谢@Thanks!
h81158807 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
PartyShaker + 1 + 1 我很赞同!
130339 + 1 我很赞同!
nekoneko2021 + 1 + 1 我很赞同!
DUDU666 + 1 + 1 我很赞同!
Brand1209 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
九江陈大锤 + 1 谢谢@Thanks!
wdraemv + 1 + 1 我很赞同!
我是大帅比丶 + 1 + 1 我很赞同!
xdjonnysu + 1 我很赞同!
YYL7535 + 1 + 1 谢谢@Thanks!
Baysir + 1 + 1 我很赞同!
wuxiawuhua + 1 + 1 谢谢@Thanks!
chadsea + 1 + 1 我很赞同!
gq060 + 1 + 1 用心讨论,共获提升!
tong_xing + 1 + 1 热心回复!
rox + 1 + 1 谢谢@Thanks!
叩叩叩哦 + 1 + 1 谢谢@Thanks!
king51999 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
gomg007 + 1 + 1 用心讨论,共获提升!
ytfh1131 + 1 + 1 谢谢@Thanks!
xuemantian0304 + 1 谢谢@Thanks!
qiao1257 + 1 我很赞同!
三千晚 + 1 + 1 我很赞同!
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
kkavifo + 1 + 1 谢谢@Thanks!
qiangbi007 + 1 + 1 用心讨论,共获提升!
laobj + 1 谢谢@Thanks!
nekous + 1 + 1 谢谢@Thanks!
香芋 + 1 + 1 用心讨论,共获提升!
ag129 + 1 谢谢@Thanks!
xzhtx + 1 + 1 我很赞同!
paomianhaochi + 1 + 1 热心回复!
g123458 + 1 谢谢@Thanks!
lostcage + 1 + 1 我很赞同!
okgjkk + 1 + 1 谢谢@Thanks!
qaz003 + 1 + 1 好有创意,扫雷快被大家玩坏了
dhdajun + 1 + 1 用心讨论,共获提升!
guyinqian + 3 感谢发布原创作品,吾爱破解论坛因你更精彩!
zhchxu123 + 1 谢谢@Thanks!
lcwww + 1 + 1 我很赞同!
amoresky + 1 谢谢@Thanks!
isskydomain + 1 + 1 谢谢@Thanks!
xuehanlin821 + 1 + 1 用心讨论,共获提升!
热心市民小丑 + 1 + 1 谢谢@Thanks!
寒鸭一对对 + 1 + 1 就很棒
foreverkeo + 1 + 1 感谢您的宝贵建议,我们会努力争取做得更好!
zhouyy + 1 + 1 谢谢@Thanks!
无尘浪子 + 1 + 1 谢谢@Thanks!
szkent + 1 + 1 热心回复!
Juhey + 1 热心回复!
chanshiking + 1 谢谢@Thanks!
thinkpad_420 + 1 + 1 厉害,佩服楼主的专研精神
amo今天学习了吗 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
lishixin23 + 1 + 1 谢谢@Thanks!
kkjoker + 1 + 1 厉害啊,讲的也很详细
bg_yx + 1 我很赞同!
夏日已末 + 1 + 1 大佬厉害啊
bugof52pj + 1 + 1 谢谢@Thanks!
ysy2001 + 1 + 1 谢谢@Thanks!
CJAOAN + 1 + 1 用心讨论,共获提升!
笙若 + 1 + 1 谢谢@Thanks!
陈世界 + 1 + 1 我很赞同!
混碗饭吃 + 1 + 1 热心回复!
qws1855 + 1 + 1 用心讨论,共获提升!
吴剑先 + 1 + 1 我很赞同!
wanfon + 1 + 1 谢谢@Thanks!
chinajxw + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
mitunakl + 1 + 1 用心讨论,共获提升!
小银子95 + 1 + 1 我很赞同!
aa530416 + 1 + 1 热心回复!
紫色 + 2 + 1 我很赞同!
as36601987 + 1 + 1 用心讨论,共获提升!
blywq + 1 + 1 谢谢@Thanks!
mainid + 1 + 1 我很赞同!
qhdsinoocean + 1 + 1 谢谢@Thanks!
Tonyha7 + 1 我很赞同!
fub8 + 1 NB PLUS
niusongpeng + 1 + 1 我很赞同!
冒险家orz + 1 我很赞同!
goMoney + 1 + 1 我很赞同!
skiss + 1 + 1 用心讨论,共获提升!
a253018580 + 1 + 1 用心讨论,共获提升!
monk3435 + 1 + 1 我很赞同!
qwe134133987 + 1 + 1 热心回复!
xuph + 1 + 1 谢谢@Thanks!
kaixianxian + 1 + 1 我很赞同!
key4479 + 1 + 1 这是玩出了新高度呀
虚竹1001 + 1 儿时的快乐

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

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

免费评分

参与人数 1热心值 +1 收起 理由
yangcongwen + 1 键盘按破了也没按出来

查看全部评分

sd952202 发表于 2021-12-6 19:14
yinlin 发表于 2021-12-7 08:53
迈克老狼 发表于 2021-12-6 19:10
这个都能破解厉害了
Demo 发表于 2021-12-6 19:11
win7以上的更有挑战性
arssswcr 发表于 2021-12-6 19:17
啊这,本来就是活跃思维的
tiancaiashuai 发表于 2021-12-6 19:22
厉害厉害,实在是佩服啊
githubi 发表于 2021-12-6 19:22
优秀,有时间学习一下,谢谢
yzice 发表于 2021-12-6 19:28
以后都不能吹嘘会玩扫雷游戏了
孤独尽头是自由 发表于 2021-12-6 19:38
不错不错
翩跹丶 发表于 2021-12-6 19:47
好家伙,这个厉害了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-22 09:13

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表