Frida操作java类的一些记录
这篇笔记主要记录在使用Frida
写一个测试框架中会需要的Api
的使用方法,包括了
- 何时执行
- 获取当前系统的信息
- 获取所有加载到当前进程的类信息
- 获取app的所有加载的类
- 获取app加载的所有so模块
- 获取app类的方法
- 获取加载模块的方法
- 操作一个java类对象
- 修改java的函数参数
- 修改java的函数的返回值
何时执行
为了保证能正常运行,需要使用如下方法执行以确保不会发生ClassNotFoundException
等异常。 code_01.js
Java.perform(function(){
//do something
//java类的操作需要在这个方法下执行,这样才能确保已经附加到了一个JVM的进程上
})
调用成功了Java.perform
函数,后续的java操作才能执行。
系统信息
系统信息包括了手机的信息和pc的信息,使用如下方法获取
判断是否附加成功
Java.avaliable -->返回一个bool类型值,如果返回False则表示当前测试进程不能用
Android的系统版本
为了能获取到当前系统的版本信息,使用如下Api
Java.androidVersion
获取系统的架构信息
获取系统的架构信息可以使用如下APi
var arch=Process.arch //返回一个 arm arm64等
PC的OS
使用Process.platform
获取操作系统的信息
Process.platform
Java类的操作
获取所有的加载类
Frida
提供了两个版本的方法来获取已经加载的类,注意,这里是指已经加载的类,就是当前进程加载的全部类,包括了系统、第三方和自身app的类型,方法有两种
-
方法1
Java.enumerateLoadedCalsses({ onMatch:function(name,handle){ //这里边可以获取类,name就是枚举出来的类信息 每次获取到一个类就回调这个函数 //这个类里可以针对性的对特定类做类型处理或者转换,这里可以操作类 } onComplete:function(){ //执行完成调用函数 } })
如下是例子
-
方法2
使用同步方法获取所有的加载类有点麻烦,因此提供了一个异步版本,只需要调用异常就能获取到所有的类
//该方法只能获取到所有的类,要操作的时候还要再次遍历 var allLoadedClasses = Java.enumerateLoadedClassesSync() //这个方法能获取所有的加载类
例子
// Script Inspired by https://github.com/0xdea/frida-scripts/tree/master/android-snippets function enumAllClasses() { var allClasses = []; var classes = Java.enumerateLoadedClassesSync(); classes.forEach(function(aClass) { try { var className = aClass.replace(/\//g, "."); } catch (err) { } allClasses.push(className); }); return allClasses; }
获取一个Java对象
Frida
提供了一些API
来操作一个java的类,如下
-
获取一个Java类
var MainActivity = Java.use("com.demo.activity.MainActivity") var StringBuffer=Java.use("java.lang.util.StringBuffer")
-
新建一个Java类
在获取到类之后,创建类包括了两个方法
-
new一个对象
新建一个对象在
Frida
中需要使用clazz.$new(...)
方法才能创建一个对象 -
调用对象的构造函数
要调用一个对象的构造函数,则使用
clazz.$init()
方法
-
-
销毁一个Java类
对象的销毁使用
clazz.$dispose()
函数完成
例如
//构造一个BaseDexClassLoader对象
var BaseDexClassLoader = Java.use("dalvik.system.BaseDexClassLoader");
//获取一个DexFile对象
var DexFile= Java.use("dalvik.system.DexFile");
var dexfile = DexFile.$new("app_path");//执行app的路径,类似Android内的DexFile dexfile = new DexFile(app_path);一样的功能
获取app的所有加载的类
为了能获取到一个app的所有类,如下 code_02.js
//获取一个DexFile对象
var DexFile= Java.use("dalvik.system.DexFile");
var dexfile = DexFile.$new("app_path");//执行app的路径,类似Android内的DexFile dexfile = new DexFile(app_path);一样的功能
var entries = dexfile.entries();//获取所有的加载类,这个方法获取所有的加载类
var loaedClasses =[];
while(entries.hasMoreElements()){
loadedClasses.push(entries.nextElement());//保存加载的类型
}
console.log("all dexfileLoadedClasses"+loadedClasses);
获取app加载的所有so模块
获取所有加载的模块可以使用如下调用方式code_03.js
'use strict;'
setTimeout(function () {
Java.perform(function () {
//
console.log("Enumerate all loaded module ");
var allModdules = Process.enumerateModules();
console.log(" --> all loaded module" );
var str = JSON.stringify(allModdules,null,2);
console.log(""+str)
});
},0);
//输出内容
[
{
"name": "app_process64",
"base": "0x5569af1000",
"size": 32768,
"path": "/system/bin/app_process64"
},
{
"name": "libandroid_runtime.so",
"base": "0x714a699000",
"size": 1982464,
"path": "/system/lib64/libandroid_runtime.so"
},
...//省略更多
获取指定模块的所有Imports
使用module.enumerateImports() -->返回一个数组
code_04.js
'use strict;'
setTimeout(function () {
Java.perform(function () {
//
console.log("Enumerate all loaded module ");
var allModdules = Process.enumerateModules();
var module = allModdules[0