[关闭]
@oro-oro 2015-08-19T10:39:22.000000Z 字数 13916 阅读 5943

三、JNI_Onload之RegisterNatives

IDAForAndroid


通过实例来了解本地函数注册原理,以及如何分析加密后的本地函数对应关系。

1. 例子1

在hello-jni项目,Java_com_example_hellojni_HelloJni_stringFromJNI这种函数名太麻烦了,所以,有必要重新注册一下本地函数。

stringFromJNI注册为fun1,fun注册为fun2。

  1. #include <string.h>
  2. #include <jni.h>
  3. #include <android/log.h>
  4. #define TAG "NATIVE DEBUG LOG"
  5. #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)
  6. #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , TAG, __VA_ARGS__)
  7. #define LOGI(...) __android_log_print(ANDROID_LOG_INFO , TAG, __VA_ARGS__)
  8. #define LOGW(...) __android_log_print(ANDROID_LOG_WARN , TAG, __VA_ARGS__)
  9. #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , TAG, __VA_ARGS__)
  10. jstring stringFromJNI( JNIEnv* env, jobject thiz )
  11. {
  12. #if defined(__arm__)
  13. #if defined(__ARM_ARCH_7A__)
  14. #if defined(__ARM_NEON__)
  15. #if defined(__ARM_PCS_VFP)
  16. #define ABI "armeabi-v7a/NEON (hard-float)"
  17. #else
  18. #define ABI "armeabi-v7a/NEON"
  19. #endif
  20. #else
  21. #if defined(__ARM_PCS_VFP)
  22. #define ABI "armeabi-v7a (hard-float)"
  23. #else
  24. #define ABI "armeabi-v7a"
  25. #endif
  26. #endif
  27. #else
  28. #define ABI "armeabi"
  29. #endif
  30. #elif defined(__i386__)
  31. #define ABI "x86"
  32. #elif defined(__x86_64__)
  33. #define ABI "x86_64"
  34. #elif defined(__mips64) /* mips64el-* toolchain defines __mips__ too */
  35. #define ABI "mips64"
  36. #elif defined(__mips__)
  37. #define ABI "mips"
  38. #elif defined(__aarch64__)
  39. #define ABI "arm64-v8a"
  40. #else
  41. #define ABI "unknown"
  42. #endif
  43. return (*env)->NewStringUTF(env, "Hello from JNI ! Compiled with ABI " ABI ".");
  44. }
  45. void fun(JNIEnv* env,jobject thiz){
  46. LOGI("Hello JNI!");
  47. }
  48. JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* pVm, void* reserved)
  49. {
  50. JNIEnv* env;
  51. if ((*pVm)->GetEnv(pVm, (void **)&env, JNI_VERSION_1_6)) {
  52. return -1;
  53. }
  54. JNINativeMethod nm[2];
  55. nm[0].name = "fun1";
  56. nm[0].signature = "()Ljava/lang/String;";
  57. nm[0].fnPtr = stringFromJNI;
  58. nm[1].name = "fun2";
  59. nm[1].signature = "()V";
  60. nm[1].fnPtr = fun;
  61. jclass cls = (*env)->FindClass(env, "com/example/hellojni/HelloJni");
  62. // Register methods with env->RegisterNatives.
  63. (*env)->RegisterNatives(env, cls, nm, 2);
  64. return JNI_VERSION_1_6;
  65. }
  1. LOCAL_PATH := $(call my-dir)
  2. include $(CLEAR_VARS)
  3. LOCAL_MODULE := hello-jni
  4. LOCAL_SRC_FILES := hello-jni.c
  5. LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog
  6. include $(BUILD_SHARED_LIBRARY)
  1. APP_ABI := armeabi

编译:

  1. $ ndk-build
  2. [armeabi] Gdbserver : [arm-linux-androideabi-4.8] libs/armeabi/gdbserver
  3. [armeabi] Gdbsetup : libs/armeabi/gdb.setup
  4. [armeabi] Compile thumb : hello-jni <= hello-jni.c
  5. [armeabi] SharedLibrary : libhello-jni.so
  6. [armeabi] Install : libhello-jni.so => libs/armeabi/libhello-jni.so

