首页
社区
课程
招聘
[原创]frida源码阅读之frida-java
发表于: 2018-6-27 11:06 31931

[原创]frida源码阅读之frida-java

2018-6-27 11:06
31931

frida的JavaScript API按功能划分了许多模块,frida-java具体实现了其中的Java模块,提供了Java Runtime相关的API。我们知道JNI连接了native世界和java世界,而frida-java相当于实现了一个js世界到java世界的单向通道。利用frida-java,我们可以使用js代码实现:调用java方法、创建java对象、对java函数进行hook等操作。

frida-java源码结构如下:

接下来通过下面两个问题来分析frida-java源码:

总的来说frida-java通过两步实现js世界到java世界的单向通道,首先利用frida-gum提供的js接口操作native世界,然后再基于jni连通到java世界。

主要步骤如下:

利用frida-gum中提供的Module、Memory、NativeFunction等模块,可以实现查找、调用、hook导出函数;读写、分配内存等操作。如下面例子所示, 可以在js代码中调用native函数。

想要使用JNI连通java世界,首先需要获取的就是JavaVM,frida-java通过调用JNI_GetCreatedJavaVMs来获取JavaVM,Dalvik虚拟机和ART虚拟机均实现了该函数。核心代码如下:

此时获取的vm只是JavaVM的一个指针,在此基础上frida-java还会构造一个VM对象,该对象相当于在js层实现了一个JavaVM的代理对象,封装了一些JavaVM的方法,如getEnv,其中vm.handle中保存的是原始的JavaVM对象。

VM的初始化过程为首先获取JavaVM的指针(通过JNI_GetCreatedJavaVMs调用),然后读取JavaVM的虚函数表,获得JavaVM的一些重要方法,并在js层包装一层,这样就在js层实现了一个JavaVM的代理,可以通过调用VM.getEnv来实现native层的JavaVM.getEnV调用。

获取到JavaVM后,就可以通过将当前线程与JavaVM相关联,然后得到JNIEnv对象,进行后续操作。上述工作由VM.perform完成,看下VM.perform源码:

和JavaVM一样,frida-java也会在js层为JNIEnv建立一个代理,具体在env.js实现

和JNI操作方式一样,我们在native层获得了JNIEnv后,要想操作java类,可以通过调用env->findClass来获得java类的class引用。但是这里有个问题,因为frida-java所在的线程是通过pthread_create创造的,然后通过AttachCurrentThread获取的JNIEnv,此时FindClass只会从系统的classloader开始查找,所以app自身的类是无法通过env->findClass来获取。因此需要手工的获取到加载该app的classloader。Java.perform在调用VM.perform之前会先获取加载该app的classloader,并保存到classFactory.loader。

frida-java使用Java.use来获得java类的class引用,Java.use(className),返回java类的一个wrapper,在js世界里,用该wrapper来操作对应的java类。Java.use直接调用了classFactory.use,代码如下:

借助于该wrapper,可以对java类进行操作,如调用构造函数创建对象。该wrapper的初始化过程如下:

借助于该wrapper的$init方法,就可以创建java对象。

frida-java采用常见的Dalvik Hook方案,将待hook的java函数修改为native函数,当调用该函数时,会执行自定义的native函数。但是和其他hook框架不同的是,使用frida时,我们hook的代码是js实现的,所以有一个基于js代码生成native函数过程。具体hook实现代码如下:

hook后执行的native函数就是用implement函数实现的,该函数时最终调用frida-node的new NativeCallback接口实现将js函数转换为native函数。

常见的ART Hook方法为:替换方法的入口点,即ArtMethod的entry_point_from_quick_compiledcode,并将原方法的信息备份到entry_point_fromjni。替换后的入口点,会重新准备栈和寄存器,执行hook的方法。

frida-java采用的hook方法,我在其他地方并未遇见过,其原理为:首先将方法native化,然后将ArtMethod的entry_point_fromjni替换为hook的方法,并将entry_point_from_quick_compiledcode替换为art_quick_generic_jni_trampoline。当调用被hook的方法时,首先会跳转到art_quick_generic_jni_trampoline,该函数会做一些jni调用的准备,然后跳转到ArtMethod结构的entry_point_fromjni所指向的hook方法,这样就完成了一次hook。完成art hook的源码如下:

