Frida JavaScript 常用 API

1. Process

1.1 Process.id

當(dāng)前附加進(jìn)程的 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)

根據(jù) 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)

根據(jù) 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,字節(jié)大小
  • path,完整文件系統(tǒng)路徑
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 庫函數(shù)。

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 庫函數(shù)

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 庫函數(shù)

2.2.6.1 Module.getExportByName(moduleName, exportName)

查找 so 文件的庫函數(shù),找不到拋異常。

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

setImmediate(main);

2.2.6.2 Module.findExportByName(moduleName, exportName)

查找 so 文件的庫函數(shù),找不到拋返回 null。

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

# 3. Memory
## 3.1 內(nèi)存檢索
### 3.1.1 Memory.scan(address, size, pattern, callbacks)
同步檢索內(nèi)存,查找匹配的字節(jié)序列的基地址及大小。

```js
function main() {
    Java.perform(() => {
        Memory.scan(libc.base, libc.size, pattern, {
            onMatch(address, size) {
                console.log("匹配到字節(jié)序列,地址為 " + address);
            },
            onError(reason) {
                console.log("內(nèi)存檢索失敗,原因?yàn)?" + reason);
            },
            onComplete() {
            }
        });
    });
}

setImmediate(main);

3.1.2 Memory.scanSync(address, size, pattern)

異步檢索內(nèi)存,查找匹配的字節(jié)序列的基地址及大小。

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("匹配到字節(jié)序列,地址為 " + memoryArray[i].address);
        }
    });
}

setImmediate(main);

3.2 內(nèi)存分配

3.2.1 Memory.alloc(size, options)

在附加進(jìn)程的堆內(nèi)存上申請大小為 size 的內(nèi)存空間,如果此內(nèi)存在 js 里沒有對其使用時會自動釋放。

function main() {
    Java.perform(() => {
        var allocMemoryAddress = Memory.alloc(4);
        console.log("動態(tài)分配內(nèi)存基地址為 " + allocMemoryAddress);
    });
}

setImmediate(main);

3.2.2 Memory.allocUtf8String(str)

在附加進(jìn)程的堆內(nèi)存上申請大小能存放 str 的內(nèi)存空間,如果此內(nèi)存在 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)

進(jìn)行內(nèi)存復(fù)制。

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)

確保當(dāng)前線程連接到虛擬機(jī)并調(diào)用函數(shù) fn。

5.2 Java.available

指定當(dāng)前進(jìn)程是否已加載虛擬機(jī)。

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 規(guī)則的函數(shù)。query 格式為 class!method,可以通過 / 添加參數(shù),比如 class!method/isu

  • i,忽略大小寫
  • s,包含方法簽名
  • u,只匹配用戶定義類,忽略系統(tǒng)類
function main() {
    Java.perform(() => {
        var methods = Java.enumerateMethods("*!get*/isu");
        console.log(JSON.stringify(methods, null, 2));
    });
}

setImmediate(main);

5.7 Java.use(className)

通過類的完全限定名獲取包裝器,可以通過調(diào)用 $new 來實(shí)例化對象。

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)

在堆內(nèi)存中找類的實(shí)例。

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)

進(jìn)行類型轉(zhuǎn)換,將指定數(shù)據(jù)強(qiáng)制轉(zhuǎn)換成所需類型。

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)

創(chuàng)建數(shù)組。

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)

動態(tài)注冊一個 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 對象,若當(dāng)前線程未附加到 VM,則拋異常。

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

setImmediate(main);

5.13.2 Java.vm.tryGetEnv()

嘗試獲取 JNIEnv 對象,若當(dāng)前線程未附加到 VM,則返回 null。

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

setImmediate(main);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容