显示完JNI函数,直接看F5伪代码。函数的对应关系还是比较清晰的。

  1. signed int __fastcall JNI_OnLoad(int a1)
  2. {
  3. signed int v1; // r3@2
  4. int v3; // [sp+8h] [bp-2Ch]@1
  5. int v4; // [sp+Ch] [bp-28h]@3
  6. int v5; // [sp+10h] [bp-24h]@3
  7. int v6; // [sp+14h] [bp-20h]@3
  8. int (__fastcall *v7)(int); // [sp+18h] [bp-1Ch]@3
  9. int v8; // [sp+1Ch] [bp-18h]@3
  10. char v9[4]; // [sp+20h] [bp-14h]@3
  11. int (*v10)(); // [sp+24h] [bp-10h]@3
  12. if ( (*(int (__cdecl **)(int, int *))(*(_DWORD *)a1 + offsetof(JNINativeInterface, FindClass)))(a1, &v3) )
  13. {
  14. v1 = -1;
  15. }
  16. else
  17. {
  18. v5 = (int)"fun1";
  19. v6 = (int)"()Ljava/lang/String;";
  20. v7 = stringFromJNI;
  21. v8 = (int)"fun2";
  22. *(_DWORD *)v9 = "()V";
  23. v10 = fun;
  24. v4 = (*(int (__fastcall **)(int, _DWORD))(*(_DWORD *)v3 + offsetof(JNINativeInterface, FindClass)))(
  25. v3,
  26. "com/example/hellojni/HelloJni");
  27. (*(void (__fastcall **)(int, int, int *, signed int))(*(_DWORD *)v3 + offsetof(JNINativeInterface, RegisterNatives)))(
  28. v3,
  29. v4,
  30. &v5,
  31. 2);
  32. v1 = 65542;
  33. }
  34. return v1;
  35. }
  1. int __fastcall stringFromJNI(int a1)
  2. {
  3. return (*(int (__cdecl **)(int, _DWORD))(*(_DWORD *)a1 + offsetof(JNINativeInterface, NewStringUTF)))(
  4. a1,
  5. "Hello from JNI ! Compiled with ABI armeabi.");
  6. }
  1. int fun()
  2. {
  3. return _android_log_print(4, "NATIVE DEBUG LOG", "Hello JNI!");
  4. }

2. 例子2

《Android 软件安全与逆向分析》9.6.2的例子。
http://yunpan.cn/cdRWxKaf9nJuL 访问密码 0939

