/Il2CppHookScripts

基于 frida 的 libil2cpp.so 运行时解析脚本

Primary LanguageJavaScript

Il2cppHook

基于 frida 的 libil2cpp.so 运行时解析脚本

Features

  • 解析 Unity 的方法 m / 类 c / 字段 f / 实例 lfs
  • 解析 运行时方法参数 b
  • 常用函数的(批量)Hook B/BF,修改函数返回值 setFunctionRet...
  • 更方便的查找函数 findMethods 以及调用函数 callFunction
  • 对象层级关系 PrintHierarchy / 类型层级关系 showTypeParent
  • 结合frida以及方法信息反汇编 showAsm
  • 常用Hook封装 HookOnPointerClick/HookSetActive/B_Button...
  • 解析 挂载脚本 showComponents alias s HookOnPointerClick/PrintHierarchyWithComponents也有引入 <--- testing
  • ...

Usage

$ git clone https://github.com/axhlzy/Il2CppHookScripts.git
$ cd Il2cppHook/
$ npm install
$ npm run watch

$ frida -U -f com.xxx.xxx -l ../_Ufunc.js
OR
$ frida -FU -l ../_Ufunc.js

API

Contents
  1. 基础函数
  2. 断点函数
  3. 常用函数Hook的封装
  4. Module/Thread相关
  5. lf 系列 (list fields ... )
  6. 其他

Examples

  • i() == list_images 不带参数即列出所有的 Images

    list_images

  • c() == list_classes 列出所有的类 list_classes(ptr/strFilter)

    list_classes

  • m() == list_methods 列出所有的方法

    list_methods

  • f() == list_fields 列出所有的字段

    list_fields

  • findClass(className) 查找类,一般配合m()使用 m(findClass('className')) === m('className')

    findClass

  • findMethod 新版 / find_method 旧版

    findMethod

  • printExp 作为findMethod的补充版,方便查找函数

    • 第一个参数是查找的函数名 findMethod
    • 第二个参数标识是否全局查找(默认在常用的函数中查找,因为是遍历嘛,这样可以有效提高查找速度) findMethod
  • getApkInfo 获取 apk 信息

    getApkInfo

  • callFunction 函数调用

    callFunction

  • showAsm 基于frida.Instruction结合unity函数信息的反汇编

    showAsm

    showAsmSP

  • showMethodInfo / MethodToShow 查看MethodInfo信息(后者多用在findMethod)showAddressInfo alias showMethodInfo(addressToMethod)

    showMethodInfo

  • showTypeParent 查看父级类型

    showTypeParent

  • showComponents 查看挂载在对象上的脚本,建议配合使用lfs,OnPointerClick、printh也有调用

    showComponents

  • B breakPoint 断点函数类

    • B ('ClassName') === B(findClass('ClassName')),不会重复添加已添加的Method,不带参数即断点所有常用的方法

      breakPoint_B

    • BF 等价于原来的 B("filterStr") ,断点包含指定字符串的方法

      breakPoint_BF

    • b ('Method_Pointer') / b('MethodInfo_Pointer')

      breakPoint_b

    • d / D : d === detachAll and d(ptr) === detach(ptr) / D() === detachAll + clear list cache

    • bp('filterMethodName') 断点包含 指定的函数名(filterMethodName) 的所有函数

  • n/nn nop Function

    • n / nn : n(ptr) === nop function and nn() === cancel nop function

      nop

  • breakInline InlineHook

    breakInline

  • breakWithArgs 带参数断点

    breakWithArgs

  • breakWithStack 带堆栈断点

    breakWithStack

  • dlopen : 提供一个早期的函数hook点

    dlopen

  • watch/watchDisabled MemoryAccessMonitor的简单封装(arm32易崩)

    watch

  • StalkerTracePath StalkerTrace封装 分析调用顺序

    StalkerTracePath

  • StalkerTraceEvent StalkerTraceEvent 分析事件

    StalkerTraceEvent

  • HookOnPointerClick :Hook 点击事件

    HookOnPointerClick

  • HookDebugLog : Hook Debug.Log

    HookDebugLog

  • HookSetActive : Hook SetActive

    HookSetActive

  • HookPlayerPrefs : Hook PlayerPrefs

    HookPlayerPrefs

  • B_Button : Hook Button

    B_Button

    B_Button

  • PrintHierarchy : 打印当前场景的层级结构

    • 注意:arm64的地址用双引号包裹起来,arm32直接传递即可 PrintHierarchy
  • showArray : 打印Array showArray

  • listModule (filterName: string) => void

    listModule

  • listModules (moduleName: string, printItems?: number) => void

    listModules

  • listThreads (maxCountThreads?: number) => void

    listThreads

  • findExport (exportName: string, moduleName?: string, callback?: (exp: ModuleExportDetails) => void) => void

    findExport

  • findImport (moduleName: string, importName?: string) => void

    findImport

  • lfs 详见 Il2cppHook\agent\bridge\fix\parseFields.ts 需要一个参数实例地址 可以去B()中找

    lfs

  • HttpGet

    httpGet

