• 安卓真机无root环境下的单机游戏修改-IL2CPP


    前言

    之前在研究手游的il2cpp修改,选取了 Mine Survival 作为研究对象,由于手上没有root的机子,于是安装在了MuMu模拟器

    但是很快发现了问题,游戏只有arm的lib,由于一系列原因,导致我无法获取到 libil2cpp.so 的基址

    在尝试了很多方法后都无法完美的解决这个问题,最终只能考虑安装在真机上了

    但是目前并没有对机子root的打算,于是选取了注入 frida-gadget 的方案,这样没有root也可以对游戏进行修改了hhh

    准备工作

    基础工作不做过多介绍,学这个的应该都懂一点

    我的设备

    • 安卓真机 - Redmi Note 8
    • 电脑 - Win10 专业版 22H2

    推荐使用 scrcpy ,可以将手机画面投屏到电脑,延迟低

    开始操作

    注入 frida-gadget

    介绍

    可以手动操作去理解原理,参考这篇文章 Using Frida on Android without root

    当然我这种懒汉肯定是选用自动化方案啦,使用 objection 来自动化patch apk

    安装 objection

    • python版本 3.4+
    • pip3版本 9.0+
    • (可选)virtualenv版本 15+
    全局安装

    1

    $ pip3 install -U objection

    虚拟环境安装

    为了防止冲突,推荐安装在虚拟环境里

    1

    2

    3

    4

    5

    6

    # 创建虚拟环境

    $ virtualenv myenv

    # 激活虚拟环境

    $ .\myenv\Scripts\activate

    # 安装objection

    $ pip3 install -U objection

    patch apk

    确定以下命令安装并且可用,将其添加到环境变量中

    adb连接上安卓设备,执行下面的命令,就可以自动化的帮你patch好apk了

    1

    $ objection patchapk --source '.\Mine Survival_v2.5.3.apk'

     

    安装测试

    Mine Survival_v2.5.3.objection.apk安装到手机

    1

    $ adb install '.\Mine Survival_v2.5.3.objection.apk'

    然后执行一下 frida-ps -U ,有如下回显就是成功了

    1

    2

    3

    4

    $ frida-ps -U

      PID  Name

    -----  ------

    21709  Gadget

    测试一下,写个获取 libil2cpp.so 基址的脚本

    1

    2

    3

    4

    Java.perform(function() {

        var module = Process.getModuleByName("libil2cpp.so");

        console.log(module.base);

    })

    注入js

    1

    $ frida -U Gadget -l .\hook.js

    可以看到成功获取到了libil2cpp.so的基址

     

     

    frida-il2cpp-bridge

    很好用,不多解释了

    安装测试

    执行下面的命令来安装 frida-il2cpp-bridge

    1

    $ npm install --save-dev frida-il2cpp-bridge

    修改 package.json

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    {

      "main": "index.ts",

      "scripts": {

        "prepare": "npm run build",

        "watch": "frida-compile index.ts -w -o hook.js"

      },

      "dependencies": {

        "frida-il2cpp-bridge": "^0.9.0"

      }

    }

    新建一个 index.ts,测试一下输出unity版本

    1

    2

    3

    4

    5

    import "frida-il2cpp-bridge";

    Il2Cpp.perform(() => {

        console.log("Unity version: " + Il2Cpp.unityVersion);

    });

    执行 npm run watch 编译一下,然后再开个console执行 frida -U Gadget -l .\hook.js

    可以看到成功输出了unity的版本

     

    开始修改

    通过分析 il2cppdumper dump后得到的 Assembly-CSharp.dll,发现了 Inventory 这个类,可以看到他有一个 AddItems 的方法,那我们就可以想办法调用他来添加物品

    现在来跟踪一下这个类

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    import "frida-il2cpp-bridge";

    Il2Cpp.perform(() => {

        console.log("Unity version: " + Il2Cpp.unityVersion);

        const AssemblyCSharp = Il2Cpp.domain.assembly("Assembly-CSharp").image

        const Inventory = AssemblyCSharp.class("Inventory");

        Il2Cpp.trace(true).classes(Inventory).and().attach();

    });

    拾取一个物品,可以看到他调用了 Inventory::AddDropItem 这个方法

     

     

    那么就可以hook他来调用 Inventory::AddItems

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    import "frida-il2cpp-bridge";

    Il2Cpp.perform(() => {

        console.log("Unity version: " + Il2Cpp.unityVersion);

        const AssemblyCSharp = Il2Cpp.domain.assembly("Assembly-CSharp").image

        const Inventory = AssemblyCSharp.class("Inventory");

        const AddDropItem = Inventory.method("AddDropItem");

        // Il2Cpp.trace(true).classes(Inventory).and().attach();

        AddDropItem.implementation = function (item): boolean {

            // bool AddItems(int id, int amount)

            this.method("AddItems").invoke(115, 999);

            const result = this.method("AddDropItem").invoke(item);

            return result;

        };

    });

    拾取物品,可以看到我们拥有了许多核导弹(喜)

     

     

    完结撒花

    感谢开源项目的维护者们

    frida-il2cpp-bridge 还是很强大的,可以去学习一下

    写的可能有点乱,有问题还请指出hh

     

     

  • 相关阅读:
    微信小程序自定义顶部导航栏
    【Linux】进程间通信——管道
    Java 面试只是背答案吗?
    STM32 APP跳转到Bootloader
    石油化工行业商业供应链管理系统:标准化供应商管理,优化企业供应链采购流程
    XDOJ-360 结点在二叉排序树的位置
    网络管理中TRUNK的作用和使用
    CSDN专栏设置
    【源码解析】Spring Bean定义常见错误
    【Android笔记41】使用Android实现一个简易版本的购物车小案例
  • 原文地址:https://blog.csdn.net/wei_java144/article/details/136575249