除了常见的B指令外,LDR PC, #Address也是一种常见的函数调用指令。

  1. .text:00001374 LDR R3, [R3]
  2. .text:00001378 MOV LR, PC
  3. .text:0000137C LDR PC, [R3,#JNINativeInterface.FindClass] ; 函数调用
  4. .text:00001380 LDR R2, =(native_class_ptr - 0x1394)
  5. .text:00001384 LDR R3, [R5]
  6. .text:00001388 MOV R1, R0
  7. .text:0000138C LDR R2, [PC,R2] ; native_class
  8. .text:00001390 STR R0, [R2]
  9. .text:00001394 LDR R2, =(__data_start - 0x13A8)
  10. .text:00001398 MOV R0, R3
  11. .text:0000139C LDR R12, [R3]
  12. .text:000013A0 ADD R2, PC, R2 ; __data_start
  13. .text:000013A4 MOV R3, #3
  14. .text:000013A8 MOV LR, PC
  15. .text:000013AC LDR PC, [R12,#JNINativeInterface.RegisterNatives] ; 函数调用
  16. .text:000013B0 CMP R0, #0
  17. .text:000013B4 BNE loc_13D8
  18. .text:000013B8 LDR R2, =(aRegisternative - 0x13CC)

JNI_OnLoad的伪代码:

  1. signed int __fastcall JNI_OnLoad(int a1)
  2. {
  3. signed int result; // r0@2
  4. if ( (*(int (**)(void))(*(_DWORD *)a1 + 24))() )
  5. {
  6. result = -1;
  7. }
  8. else
  9. {
  10. _android_log_print(2, "com.droider.ndkapp", "JNI_OnLoad()");
  11. native_class = (*(int (__fastcall **)(_DWORD *, _DWORD))(*g_env + offsetof(JNINativeInterface, FindClass)))(
  12. g_env,
  13. "com/droider/ndkapp/MyApp");
  14. if ( (*(int (__fastcall **)(_DWORD *, _DWORD, _DWORD, signed int))(*g_env
  15. + offsetof(JNINativeInterface, RegisterNatives)))(
  16. g_env,
  17. native_class,
  18. _data_start,
  19. 3) )
  20. {
  21. _android_log_print(6, "com.droider.ndkapp", "RegisterNatives() --> nativeMethod() failed");
  22. result = -1;
  23. }
  24. else
  25. {
  26. _android_log_print(2, "com.droider.ndkapp", "RegisterNatives() --> nativeMethod() ok");
  27. result = 65542;
  28. }
  29. }
  30. return result;
  31. }

RegisterNatives函数注册的是一个函数数组,_data_start就是保存函数的数组。

单击进去,看看_data_start,便可以找到函数的对应关系了。

  1. .data:00004EA4 ; Segment type: Pure data
  2. .data:00004EA4 AREA .data, DATA
  3. .data:00004EA4 ; ORG 0x4EA4
  4. .data:00004EA4 EXPORT __data_start
  5. .data:00004EA4 __data_start DCD aInitsn ; DATA XREF: JNI_OnLoad+8Co
  6. .data:00004EA4 ; .text:off_1408o
  7. .data:00004EA4 ; "initSN"
  8. .data:00004EA8 DCD aV ; "()V"
  9. .data:00004EAC DCD n1
  10. .data:00004EB0 DCD aSavesn ; "saveSN"
  11. .data:00004EB4 DCD aLjavaLangStrin ; "(Ljava/lang/String;)V"
  12. .data:00004EB8 DCD n2
  13. .data:00004EBC DCD aWork ; "work"
  14. .data:00004EC0 DCD aV ; "()V"
  15. .data:00004EC4 DCD n3

3. 例子3

有时候这个数组可能是加密过的,这就需要去解密这个数组了。
例子:http://yunpan.cn/cdMsjyYeKbdRj 访问密码 cabb

这里主要是分析,该样本的函数对应关系。

jniExport 类下面有这些native函数:

  1. public native void nq10(String arg1, String arg2, int arg3) {
  2. }
  3. public native void nq11(String arg1, int arg2) {
  4. }
  5. public native void nq12(Context arg1, ClassLoader arg2, int arg3) {
  6. }
  7. public native void nq13(String arg1, int arg2) {
  8. }
  9. public native void nq14(String arg1, int arg2) {
  10. }

用IDA打开nqshield.so,却没有发现对应的函数,直接看JNI_OnLoad函数。

  1. signed int __fastcall JNI_OnLoad(int a1)
  2. {
  3. int v1; // r4@1
  4. int v2; // r3@1
  5. int v3; // r4@2
  6. int v4; // r0@2
  7. int v5; // r1@2
  8. signed int result; // r0@4
  9. int v7; // [sp+4h] [bp-Ch]@1
  10. v1 = a1;
  11. sub_2438();
  12. v2 = *(_DWORD *)v1;
  13. v7 = 0;
  14. if ( (*(int (__fastcall **)(int, int *, signed int))(v2 + offsetof(JNINativeInterface, FindClass)))(v1, &v7, 65540)
  15. || (v3 = v7,
  16. v4 = dcf13197d7a5901a5ad213f34001fe4(79),
  17. (v5 = (*(int (__fastcall **)(int, int))(*(_DWORD *)v3 + offsetof(JNINativeInterface, FindClass)))(v3, v4)) == 0) )
  18. {
  19. result = -1;
  20. }
  21. else if ( (*(int (__fastcall **)(int, int, int *, signed int))(*(_DWORD *)v3
  22. + offsetof(JNINativeInterface, RegisterNatives)))(
  23. v3,
  24. v5,
  25. &dword_D004, // 这里就是注册的函数素组。
  26. 5) < 0 )
  27. {
  28. result = -1;
  29. }
  30. else
  31. {
  32. result = 65540;
  33. }
  34. return result;
  35. }

点击dword_D004,跳到对应的数组地址:

  1. .data:0000D004 00 00 00 00 dword_D004 DCD 0 ; DATA XREF: JNI_OnLoad+74o
  2. .data:0000D004 ; .text:off_64BCo ...
  3. .data:0000D008 00 00 00 00 dword_D008 DCD 0 ; DATA XREF: sub_64C0+20w
  4. .data:0000D00C 4C 22 00 00 DCD b9df1ce797fd03603fd7137afff2957
  5. .data:0000D010 00 00 00 00 dword_D010 DCD 0 ; DATA XREF: sub_64C0+2Cw
  6. .data:0000D014 00 00 00 00 dword_D014 DCD 0 ; DATA XREF: sub_64C0+38w
  7. .data:0000D018 78 23 00 00 DCD eb5993d402df42eac47e82555b7ae31
  8. .data:0000D01C 00 00 00 00 dword_D01C DCD 0 ; DATA XREF: sub_64C0+44w
  9. .data:0000D020 00 00 00 00 dword_D020 DCD 0 ; DATA XREF: sub_64C0+50w
  10. .data:0000D024 6C 61 00 00 DCD fa3f3a501e8754e88bed48c128ef90
  11. .data:0000D028 00 00 00 00 dword_D028 DCD 0 ; DATA XREF: sub_64C0+5Cw
  12. .data:0000D02C 00 00 00 00 dword_D02C DCD 0 ; DATA XREF: sub_64C0+68w
  13. .data:0000D030 48 5D 00 00 DCD abc020d3ee6fbc05ab1ed6b4da7252d
  14. .data:0000D034 00 00 00 00 dword_D034 DCD 0 ; DATA XREF: sub_64C0+74w
  15. .data:0000D038 00 00 00 00 dword_D038 DCD 0 ; DATA XREF: sub_64C0+80w
  16. .data:0000D03C 10 58 00 00 DCD e300588cc034bcbaa7d61

以上有5组函数关系:

函数名 参数 本地方法
dword_D004 dword_D008 b9df1ce797fd03603fd7137afff2957
dword_D010 dword_D014 eb5993d402df42eac47e82555b7ae31
dword_D01C dword_D020 fa3f3a501e8754e88bed48c128ef90
dword_D028 dword_D02C abc020d3ee6fbc05ab1ed6b4da7252d
dword_D034 dword_D038 e300588cc034bcbaa7d61

dword_****,这些都是字符串来的,这些东西在哪里初始化的呢?
因为这个在JNI_OnLoad函数就要使用了,那么这些字符串,肯定在该函数之前初始化的。
譬如,.init_array

按快捷键Shift+F7或者View->Open Subview->Segments,可以打开段视图。

Segments

点击进去:

  1. .init_array:0000CD24 ; Segment type: Pure data
  2. .init_array:0000CD24 AREA .init_array, DATA
  3. .init_array:0000CD24 ; ORG 0xCD24
  4. .init_array:0000CD24 C0 64 00 00 DCD sub_64C0
  5. .init_array:0000CD28 29 8C 00 00 DCD sub_8C28+1
  6. .init_array:0000CD2C 00 00 00 00 ALIGN 0x10
  7. .init_array:0000CD2C ; .init_array ends

不过,本人直接按快捷键x,调出dword_D004的交叉引用窗口,看它是在哪里初始化的。
交叉引用

选中w,数据写入的地址,进去,可以找到初始化的代码:

  1. int sub_64C0()
  2. {
  3. int result; // r0@1
  4. dword_D004 = dcf13197d7a5901a5ad213f34001fe4(110);
  5. dword_D008 = dcf13197d7a5901a5ad213f34001fe4(115);
  6. dword_D010 = dcf13197d7a5901a5ad213f34001fe4(111);
  7. dword_D014 = dcf13197d7a5901a5ad213f34001fe4(116);
  8. dword_D01C = dcf13197d7a5901a5ad213f34001fe4(112);
  9. dword_D020 = dcf13197d7a5901a5ad213f34001fe4(117);
  10. dword_D028 = dcf13197d7a5901a5ad213f34001fe4(113);
  11. dword_D02C = dcf13197d7a5901a5ad213f34001fe4(118);
  12. dword_D034 = dcf13197d7a5901a5ad213f34001fe4(114);
  13. result = dcf13197d7a5901a5ad213f34001fe4(119);
  14. dword_D038 = result;
  15. return result;
  16. }

解密函数找到了,剩下就是解密问题了。
接下来直接调用dcf13197d7a5901a5ad213f34001fe4方法进行解密即可。

点击函数,去看看它的原型:

  1. int __fastcall dcf13197d7a5901a5ad213f34001fe4(int result)

快捷键Tab,切反汇编视图,查看该函数名:

  1. .text:00002A18
  2. .text:00002A18 ; dcf13197d7a5901a5ad213f34001fe4(myString)
  3. .text:00002A18 EXPORT _Z31dcf13197d7a5901a5ad213f34001fe48myString
  4. .text:00002A18 _Z31dcf13197d7a5901a5ad213f34001fe48myString
  5. .text:00002A18 ; CODE XREF: e78be2435917208c8fa0c2af796f6c38(_JNIEnv *,_jobject *,_jobject *,_jobject *)+1Cp
  6. .text:00002A18 ; e78be2435917208c8fa0c2af796f6c38(_JNIEnv *,_jobject *,_jobject *,_jobject *)+40p ...
  7. .text:00002A18 CMP R0, #0x9C ; switch 157 cases
  8. .text:00002A1C ADDLS PC, PC, R0,LSL#2 ; switch jump
  9. .text:00002A20 ; ---------------------------------------------------------------------------
  10. .text:00002A20
  11. .text:00002A20 loc_2A20 ; CODE XREF: dcf13197d7a5901a5ad213f34001fe4(myString)+4j
  12. .text:00002A20 B locret_363C ; jumptable 00002A1C default case
  13. .text:00002A24 ; ---------------------------------------------------------------------------
  14. .text:00002A24

_Z31dcf13197d7a5901a5ad213f34001fe48myString就是这个解密函数的名字。

接下来就可以写代码,调用so解密了:
hello.c

  1. /* hello.c: Hello World program */
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <dlfcn.h>
  5. int main(int argc, char* argv[]){
  6. int (*decode)(int);
  7. void *handle;
  8. handle = dlopen("/data/local/tmp/libnqshield.so", RTLD_LOCAL | RTLD_LAZY);
  9. if ( !handle) {
  10. printf("%s,%d, NULL == handle\n", __FUNCTION__, __LINE__);
  11. return -1;
  12. }
  13. decode = (int (*)(int)) dlsym(handle, "_Z31dcf13197d7a5901a5ad213f34001fe48myString");
  14. const char *errstr;
  15. errstr = (char *) dlerror();
  16. if (errstr != NULL)
  17. printf ("A dynamic linking error occurred: (%s)\n", errstr);
  18. printf("%s\n", decode(110));
  19. printf("%s\n", decode(115));
  20. printf("%s\n", decode(111));
  21. printf("%s\n", decode(116));
  22. printf("%s\n", decode(112));
  23. printf("%s\n", decode(117));
  24. printf("%s\n", decode(113));
  25. printf("%s\n", decode(118));
  26. printf("%s\n", decode(114));
  27. printf("%s\n", decode(119));
  28. dlclose(handle);
  29. }

makefile

  1. NDK_ROOT=D:\android-ndk-r10d
  2. TOOLCHAINS_ROOT=$(NDK_ROOT)/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64
  3. TOOLCHAINS_PREFIX=$(TOOLCHAINS_ROOT)/bin/arm-linux-androideabi
  4. TOOLCHAINS_INCLUDE=$(TOOLCHAINS_ROOT)/lib/gcc/arm-linux-androideabi/4.9/include-fixed
  5. PLATFORM_ROOT=$(NDK_ROOT)/platforms/android-19/arch-arm
  6. PLATFORM_INCLUDE=$(PLATFORM_ROOT)/usr/include
  7. PLATFORM_LIB=$(PLATFORM_ROOT)/usr/lib
  8. MODULE_NAME=hello
  9. RM=rm
  10. FLAGS=-I$(TOOLCHAINS_INCLUDE) \
  11. -I$(PLATFORM_INCLUDE) \
  12. -L$(PLATFORM_LIB) \
  13. -nostdlib \
  14. -lgcc \
  15. -Bdynamic \
  16. -lc
  17. OBJS=$(MODULE_NAME).o \
  18. $(PLATFORM_LIB)/crtbegin_dynamic.o \
  19. $(PLATFORM_LIB)/crtend_android.o
  20. all:
  21. $(TOOLCHAINS_PREFIX)-gcc $(FLAGS) -E $(MODULE_NAME).c -o $(MODULE_NAME).i
  22. $(TOOLCHAINS_PREFIX)-gcc $(FLAGS) -S $(MODULE_NAME).i -o $(MODULE_NAME).s
  23. $(TOOLCHAINS_PREFIX)-gcc $(FLAGS) -c $(MODULE_NAME).s -o $(MODULE_NAME).o
  24. $(TOOLCHAINS_PREFIX)-gcc $(FLAGS) -ldl $(OBJS) -o $(MODULE_NAME)
  25. clean:
  26. $(RM) *.o
  27. install:
  28. adb push $(MODULE_NAME) /data/local/tmp/
  29. adb push libnqshield.so /data/local/tmp/
  30. adb shell chmod 755 /data/local/tmp/$(MODULE_NAME)
  31. adb shell /data/local/tmp/$(MODULE_NAME)

编译,执行

  1. $ make
  2. D:\android-ndk-r10d/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-gcc -ID:\android-ndk-r10d/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9/include-fixed -ID:\android-ndk-r10d/platforms/android-19/arch-arm/usr/include -LD:\android-ndk-r10d/platforms/android-19/arch-arm/usr/lib -nostdlib -lgcc -Bdynamic -lc -E hello.c -o hello.i
  3. D:\android-ndk-r10d/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-gcc -ID:\android-ndk-r10d/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9/include-fixed -ID:\android-ndk-r10d/platforms/android-19/arch-arm/usr/include -LD:\android-ndk-r10d/platforms/android-19/arch-arm/usr/lib -nostdlib -lgcc -Bdynamic -lc -S hello.i -o hello.s
  4. D:\android-ndk-r10d/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-gcc -ID:\android-ndk-r10d/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9/include-fixed -ID:\android-ndk-r10d/platforms/android-19/arch-arm/usr/include -LD:\android-ndk-r10d/platforms/android-19/arch-arm/usr/lib -nostdlib -lgcc -Bdynamic -lc -c hello.s -o hello.o
  5. D:\android-ndk-r10d/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-gcc -ID:\android-ndk-r10d/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9/include-fixed -ID:\android-ndk-r10d/platforms/android-19/arch-arm/usr/include -LD:\android-ndk-r10d/platforms/android-19/arch-arm/usr/lib -nostdlib -lgcc -Bdynamic -lc -ldl hello.o D:\android-ndk-r10d/platforms/android-19/arch-arm/usr/lib/crtbegin_dynamic.o D:\android-ndk-r10d/platforms/android-19/arch-arm/usr/lib/crtend_android.o -o hello
  6. $ make install
  7. adb push hello /data/local/tmp/
  8. 99 KB/s (6328 bytes in 0.062s)
  9. adb push libnqshield.so /data/local/tmp/
  10. 1249 KB/s (50524 bytes in 0.039s)
  11. adb shell chmod 755 /data/local/tmp/hello
  12. adb shell /data/local/tmp/hello
  13. nq10
  14. (Ljava/lang/String;Ljava/lang/String;I)V
  15. nq11
  16. (Ljava/lang/String;I)V
  17. nq12
  18. (Landroid/content/Context;Ljava/lang/ClassLoader;I)V
  19. nq13
  20. (Ljava/lang/String;I)V
  21. nq14
  22. (Ljava/lang/String;I)V

得到最后的函数对应表:

函数名 参数 本地方法
nq10 (Ljava/lang/String;Ljava/lang/String;I)V b9df1ce797fd03603fd7137afff2957
nq11 (Ljava/lang/String;I)V eb5993d402df42eac47e82555b7ae31
nq12 (Landroid/content/Context;Ljava/lang/ClassLoader;I)V fa3f3a501e8754e88bed48c128ef90
nq13 (Ljava/lang/String;I)V abc020d3ee6fbc05ab1ed6b4da7252d
nq14 (Ljava/lang/String;I)V e300588cc034bcbaa7d61

接下来只需要对其重命名即可。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注