然后看下art_quick_generic_jni_trampoline源码,art_quick_generic_jni_trampoline主要负责jni调用的准备,包括堆栈的设置,参数的设置等。个人能力有限只能大概看看流程。

主要是将调用约定转换为c的调用约定,将参数准备好,然后调用artQuickGenericJniTrampoline,该函数源码如下:

笔记分析的还是很粗糙的,发出来是希望可以抛砖引玉,可以在论坛看到更多frida的文章,如有错误,恳请大佬指出。

 
 
 
 
var friendlyFunctionName = new NativeFunction(friendlyFunctionPtr, 'void', ['pointer', 'pointer']);
var returnValue = Memory.alloc(sizeOfLargeObject);
friendlyFunctionName(returnValue, thisPtr);
//lib/android.js
const vms = Memory.alloc(pointerSize);
const vmCount = Memory.alloc(jsizeSize);
checkJniResult('JNI_GetCreatedJavaVMs', temporaryApi.JNI_GetCreatedJavaVMs(vms, 1, vmCount));
if (Memory.readInt(vmCount) === 0) {
  return null;
}
temporaryApi.vm = Memory.readPointer(vms);

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 3
支持
分享
最新回复 (24)
雪    币: 208
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
Frida在腾讯手游助手这个模拟器上,会导致蓝屏
2018-6-27 14:00
0
雪    币: 144
活跃值: (335)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
尝试ptrace都会蓝吧
2018-6-27 17:01
0
雪    币: 2719
活跃值: (1595)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
4
YerikK Frida在腾讯手游助手这个模拟器上,会导致蓝屏
你可以 看看 他的代码  为何导致 蓝屏
2018-7-12 22:17
0
雪    币: 208
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
Vn小帆 你可以 看看 他的代码 为何导致 蓝屏
谁的代码。。。模拟器的吗?模拟器的代码没有源码好吧。。。
2018-7-14 15:08
0
雪    币: 2719
活跃值: (1595)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
YerikK 谁的代码。。。模拟器的吗?模拟器的代码没有源码好吧。。。
你可以反编译啊
2018-7-14 15:48
0
雪    币: 839
活跃值: (2832)
能力值: ( LV11,RANK:190 )
在线值:
发帖
回帖
粉丝
7
很棒啊
2018-7-17 10:45
0
雪    币: 6
活跃值: (135)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
这是兼容性问题吧,artmethod这个东西在很多定制系统和模拟器上是有变化的
2019-1-18 17:47
0
雪    币: 0
活跃值: (1525)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
666
2019-1-18 18:28
0
雪    币: 294
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
原issue地址是:https://github.com/frida/frida-java/issues/78
问题是:

I have a question in "java.lang.Class.getMethod".

public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { return getMethod(name, parameterTypes, true); }

the second parameter need a "[Ljava.lang.Object;" type, and java code like this:

getMethod("say", new Class[]{String.class,int.class});
getMethod("say", new Class[]{Integer.TYPE,Integer.TYPE});

so How can i create this array using js or other ways ?

in addition,I created a obj array like this:
var Integerclass = Java.use("java.lang.Integer");
var objectArr = Java.array('Ljava.lang.Class;',[Integerclass.TYPE,Integerclass.TYPE]);

but i got a "invalid argument value" error.
{'type': 'error', 'description': 'Error: invalid argument value', 'stack': 'Error: invalid argument value\n at frida/node_modules/frida-java/lib/env.js:515\n at frida/node_modules/frida-java/lib/class-factory.js:2592\n at toJniObjectArray (frida/node_modules/frida-java/lib/class-factory.js:2640)\n at java.js:4489\n at frida/node_modules/frida-java/lib/class-factory.js:743\n at [anon] (script1.js:28)\n at input:1', 'fileName': 'frida/node_modules/frida-java/lib/env.js', 'lineNumber': 515, 'columnNumber': 1}

这个问题我也遇到了,就是在js中反射方式调用java的函数,那么就需要创建java.lang.Class类型的数组,在Java中,基本类型可以表达为int.class,boolean.class等,但是就如上面问题所诉,在frida的script中该如何创建int.class,boolean.class等呢。
2019-4-17 00:58
0
雪    币: 182
活跃值: (555)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
11
我叫菠菜的菠 原issue地址是:https://github.com/frida/frida-java/issues/78 问题是: I have a question in "java.lan ...
 var intClass = Java.use("java.lang.Integer").class;
 var booleanClass = Java.use("java.lang.Boolean").class;
 var objectArr = Java.array("Ljava.lang.Class;", [intClass, booleanClass]);
