【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: 文章中内容仅用于技术交流,请勿用于违规违法行为。

相关推荐
白乐天_n7 小时前
腾讯游戏安全移动赛题Tencent2016A
安全·游戏
这是我587 小时前
C++打小怪游戏
c++·其他·游戏·visual studio·小怪·大型·怪物
tealcwu8 小时前
【游戏设计原理】21 - 解谜游戏的设计
游戏·游戏策划
清梦20208 小时前
经典问题---跳跃游戏II(贪心算法)
算法·游戏·贪心算法
tealcwu9 小时前
【游戏设计原理】22 - 石头剪刀布
游戏·游戏策划
l1384942745112 小时前
Java每日一题(2)
java·开发语言·游戏
孤留光乩1 天前
从零搭建纯前端飞机大战游戏(附源码)
前端·javascript·游戏·html·css3
王大队长1 天前
Epic游戏使用mod
游戏
tealcwu1 天前
【游戏设计原理】20 - 囚徒困境
游戏
这是我581 天前
C++打小怪游戏2
c++·游戏