0%

jni动态注册

代码

java代码

1
2
3
4
5
6
7
8
9
10
11
// 文件:MainActivity.java
package com.jason.testys;

public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("native-lib");
}
//

public native void reginso();
}

cpp代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 文件:native-lib.cpp

#include <jni.h>
#include <android/log.h>
void native_test2() {
__android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "native_test2");
}

//注册Java端的方法 以及本地相对应的方法
JNINativeMethod method[] = {
{"reginso","()V",(void*)native_test2}
};

//注册相应的类以及方法
jint registerNativeMeth(JNIEnv *env){
jclass cl=env->FindClass("com/jason/testys/MainActivity");
if((env->RegisterNatives(cl,method,sizeof(method)/sizeof(method[0])))<0){
return -1;
}
return 0;
}


//实现jni_onload 动态注册方法
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
return -1;
}
if(registerNativeMeth(env)!=JNI_OK){//注册方法
return -1;
}
return JNI_VERSION_1_4;//必须返回这个值
}

IDA分析出的伪代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// jint registerNativeMeth(JNIEnv *env)

__int64 __fastcall registerNativeMeth(__int64 a1)
{
__int64 v1; // x19
__int64 v2; // x0

v1 = a1;
v2 = (*(__int64 (**)(void))(*(_QWORD *)a1 + 48LL))();
return (unsigned int)((*(signed int (__fastcall **)(__int64, __int64, char **, signed __int64))(*(_QWORD *)v1 + 1720LL))(
v1,
v2,
method,
1LL) >> 31);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// jint JNI_OnLoad(JavaVM* vm, void* reserved)

signed __int64 __fastcall JNI_OnLoad(__int64 a1)
{
unsigned __int64 v1; // x20
signed __int64 result; // x0
__int64 v3; // x19
__int64 v4; // x0
__int64 v5; // [xsp+0h] [xbp-10h]
__int64 v6; // [xsp+8h] [xbp-8h]

v1 = _ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2));
v6 = *(_QWORD *)(v1 + 40);
v5 = 0LL;
if ( (*(unsigned int (**)(void))(*(_QWORD *)a1 + 48LL))() )
{
result = 0xFFFFFFFFLL;
}
else
{
v3 = v5;
v4 = (*(__int64 (__fastcall **)(__int64, const char *))(*(_QWORD *)v5 + 48LL))(v5, "com/jason/testys/MainActivity");
if ( (*(signed int (__fastcall **)(__int64, __int64, char **, signed __int64))(*(_QWORD *)v3 + 1720LL))(
v3,
v4,
method,
1LL) < 0 )
result = 1LL;
else
result = 65540LL;
}
*(_QWORD *)(v1 + 40);
return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//java代码
JNINativeMethod method[] = {
{"reginso","()V",(void*)native_test2}
};

//伪代码
.data:0000000000002B08 ; Segment type: Pure data
.data:0000000000002B08 AREA .data, DATA, ALIGN=3
.data:0000000000002B08 ; ORG 0x2B08
.data:0000000000002B08 EXPORT method
.data:0000000000002B08 method DCQ aReginso ; DATA XREF: LOAD:00000000000000F8↑o
.data:0000000000002B08 ; LOAD:00000000000003B8↑o ...
.data:0000000000002B08 ; "reginso"
.data:0000000000002B10 DCQ aV ; "()V"
.data:0000000000002B18 DCQ _Z12native_test2v ; native_test2(void)
.data:0000000000002B18 ; .data ends
.data:0000000000002B18
extern:0000000000002B20 ; ===========================================================================
extern:0000000000002B20
extern:0000000000002B20 ; Segment type: Externs
extern:0000000000002B20 IMPORT __cxa_finalize ; CODE XREF: .__cxa_finalize+C↑j
extern:0000000000002B20 ; DATA XREF: .got.plt:off_1AE8↑o
extern:0000000000002B28 IMPORT __cxa_atexit ; CODE XREF: .__cxa_atexit+C↑j
extern:0000000000002B28 ; DATA XREF: .got.plt:off_1AF0↑o
extern:0000000000002B30 IMPORT __android_log_print
extern:0000000000002B30 ; CODE XREF: .__android_log_print+C↑j
extern:0000000000002B30 ; DATA XREF: .got.plt:off_1AF8↑o
extern:0000000000002B38 IMPORT __stack_chk_fail ; CODE XREF: .__stack_chk_fail+C↑j
extern:0000000000002B38 ; DATA XREF: .got.plt:off_1B00↑o
extern:0000000000002B38
extern:0000000000002B38 END start

分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//java代码
JNIEnv* env = NULL;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
return -1;
}

//伪代码
v5 = 0LL;
if ( (*(unsigned int (**)(void))(*(_QWORD *)a1 + 48LL))() )
{
result = 0xFFFFFFFFLL;
}
else
{
v3 = v5;
}

//分析
1. a1 = vm
2. v5 = env
3. (*(_QWORD *)a1 + 48LL) = vm->GetEnv
4. v5被赋值了
1
2
3
4
5
6
7
8
9
10
11
12
13
//java代码
jclass cl=env->FindClass("com/jason/testys/MainActivity");

//伪代码
v3 = v5;
v4 = (*(__int64 (__fastcall **)(__int64, const char *))(*(_QWORD *)v5 + 48LL))(v5, "com/jason/testys/MainActivity");


//分析
1. v5 = env
2. (*(_QWORD *)v5 + 48LL) = env->FindClass
3. (v5, "com/jason/testys/MainActivity") = ("com/jason/testys/MainActivity")
4. v4 = jclass cl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//java代码
if((env->RegisterNatives(cl,method,sizeof(method)/sizeof(method[0])))<0){
return -1;
}

//伪代码
if ( (*(signed int (__fastcall **)(__int64, __int64, char **, signed __int64))(*(_QWORD *)v3 + 1720LL))(
v3,
v4,
method,
1LL) < 0 )
result = 1LL;
else
result = 65540LL;

//分析
0. v4 = cl
1. v3 = env
2. (*(_QWORD *)v3 + 1720LL) = env->RegisterNatives
3. (v3, v4, method, 1LL) = (cl, method, sizeof(method)/sizeof(method[0])))<0)
  • 结果
1
2
3
4
5
6
7
8
9
10
11
12
13
// 参数数量变化

GetEnv: 2 -> 0
vm->GetEnv((void**) &env, JNI_VERSION_1_4)
(*(_QWORD *)a1 + 48LL)()

FindClass: 1 -> 2
env->FindClass("com/jason/testys/MainActivity")
(*(_QWORD *)v5 + 48LL)(v5, "com/jason/testys/MainActivity")

RegisterNatives: 3 -> 4
env->RegisterNatives(cl,method,1)
(*(_QWORD *)v3 + 1720LL)(v3,v4,method,1LL)