2019-4-17 10:17
0
雪    币: 294
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
大佬,你看我提到的那个问题没有,其实是这样的,假如我有个函数是:
public int test(int i){
        return i;
    }
那么我在frida中也可以用反射的方式调用此函数,那么我的js代码可以这样写:
var Platform1 = Java.use("com.example.cryptutils.util.Test");
var method = Platform1.class.getDeclaredMethod("test",Java.array('java.lang.Class', [xxx]) );
这里构造getDeclaredMethod函数的时候,第二次参数是一个Class类型的数组,就是test函数入参的class类型的数组是不是。
按照java的写法,Java.array('java.lang.Class', [xxx])这里的xxx应该就是int.class,但是js是识别不了int.class,那就就需要构造,按照你的写法,int.class 写成了Java.use("java.lang.Integer").class的话,那就这里的method变量就称为了:
var method = Platform1.class.getDeclaredMethod("test",Java.array('java.lang.Class', [Java.use("java.lang.Integer").class]) );
但是在java中int.class 和Java.use("java.lang.Integer").class是两回事,就会导致frida直接抛出MethodNotFound的错误。
2019-4-17 14:04
0
雪    币: 294
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
glider菜鸟 var intClass = Java.use("java.lang.Integer").class; var booleanClass = Java.use("j ...
盼大佬回复的啊,这个问题已经很久了一直都在解决,其实在github上也有人提了这问题,当时他的做法是
var integerClass = Java.use("java.lang.Integer");
var intClass = integerClass.TYPE;
这样来代替,因为在java中int.class == Integer.TYPE;但是这样的话,在js中构造Class数组,Java.array('java.lang.Class', [integerClass.TYPE]) 
这样构造的话,frida出会报错:invalid argument value的错误。
2019-4-17 14:14
0
雪    币: 2375
活跃值: (433)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
YerikK Frida在腾讯手游助手这个模拟器上,会导致蓝屏
安卓不会蓝屏吧,导致windows蓝屏?
2019-6-13 16:09
0
雪    币: 2375
活跃值: (433)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
YerikK Frida在腾讯手游助手这个模拟器上,会导致蓝屏
android.js,为什么很多js文件?
2019-6-13 16:21
0
雪    币: 574
活跃值: (405)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
高手,膜拜下,先mark慢慢学习
2019-6-14 15:12
0
雪    币: 431
活跃值: (2779)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
厉害
2019-11-5 23:29
0
雪    币: 19
活跃值: (1086)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
我叫菠菜的菠 盼大佬回复的啊,这个问题已经很久了一直都在解决,其实在github上也有人提了这问题,当时他的做法是 var integerClass = Java.use("java.lang.Inte ...
var Integer = Java.use("java.lang.Integer");

var int_clz=Integer.class.getField("TYPE").get(null);

console.warn(int_clz);

var Bool=Java.use("java.lang.Boolean");

var boolean_clz=Bool.class.getField("TYPE").get(null);

console.warn(boolean_clz);

var Byte=Java.use("java.lang.Byte");

var byte_clz=Byte.class.getField("TYPE").get(null);

console.warn(byte_clz);
2019-11-5 23:31
0
雪    币: 55
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
怎么把frida-java集成到vscode里面去编写然后编译的啊????
2019-11-23 10:25
0
雪    币: 431
活跃值: (2779)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
mark
2019-11-25 23:34
0
雪    币: 22
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
21
您好,大佬,请问一下包含replaceDalvikImplementation的js文件是在frida-server的代码嘛?好像没找到 frida-server 的对应代码
2020-4-28 20:17
0
雪    币: 2141
活跃值: (7226)
能力值: ( LV11,RANK:180 )
在线值:
发帖
回帖
粉丝
22
 
2020-5-17 19:05
0
雪    币: 319
活跃值: (626)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
23
mark
2020-7-5 10:47
0
雪    币: 4128
活跃值: (869)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
24
YerikK Frida在腾讯手游助手这个模拟器上,会导致蓝屏
很明显,模拟器有保护,TP保护
2020-11-13 10:08
0
游客
登录 | 注册 方可回帖
返回
//