jshook 中文文档 下载 App

内核模式内存读写——kernel.getModuleBase + readDword/writeDword

核心三步骤

内核模式下操作目标进程内存,永远是这三步:

// 1. 拿 SO 库基址
var base = kernel.getModuleBase('libil2cpp.so');

// 2. 算实际地址:基址 + 偏移
var targetAddr = parseInt(base, 16) + 0x1A2B3C4;

// 3. 读或写
var health = kernel.readFloat('0x' + targetAddr.toString(16));
kernel.writeFloat('0x' + targetAddr.toString(16), 999.0);

完整示例:写无敌模式

if (runtime.isKernel) {
    // 等 libil2cpp.so 加载好
    var timer = setInterval(function () {
        var il2cpp = kernel.getModuleBase('libil2cpp.so');
        if (il2cpp && il2cpp !== '0x0') {
            clearInterval(timer);
            console.log('[+] libil2cpp base: ' + il2cpp);
            
            // 假设生命值变量在基址 + 0x1A2B3C4 的位置(从 dump.cs 或内存扫描拿到)
            var healthAddr = parseInt(il2cpp, 16) + 0x1A2B3C4;
            var healthHex = '0x' + healthAddr.toString(16);
            
            console.log('[+] 生命值地址: ' + healthHex);
            
            // 读当前值
            var currentHealth = kernel.readFloat(healthHex);
            console.log('[+] 当前生命值: ' + currentHealth);
            
            // 每 3 秒改成 999
            setInterval(function () {
                kernel.writeFloat(healthHex, 999.0);
                console.log('[+] 生命值已设为 999');
            }, 3000);
        }
    }, 100);
}

支持的读写类型

API类型说明
kernel.readDword(address)int(4 字节整数)读 32 位整数
kernel.writeDword(address, value)int写 32 位整数
kernel.readFloat(address)float(4 字节浮点数)读 IEEE 754 浮点数
kernel.writeFloat(address, value)float写 IEEE 754 浮点数

address 参数统一用字符串格式的十六进制,如 '0x7f8a12345000'。

怎么拿到偏移量

内核模式下无法用 Memory.scan 或 Module.findBaseAddress——观察者进程的地址空间和目标进程完全不同。

所以偏移量的获取只能在普通模式下先做一次:

方法一:普通模式下用 Frida 找基址

// 普通模式下运行,找到地址后记录下来
var addr = Module.findBaseAddress('libil2cpp.so');
console.log('[+] libil2cpp base: ' + addr);
// 然后用 Interceptor 或 Memory.scan 找到目标变量的偏移

方法二:用 Il2CppDumper 导出的 dump.cs

dump.cs 里包含了所有类、方法、字段的偏移量列表。直接查就行。

方法三:MCP 工具配合 VS Code Copilot

JsHook 的内置 MCP 服务可以让 AI 辅助定位内存地址。详见 MCP 可用工具清单。

getModuleBase 返回 0x0 怎么办

var base = kernel.getModuleBase('libil2cpp.so');
console.log('base: ' + base);  // 输出 0x0

排查顺序:

  1. 目标应用有没有在运行? SO 库没加载的话基址就是 0x0
  2. SO 名对不对? 区分大小写,用实际的 SO 文件名
  3. 内核驱动正常工作吗? 检查驱动加载日志
  4. 是观察者进程的问题? 看看 /data/adb/jshook/.kernel/ 下有没有 kernel_*.log

readDword / writeDword 用什么场景

注意事项