【Frida】10_用鼠标自动标记棋盘上的雷区(一键过关)

🛫 系列文章导航

▒ 目录 ▒

🛫 导读

开发环境

版本号 描述
文章日期 2024-03-17
操作系统 Win11 - 22H2 22621.2715
node -v v20.10.0
npm -v 10.2.3
yarn -v 3.1.1
frida-compile 10.2.1 高版本各种异常
扫雷程序下载地址 https://download.csdn.net/download/kinghzking/88979919
课程源码 https://gitcode.net/kinghzking/MyOpen 所在目录:/course/frida

1️⃣ 需求分析

流程:

  • 将目标窗口切换到前台(参考历史文章)
  • 获取游戏地图区域位置(软件窗口固定偏移)
  • 遍历棋盘,按行遍历
    • 如果是地雷(0x8F),标记为地雷(右键点击)
    • 如果是无雷区(0x0F),左键点击。
  • 重绘窗口区域(参考历史文章)

获取游戏地图区域位置(软件窗口固定偏移)

  • 我们先看下从基址拿到的内存数据,地址0x01005340对应的是(0,0)元素,该元素值为0x10,表示边界,不需要点击。真正需要点击的是0x01005361,该元素才是界面上的第一个元素。

    有了上面的介绍,我们可以假设一个虚拟的(0,0)点,如下图所示,该点相对于窗口的坐标为(6,88),所以,起始点的计算如下(lpRect为窗口在屏幕中的左上角位置):

  • this.start_x = lpRect.readU32() + 6;

  • this.start_y = lpRect.add(4).readU32() + 88;

    完整的代码如下:

js 复制代码
class L07 {
  // 设置鼠标位置_自动点击鼠标
  private start_x = 0;
  private start_y = 0;
  private step = 16;

  获取软件窗口位置_设置鼠标指针位置() {
    let lpRect = Memory.alloc(4 * 4);
    User32.GetWindowRect(this.hWnd, lpRect);
    this.start_x = lpRect.readU32() + 6;
    this.start_y = lpRect.add(4).readU32() + 88;
    console.log("start_x", this.start_x);
    console.log("start_y", this.start_y);
  }

模拟点击:mouse_click

模拟鼠标操作,我们需要使用Windows API函数MouseEvent。该函数是一个Windows API函数,用于模拟鼠标的各种操作,例如移动鼠标、点击鼠标按键等。但需要注意的是,由于其在新版本的Windows中已经被标记为过时,推荐使用更现代的方法,如SendInput函数来模拟输入事件。

函数原型:

cpp 复制代码
void MouseEvent(
    DWORD dwFlags,  // 指定鼠标动作的标志,可以是以下值的组合:
                   // MOUSEEVENTF_ABSOLUTE:指定x和y参数是绝对坐标
                    // MOUSEEVENTF_LEFTDOWN:模拟鼠标左键按下
                    // MOUSEEVENTF_LEFTUP:模拟鼠标左键释放
                    // MOUSEEVENTF_RIGHTDOWN:模拟鼠标右键按下
                    // MOUSEEVENTF_RIGHTUP:模拟鼠标右键释放
                    // MOUSEEVENTF_MIDDLEDOWN:模拟鼠标中键按下
                       // MOUSEEVENTF_MIDDLEUP:模拟鼠标中键释放
                       // MOUSEEVENTF_WHEEL:模拟鼠标滚轮滚动
                       // MOUSEEVENTF_XDOWN:模拟鼠标X按钮按下
                       // MOUSEEVENTF_XUP:模拟鼠标X按钮释放
       DWORD dx,       // x坐标变化量或绝对坐标(取决于dwFlags)
       DWORD dy,       // y坐标变化量或绝对坐标(取决于dwFlags)
       DWORD dwData,   // 滚轮滚动量
    ULONG_PTR dwExtraInfo // 额外信息,一般设为0
);

mouse_click实现逻辑:

  • User32.SetCursorPos移动到指定位置
  • 当为左键时,模拟鼠标左键按下和弹起。
  • 当为右键时,模拟鼠标右键按下和弹起。
js 复制代码
  mouse_click(x: number, y: number, left_click: boolean = true) {
    User32.SetCursorPos(this.start_x + this.step * x, this.start_y + this.step * y);
    if (left_click) {
      User32.MouseEvent(User32.Const.MOUSEEVENTF_LEFTDOWN, 0, 0, 0,  User32.GetMessageExtraInfo());
      User32.MouseEvent(User32.Const.MOUSEEVENTF_LEFTUP, 0, 0, 0, User32.GetMessageExtraInfo());
    }
    else {
      User32.MouseEvent(User32.Const.MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, User32.GetMessageExtraInfo());
      User32.MouseEvent(User32.Const.MOUSEEVENTF_RIGHTUP, 0, 0, 0, User32.GetMessageExtraInfo());
    }
  }

2️⃣ 代码编写测试

核心的函数都已经封装完毕,最后我们遍历地雷数据,执行点击事件,这里需要注意几点内容:

  • for循环中的长宽范围需要+2,因为有边界0x10
  • byte_data为head的偏移j + 0x20 * i,这是因为每行数据是固定的0x20(这也是为什么扫雷最大宽为30的原因)
  • 程序只有初始的时候有两种状态:0x8F0x0F,如果已经开始游戏的情况,会出现未处理的按钮。
    具体代码如下:
js 复制代码
class L07 {
  run() {
    this.将目标窗口切换到前台()
    this.获取软件窗口位置_设置鼠标指针位置()

    //遍历棋盘,按行遍历
    for (let i = 0; i < this.height + 2; i++) {
      //按列遍历
      let data = [];
      for (let j = 0; j < this.width + 2; j++) {
        let byte_data = this.head.add(j + 0x20 * i).readU8();
        data.push(byte_data.toString(16).padStart(2, "0"));

        // 标记地雷
        if  (byte_data == 0x8F) {
          this.mouse_click(j, i, false);
        }
        // 点击无雷区
        if (byte_data == 0x0F) {
          this.mouse_click(j, i);
        }
      }
      console.log(data.join(" "));
    }

    // 重绘窗口区域
    this.board_repaint()
  }
}

let l07 = new L07();
l07.run();

代码已上传gitcode:https://gitcode.net/kinghzking/MyOpen 。 所在目录为:/course/frida/11_用鼠标自动标记棋盘上的雷区/index.ts

配置脚本如下:

执行npm run watch11,以监视模式编译脚本。

执行npm run runx,运行编译后的脚步,最终1秒过关。

🛬 文章小结

到此为止,我们通过TypeScript方式进行开发,通过扫雷程序,实战了Frida的基本使用。

当然,Frida的路途还很遥远,期待下次再见。
ps: 文章中内容仅用于技术交流,请勿用于违规违法行为。

相关推荐
风酥糖11 小时前
Godot游戏练习01-第24节-多人游戏暂停菜单,游戏优化
游戏·游戏引擎·godot
CDN36011 小时前
游戏盾 SDK 混淆后失效?豁免规则与打包配置解决方案
运维·游戏·网络安全
huwuhang12 小时前
Winkawaks街机游戏模拟器整合ROM版 1.65 汉化修正完整版 2026.03.30
android·游戏·游戏机
智算菩萨13 小时前
【Pygame】第20章 从0到1构建贪吃蛇:基于Pygame的游戏架构与状态机设计实战(有超详细中文注释)
python·游戏·pygame
wanhengidc15 小时前
云手机 性能不受限 数据安全
服务器·网络·安全·游戏·智能手机
ZJH__GO15 小时前
java--飞机大战游戏
java·游戏
智算菩萨16 小时前
【Pygame】第23章 平台跳跃游戏:基于有限状态机的2D平台物理模拟与摄像机视口管理系统(有超详细中文注释供大家学习)
python·游戏·pygame
CCIE-Yasuo16 小时前
《永恒战士2-无双战神》无限金币版(提供apk下载)安卓Android逆向记录学习-Deepseek-AI辅助
android·java·学习·游戏
代码小书生17 小时前
Windows X-Lite Win11 26H1 v3 游戏优化系统!集Win11、Win10、Win7三代优点,兼顾游戏办公生产算力,系统精简纯净
windows·游戏·windows x-lite·windows 游戏版·windows优化版·老电脑系统
竹之却17 小时前
【Minecraft】无法连接至服务器,登录失败:无效会话(请尝试重启游戏及启动器)
运维·服务器·游戏·我的世界·minecraft