...

Test

  • 详见 Il2cppHook\agent\base\dynamic.ts (命令行补全) dynamic_2 dynamic_3 dynamic_1

Commit

  • 文件结构按照Unity类继承关系实现
  • 文件命名规则以及结构
    • 一个类文件夹下一个include.ts包含当前类文件以及该类子类文件夹的include
    • api.ts
      • 用作解析常用函数 (exp: ptr(Il2Cpp.Api.Application._Quit) )
      • 函数的命名使用 '_' + 具体的函数名,多参数使用后缀 '_x' 结尾i (exp: Il2Cpp.Api.Application._Quit_1)
      • api class 命名为 类名 + 'API' (exp: System_ValueType_API)
    • class.ts
      • NativePointer转换为Class的实现 (把ptr当成class来解析)
      • 包含一些(静态)字段,(静态)方法,以及方便调用的一些函数封装
      • this.handle 存贮当前 ptr,可以是 实例指针也可以是类指针 (多数情况使用实例指针)
      • 每一个class.ts都可以写上自己的toString方法以便于直接解析该类
    • export.ts
      • 主要用作拓展类的一些导出方法
  • TODO 按照这个文件结构可以拓展到整个UnityAPI (提供了 generateApi / generateClass / generateFieldEnum 方便的拓展类,生成的东西不太准,需要稍微修改点点), 后面在 dynamic.ts 又提供了反射来时间命令行直接补全的操作,不过因为使用前他会遍历所以导致很慢,所以暂时没用(或者说可以选择筛选部分常用的class来使用 具体用法

Tips

  • 由于JS特性在64位hook下存在精度问题,arm64下的指针大小是8字节,但是js命令行传参最大值是 Number.MAX_SAFE_INTEGER = 9007199254740991 (0x1fffffffffffff),所以命令行直接给值超出范围导致精度丢失,这时候建议使用string类型 use ptr("0xb400007d17736990") instead of ptr(0xb400007d17736990),这部分发现的比较晚后续很多东西都没有做好优化
  • 如果需要启动的时候先暂停下来,可以在这里调用pause,重新编译ts,然后在命令行输入 resume() 继续执行
  • 我这里用的环境: frida==15.2.2 | frida-tools==10.5.4 , 测试机 :piex 4 原生android 11
    1. 确认手机端server与电脑端frida版本一致,如果你的版本不一致概率性出问题
    2. 已确认高版本的 frida-tools 在使用老版 Ufunc.js (ts版不受影响)会出问题,所以建议直接使用 10.5.4 版本
    3. 由于ts分支版本的 Ufunc.js 是基于frida-il2cpp-bridge 的,所以有一些新版Unity它本身不支持的,自然也会影响脚本的使用,也可以尝试使用老版本(master分支)下的Ufunc.js
    4. il2cpp: couldn't determine the Unity version, please specify it manually 参见 这里
  • 建议使用真机,尽量不在x86模拟器中使用,x86中找不到对应so,其次frida对于模拟器的兼容性也并不好
  • 文档写的不够详细,所以大伙想看那些导出函数建议直接搜索 globalThis. 即可
  • 数据类型这一块还是很混 ValueType ,后续会慢慢优化

todo:

  • 从游戏对象获取对象下挂载的脚本
  • qbdi 调用栈
  • 协程hook webrequests hook
  • 从任意一个游戏对象无法遍历到当前场景所有游戏对象(顶层对象不同)
  • 不能跨场景找游戏对象 ...

QQ群:992091014

欢迎各位大佬加群交流

提供新的功能需求,反馈问题,提交代码