欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

扫雷插件分析与编写

发布时间:2025/3/21 28 豆豆
生活随笔 收集整理的这篇文章主要介绍了 扫雷插件分析与编写 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

至个人年久失修的git博客搬运https://yusakul.github.io/


扫雷游戏插件的目标

  • 当鼠标放在扫雷的方格中时,会显示是否有雷。
  • 一键扫雷,快捷键是F5
  • 扫雷游戏的分析

  • 需要的技能
  • ① 会编写DLL

    ②会写注入读取或者写内存的代码

    ③能够分析出扫雷程序中的信息

  • 需要分析的数据
  • ① 扫雷数组的大小

    ② 扫雷数组的宽度 、高度

    ③ 扫雷数组中的数量

  • 需要分析的代码
  • ① 找到遍历扫雷数组的代码,或者分析出如何遍历数组

    ② 找到屏幕坐标转换数组下的代码,或者分析出这个过程

    ③ 找到数组下标转换屏幕坐的代码,或者分析出这个过程

  • 代码框架
  • 接管扫雷窗口的回调函数,处理F5的按键消息

    修改窗口属性SetWindowLong

    扫雷游戏-分析数据

    ① 扫雷数组的大小

    ② 扫雷数组的宽度 、高度

    ③ 扫雷数组中的数量

    根据宽度或者高的值变化,使用 CE 在内存中搜索数值,从而能找到宽度的地址

    CE使用
  • 修改程序数据的值,在CE中搜索

  • 每次修改之后,再使用CE搜索,最后确定可能的值

  • 注意:绿色的地址就是可以映射到文件偏移的地址,绿色地址称为基址

  • 在可能的值上查找此地址数据的代码
  • 再次修改数据,会有代码被记录

    代码处:10036AC

    高度:1005338

    宽度:1005334

    雷数:1005330

    扫雷游戏-分析代码

  • 从数值变化的代码处开始分析
  • 从代码处: 10036 AC 开始跟踪分析

  • 敏感 API 下断点,再进一步分析 下断点,再进一步分析
  • 定时器创建和销毁: SetTimer,KillTimer

    随机函数: rand

  • 从窗口回调函数开始分析 窗口回调函数开始分析 ,分析鼠标按下消息

    使用 spy++ 查找程序的窗口回调

  • 地址:1001BC9

  • 从数值变化的代码处开始分析
  • 从代码处:10036AC开始跟踪分析

    修改完数据之后,应该初始化扫雷数组、随机生成雷。

    随机生成雷的代码中,是一个循环随机生成雷的x,y 坐标,然后写入到对应缓冲区

    基地址:0x1005340

    X坐标计算:随机数+1

    Y坐标计算:(随机数+1)*32

    根据内存情况可以分析出一些标记:

    0F :初始化的值

    8F :雷的标记

    4X :周围有几颗雷就是4X, 41,42,43,44……

    10 :边界

    有了随机雷的生成,那么在雷生成前面的CALL,应该就是初始化雷区数组的代码,经过调试查看内存,发现真的是。

    分析初始化雷区数组代码,发现为三步

  • 初始化全部缓冲区为 0x0 F

  • 初始化行标记 为 0x10

  • 初始化列标记 位 0x 10

  • 搭建代码框架

    第一步 ,定义一些值和函数

    WNDPROC g_OldProc = NULL; HWND g_hWnd = NULL; LRESULT WINAPI WindowProc ( _In_ HWND hWnd, _In_ UINT Msg, _In_ WPARAM wParam, _In_ LPARAM lParam) {if (Msg == WM_KEYDOWN && wParam == VK_F5){CString strString;strString.Format(L"wParam = %p", wParam);OutputDebugString(strString.GetBuffer());return DefWindowProc(hWnd, Msg, wParam, lParam);}return CallWindowProc(g_OldProc, hWnd, Msg, wParam, lParam); }

    第二步,修改回调函数

    // 修改扫雷窗口的回调函数 // 1. 找到扫雷窗口 g_hWnd = FindWindow(NULL, L"扫雷"); // 2. 修改窗口回调 g_OldProc = (WNDPROC)SetWindowLong(g_hWnd, GWL_WNDPROC, (LONG)WindowProc); // 恢复窗口回调 SetWindowLong(g_hWnd, GWL_WNDPROC, (LONG)g_OldProc);

    注意:写代码要记得释放和恢复,写代码要做好debug的准备

    经过调整编写之后,遍历扫雷的数组

    // 基地址:0x1005340 // 高度:1005338 // 宽度:1005334 // 雷数:1005330 byte** g_MineArray = (byte**)0x1005340; int* g_nHeight = (int*)0x1005338; int* g_nWidth = (int*)0x1005334; int* g_nMineCount = (int*)0x1005330;LRESULT WINAPI WindowProc ( _In_ HWND hWnd, _In_ UINT Msg, _In_ WPARAM wParam, _In_ LPARAM lParam) {if (Msg == WM_KEYDOWN && wParam == VK_F5){CString strString;strString.Format(L"saolei wParam = %p", wParam);OutputDebugString(strString.GetBuffer());// 遍历扫雷数组int nHeight = *g_nHeight; // 高度yint nWidth = *g_nWidth; // 宽度xint nCount = *g_nMineCount;int nCurrentCount = 0;for (int j = 1; j < nHeight+1; j++){CString strString1;strString1.Format(L"saolei 行:%d ", j);// 行遍历时,需要注意去掉边界for (int i = 1; i < nWidth + 2 - 1; i++){byte byCode = *(byte*)((int)g_MineArray+i+j*32);if (byCode == (byte)0x8F){nCurrentCount += 1;}CString strCode;strCode.Format(L" %02x ", byCode);strString1 += strCode;}strString1 += L"\r\n";OutputDebugString(strString1.GetBuffer());}CString strString2;strString2.Format(L"saolei 雷数 = %d", nCurrentCount);OutputDebugString(strString2.GetBuffer());return DefWindowProc(hWnd, Msg, wParam, lParam);}return CallWindowProc(g_OldProc, hWnd, Msg, wParam, lParam); }

    分析 -屏幕坐标转数组下标

    分析思路:

    ① 窗口回调下消息断点,分析鼠标按下弹起消息的流程

    ② 静态分析窗口回调,使用IDA找到对应的消息处理流程

    窗口回调地址:1001BC9

    在地址处下消息断点WM_LBUTTONDOWN

    在这个消息的lParam参数里是x,y坐标

    将汇编代码翻译为C代码

    WORD y = HIWORD(lParam); y = (y - 0x27) >> 4;WORD x = LOWORD(lParam); x = (x + 4) >> 4;byte byCode = *(byte*)((int)g_MineArray + x + y * 32);if (byCode == (byte)0x8F) {SetWindowText(hWnd,L"扫雷 - 友情提示:你踩到雷了!"); } else {SetWindowText(hWnd, L"扫雷"); }

    分析-数组下标转屏幕坐标

    将上面的代码反转

    // 发送一个鼠标按下弹起的消息 WORD y = j; y = (y << 4) + 0x27; //y 高16位WORD x = i; x = (x << 4) - 4; // x 低16位SendMessage(hWnd, WM_LBUTTONDOWN, 0, MAKELPARAM(x,y)); SendMessage(hWnd, WM_LBUTTONUP, 0, MAKELPARAM(x, y));

    DLL调试

  • 如果有源码,可以使用VS进行调试,只需要设置启动exe即可

  • 如果没有源码,使用OD调试,一般选择在调试的代码处加入特征汇编指令

  • 比如:

    Mov eax, eax

    Mov eax, eax

    在注入 DLL 之后,可以搜索指令 之后,可以搜索指令

    选择 DLL 模块 (在模块列表中找到对应,右键跟随入口)

    选择 DLL 模块的代码基址 (进入模块代码之后,拖到最前面)

    使用 Ctrl +S, 搜索

  • 在OD中注入DLL
  • 总结

    以上是生活随笔为你收集整理的扫雷插件分析与编写的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。