Frida JavaScript 常用 API

1. Process

1.1 Process.id

当前附加进程的 pid

function main() {
    Java.perform(() => {
        console.log("process pid = " + Process.id);
    });
}

setImmediate(main);

1.2 Process.enumerateModules()

枚举已加载的 so

function main() {
    Java.perform(() => {
        var Modules = Process.enumerateModules();
        for (let i = 0; i < Modules.length; i++) {
            const Module = Modules[i];
            console.log(JSON.stringify(Module));
        }
    });
}

setImmediate(main);

1.3 查找 so

1.3.1 Process.getModuleByName(name)

根据 name 查找 so,找不到则抛异常。

function main() {
    Java.perform(() => {
        var libc = Process.getModuleByName("libc.so");
        console.log(JSON.stringify(libc, null, 2));
    });
}

setImmediate(main);

1.3.2 Process.findModuleByName(name)

根据 name 查找 so,找不到则返回 null

function main() {
    Java.perform(() => {
        var libc = Process.findModuleByName("libc.so");
        console.log(JSON.stringify(libc, null, 2))
    });
}

setImmediate(main);

2. Module

2.1 属性

  • name,模块名
  • base,基地址,类型为 NativePointer
  • size,字节大小
  • path,完整文件系统路径
function main() {
    Java.perform(() => {
        var libc = Module.load('libc.so');
        console.log("libc 属性:");
        console.log("\tname: " + libc.name);
        console.log("\tbase: " + libc.base);
        console.log("\tsize: " + libc.size);
        console.log("\tpath: " + libc.path);
    });
}

setImmediate(main);

2.2 常用 API

2.2.1 Module.load(path)

加载指定的 so 文件,如果无法加载会抛异常。

function main() {
    Java.perform(() => {
        var libc = Module.load('libc.so');
        console.log(JSON.stringify(libc, null, 2));
    });
}

setImmediate(main);

2.2.2 Module.enumerateImports()

枚举 so 文件所有的 Import 库函数。

function main() {
    Java.perform(() => {
        var libc = Module.load("libc.so");
        var Imports = libc.enumerateImports();
        for (let i = 0; i < Imports.length; i++) {
            console.log(JSON.stringify(Imports[i], null, 2));
        }
    });
}

setImmediate(main);

2.2.3 Module.enumerateExports()

枚举 so 文件所有的 Export 库函数

function main() {
    Java.perform(() => {
        var libc = Module.load("libc.so");
        var Exports = libc.enumerateExports();
        for (let i = 0; i < Exports.length; i++) {
            console.log(JSON.stringify(Exports[i], null, 2));
        }
    });
}

setImmediate(main);

2.2.4 Module.ensureInitialized(name)

确保 so 文件初始化。

function main() {
    Java.perform(() => {
        Module.ensureInitialized("libc.so")
    });
}

setImmediate(main);

2.2.5 获取 so 文件基地址

2.2.5.1 Module.getBaseAddress(name)

获取 so 文件基地址,找不到则抛异常。

function main() {
    Java.perform(() => {
        var libcBaseAddress = Module.getBaseAddress('libc.so');
        console.log("libc.so 基地址为 " + libcBaseAddress);
    });
}

setImmediate(main);

2.2.5.2 Module.findBaseAddress(name)

获取 so 文件基地址,找不到返回 null

function main() {
    Java.perform(() => {
        var libcBaseAddress = Module.findBaseAddress('libc.so');
        console.log("libc.so 基地址为 " + libcBaseAddress);
    });
}

setImmediate(main);

2.2.6 查找 Export 库函数

2.2.6.1 Module.getExportByName(moduleName, exportName)

查找 so 文件的库函数,找不到抛异常。

function main() {
    Java.perform(() => {
        var ioctlBaseAddress = Module.getExportByName("libc.so", "ioctl");
        console.log("函数 ioctl 的基地址为 " + ioctlBaseAddress);
    });
}

setImmediate(main);

2.2.6.2 Module.findExportByName(moduleName, exportName)

