如何用 Frida 读取堆上的内存?

How to read memory on the heap with Frida?

我尝试使用 Frida 和位于 Android 虚拟设备(模拟)上的服务器读取堆上的内存,但我一直遇到内存 access violation 错误。

首先我在寻找一个有趣的实例 class:

Java.performNow(function() {
    Java.choose("com.example.model.interestingObject", {
        onMatch: function(instance) {
            console.log(instance.toString());                   
        }, onComplete: function() {
        }
    });
});

作为输出,我得到(我想)内存中的地址: com.example.model.interestingObject@d735e35

但是当我尝试从该地址读取时: Memory.readByteArray(ptr("0xd735e35"), 64); 然后我得到以下错误:

Error: access violation accessing 0xd735e35
    at frida/runtime/core.js:282
    at /repl18.js:26

问题是,如何从该地址读取字节?我对 Frida 很陌生,所以可能做错了什么。很高兴为您提供帮助!

查看Java函数Object.toString()可以看到值d735e35不是地址而是对象的哈希码:

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

因此您查看的内存地址错误,导致您观察到 access violation

一般来说 Java/Android 你不应该尝试直接访问内存。使用 Frida 的可用函数来列出所有字段及其值。

我想你只需要投射你找到的实例@ onMatch

Java.cast(instance,Java.use("com.example.model.interestingObject")).toString()

docs

其他一切都很好
  • Java.choose(className, callbacks):通过扫描 Java 堆枚举 class 名称 class 的活动实例,其中回调是指定的对象:

    • onMatch: 函数(实例):为使用现成实例找到的每个活动实例调用一次,就像您使用原始句柄调用 Java.cast() 一样到这个特定的实例。 该函数可以return字符串提前终止取消枚举。

    • onComplete: function(): 当所有实例都被枚举时调用

要打印 class 个成员,您可以使用 Object.getOwnPropertyNames(obj.__proto__).join('\n\t')