查找 so 文件的库函数,找不到抛返回 null

function main() {
    Java.perform(() => {
        var ioctlBaseAddress = Module.findExportByName("libc.so", "ioctl");
        console.log("函数 ioctl 的基地址为 " + ioctlBaseAddress);
    });
}

# 3. Memory
## 3.1 内存检索
### 3.1.1 Memory.scan(address, size, pattern, callbacks)
同步检索内存,查找匹配的字节序列的基地址及大小。

```js
function main() {
    Java.perform(() => {
        Memory.scan(libc.base, libc.size, pattern, {
            onMatch(address, size) {
                console.log("匹配到字节序列,地址为 " + address);
            },
            onError(reason) {
                console.log("内存检索失败,原因为 " + reason);
            },
            onComplete() {
            }
        });
    });
}

setImmediate(main);

3.1.2 Memory.scanSync(address, size, pattern)

异步检索内存,查找匹配的字节序列的基地址及大小。

function main() {
    Java.perform(() => {
        var libc = Process.findModuleByName("libc.so");
        var memoryArray = Memory.scanSync(libc.base, libc.size, "00 ?8 4d ?? 00");
        for (let i = 0; i < memoryArray.length; i++) {
            console.log("匹配到字节序列,地址为 " + memoryArray[i].address);
        }
    });
}

setImmediate(main);

3.2 内存分配

3.2.1 Memory.alloc(size, options)

在附加进程的堆内存上申请大小为 size 的内存空间,如果此内存在 js 里没有对其使用时会自动释放。

function main() {
    Java.perform(() => {
        var allocMemoryAddress = Memory.alloc(4);
        console.log("动态分配内存基地址为 " + allocMemoryAddress);
    });
}

setImmediate(main);

3.2.2 Memory.allocUtf8String(str)

在附加进程的堆内存上申请大小能存放 str 的内存空间,如果此内存在 js 里没有对其使用时会自动释放。

function main() {
    Java.perform(() => {
        var allocMemoryAddress = Memory.allocUtf8String("Hello, Frida!");
        console.log(hexdump(allocMemoryAddress, {offset:0, length:"Hello, Frida!".length}));
    });
}

setImmediate(main);

3.3 Memory.copy(dst, src, size)

进行内存复制。

function main() {
    Java.perform(() => {
        var allocMemoryAddress = Memory.alloc(4);
        Memory.copy(allocMemoryAddress, libc.base, 4);
        console.log(hexdump(allocMemoryAddress, { length: 4, offset: 0 }));
    });
}

setImmediate(main);

4. Interceptor

5. Java

5.1 Java.perform(fn)

确保当前线程连接到虚拟机并调用函数 fn

5.2 Java.available

指定当前进程是否已加载虚拟机。

function main() {
    Java.perform(() => {
        console.log("Java.available = " + Java.available);
    });
}

setImmediate(main);

5.3 Java.androidVersion

获取 android 版本。

function main() {
    Java.perform(() => {
        console.log("Java.androidVersion = " + Java.androidVersion);
    });
}

setImmediate(main);

5.4 枚举已加载的类

5.4.1 Java.enumerateLoadedClasses(callbacks)

异步枚举已加载的类。

function main() {
    Java.perform(() => {
        Java.enumerateLoadedClasses({
            onMatch(name, handle) {
                console.log("class name is " + name);
            },
            onComplete() {
            }
        })
    });
}

setImmediate(main);

5.4.2 Java.enumerateLoadedClassesSync()

Java.enumerateLoadedClassesSync(),同步枚举已加载的类。

function main() {
    Java.perform(() => {
        var classNames = Java.enumerateLoadedClassesSync()
        for (let i = 0; i < classNames.length; i++) {
            console.log("class name is " + classNames[i]);
        }
    });
}

setImmediate(main);

5.5 枚举类加载器

5.5.1 Java.enumerateClassLoaders(callbacks)

异步枚举类加载器。

function main() {
    Java.perform(() => {
        Java.enumerateClassLoaders({
            onMatch(loader) {
                console.log(loader.getClass());
            },
            onComplete() {
            }
        });
    });
}

setImmediate(main);

5.5.2 Java.enumerateClassLoadersSync()

同步枚举类加载器。

function main() {
    Java.perform(() => {
        var classLoaders = Java.enumerateClassLoadersSync();
        for (let i = 0; i < classLoaders.length; i++) {
            console.log(classLoaders[i].getClass());
        }
    });
}

setImmediate(main);

5.6 Java.enumerateMethods(query)

枚举满足 query 规则的函数。query 格式为 class!method,可以通过 / 添加参数,比如 class!method/isu

  • i,忽略大小写
  • s,包含方法签名
  • u,只匹配用户定义类,忽略系统类
function main() {
    Java.perform(() => {
        var methods = Java.enumerateMethods("*!get*/isu");
        console.log(JSON.stringify(methods, null, 2));
    });
}

setImmediate(main);

5.7 Java.use(className)

通过类的完全限定名获取包装器,可以通过调用 $new 来实例化对象。

function main() {
    Java.perform(() => {
        var JString = Java.use('java.lang.String');
        var str = JString.$new("Hello, Frida!");
    });
}

setImmediate(main);

5.8 Java.choose(className, callbacks)

在堆内存中找类的实例。

function main() {
    Java.perform(() => {
        Java.choose("android.app.ActivityThread", {
            onMatch: function (instance) {
                console.log(instance.currentApplication());
            },
            onComplete() {
            }
        });
    });
}

setImmediate(main);

5.9 Java.cast(handle, kclass)

进行类型转换,将指定数据强制转换成所需类型。

function main() {
    Java.perform(() => {
        var JObject = Java.use("java.lang.Object");
        var JString = Java.use("java.lang.String");
        var str = JString.$new("Hello, Frida!");
        var objStr = Java.cast(str, JObject);
    });
}

setImmediate(main);

5.10 Java.array(type, elements)

创建数组。

function main() {
    Java.perform(() => {
        var JString = Java.use("java.lang.String");
        var JStringArray = Java.array("java.lang.String", [JString.$new("Hello"), JString.$new("Frida")]);
        for (let i = 0; i < JStringArray.length; i++) {
            console.log(JStringArray[i]);
        }
    });
}

setImmediate(main);

5.11 Java.registerClass(spec)

动态注册一个 Java 类。

function main() {
    Java.perform(() => {
        Java.registerClass({
            name: "com.smile.gifmaker.DynamicClass",
            fields: {
                str: "java.lang.String"
            },
            methods: {
                getStr: {
                    returnType: 'java.lang.String',
                    implementation() {
                        return str;
                    }
                },
                setStr: {
                    returnType: 'void',
                    argumentTypes: ['java.lang.String'],
                    implementation(text) {
                        str = text;
                    }
                }
            }
        })
        var instance = Java.use("com.smile.gifmaker.DynamicClass").$new()
        instance.setStr("Hello, Frida!");
        console.log(instance.getStr());
    }
}

setImmediate(main);

5.12 Java.openClassFile(filePath)

打开 dex 文件。

function main() {
    Java.perform(() => {
        var dexFile = Java.openClassFile('/data/data/com.ppdai.frida/classes.dex');
        dexFile.load();
        var classNames = dexFile.getClassNames();
        for (let i = 0; i < classNames.length; i++) {
            console.log(classNames[i]);
        }
    });
}

setImmediate(main);

5.13 获取 JNIEnv

5.13.1 Java.vm.getEnv()

获取 JNIEnv 对象,若当前线程未附加到 VM,则抛异常。

function main() {
    Java.perform(() => {
        var JNIEnv = Java.vm.getEnv();
    });
}

setImmediate(main);

5.13.2 Java.vm.tryGetEnv()

尝试获取 JNIEnv 对象,若当前线程未附加到 VM,则返回 null

function main() {
    Java.perform(() => {
        var JNIEnv = Java.vm.tryGetEnv();
    });
}

setImmediate(main);

你可能感兴趣的:(Frida JavaScript 常用 API)