此本机代码是否可以进行进一步的静态分析?
Is this native code possible for further static analysis?
我试图在 android 应用程序中对本机库代码进行逆向工程。 .so
包含许多功能。但是 Java 代码中引用了函数 sUQWWyTBEs()
。我很好奇这个功能是如何工作的。
这个函数 returns 一个像这样的字符串 47fjlkj843h9asjklj94kljfsad93j4l2715943hasd...
但我想要的是这个值是如何生成或返回的。
用Ghidra
反编译函数sUQWWyTBEs()
的代码:
*************************************************************
* FUNCTION
*************************************************************
undefined __cdecl Myapp_sUQWWyTBEs()
undefined w0:1 <RETURN>
longlong * x0:8 param_1
Myapp_sUQWWyTBEs XREF[2]: Entry Point (*) , 00101350
00100e44 08 00 40 f9 ldr x8, [param_1 ]
00100e48 01 00 00 b0 adrp x1, s_c7a584936712f32773d3d0a_00101000 ; = "c7a584936712f32773d3d0a"
00100e4c 21 60 08 91 add x1, x1, #0x218
00100e50 02 9d 42 f9 ldr x2, [x8, #0x538 ]
00100e54 40 00 1f d6 br x2
根据我的理解,我做了如下静态分析:
00100e44 08 00 40 f9 ldr x8, [param_1 ]
将内存地址 param_1 处的值加载到寄存器 x8。
0100e48 01 00 00 b0 adrp x1, s_c7a584936712f32773d3d0a_00101000
将寄存器 x1 设置为 0x101000。
00100e4c 21 60 08 91 add x1, x1, #0x218
将 0x218 添加到 x1,因此将 x1 设置为 0x101218。
00100e50 02 9d 42 f9 ldr x2, [x8, #0x538 ]
将 x8 + 0x538 处的值加载到 x2。
00100e54 40 00 1f d6 br x2
最后分支到x2
中存储的地址。
话虽这么说,这里我不知道地址为 x2
的内存,显然它最初取决于 param_1
持有的值。有什么办法或者我怎样才能参考 param_1
的初始化位置?我不太了解 Ghidra
或其他逆向工程工具的用法。任何人都可能提供帮助,我们将不胜感激。
假设此函数在 Java 端声明为 native
函数,param_1
是 JNIEnv*
。 Android JNI documentation states:
JNI defines two key data structures, "JavaVM" and "JNIEnv". Both of these are essentially pointers to pointers to function tables.
因此,您显示的代码基本上是在偏移量 0x538 处调用函数 table 中的函数。假设你正在展示一个 64 位 Android 程序,函数指针是 8 个字节,所以你需要找出第 167 个函数指针(从 0 开始)。
获取 jni.h
的副本并提取 struct JNINativeInterface
的成员,从 0 开始编号:
0: void* reserved0;
1: void* reserved1;
2: void* reserved2;
3: void* reserved3;
4: jint (*GetVersion)(JNIEnv *);
...
167: jstring (*NewStringUTF)(JNIEnv*, const char*);
因此,假设我没有犯任何错误,您显示的代码调用 env->NewStringUTF
并使用 s_c7a584936712f32773d3d0a_00101000+0x218
作为参数。
我认为您可以让 Ghidra 解析 jni.h 以使这些类型可用。如果您随后更改 param_1
的类型,这可能足以让 Ghidra 为您执行此映射并生成对 C/C++.
的合理反编译。
我试图在 android 应用程序中对本机库代码进行逆向工程。 .so
包含许多功能。但是 Java 代码中引用了函数 sUQWWyTBEs()
。我很好奇这个功能是如何工作的。
这个函数 returns 一个像这样的字符串 47fjlkj843h9asjklj94kljfsad93j4l2715943hasd...
但我想要的是这个值是如何生成或返回的。
用Ghidra
反编译函数sUQWWyTBEs()
的代码:
*************************************************************
* FUNCTION
*************************************************************
undefined __cdecl Myapp_sUQWWyTBEs()
undefined w0:1 <RETURN>
longlong * x0:8 param_1
Myapp_sUQWWyTBEs XREF[2]: Entry Point (*) , 00101350
00100e44 08 00 40 f9 ldr x8, [param_1 ]
00100e48 01 00 00 b0 adrp x1, s_c7a584936712f32773d3d0a_00101000 ; = "c7a584936712f32773d3d0a"
00100e4c 21 60 08 91 add x1, x1, #0x218
00100e50 02 9d 42 f9 ldr x2, [x8, #0x538 ]
00100e54 40 00 1f d6 br x2
根据我的理解,我做了如下静态分析:
00100e44 08 00 40 f9 ldr x8, [param_1 ]
将内存地址 param_1 处的值加载到寄存器 x8。
0100e48 01 00 00 b0 adrp x1, s_c7a584936712f32773d3d0a_00101000
将寄存器 x1 设置为 0x101000。
00100e4c 21 60 08 91 add x1, x1, #0x218
将 0x218 添加到 x1,因此将 x1 设置为 0x101218。
00100e50 02 9d 42 f9 ldr x2, [x8, #0x538 ]
将 x8 + 0x538 处的值加载到 x2。
00100e54 40 00 1f d6 br x2
最后分支到x2
中存储的地址。
话虽这么说,这里我不知道地址为 x2
的内存,显然它最初取决于 param_1
持有的值。有什么办法或者我怎样才能参考 param_1
的初始化位置?我不太了解 Ghidra
或其他逆向工程工具的用法。任何人都可能提供帮助,我们将不胜感激。
假设此函数在 Java 端声明为 native
函数,param_1
是 JNIEnv*
。 Android JNI documentation states:
JNI defines two key data structures, "JavaVM" and "JNIEnv". Both of these are essentially pointers to pointers to function tables.
因此,您显示的代码基本上是在偏移量 0x538 处调用函数 table 中的函数。假设你正在展示一个 64 位 Android 程序,函数指针是 8 个字节,所以你需要找出第 167 个函数指针(从 0 开始)。
获取 jni.h
的副本并提取 struct JNINativeInterface
的成员,从 0 开始编号:
0: void* reserved0;
1: void* reserved1;
2: void* reserved2;
3: void* reserved3;
4: jint (*GetVersion)(JNIEnv *);
...
167: jstring (*NewStringUTF)(JNIEnv*, const char*);
因此,假设我没有犯任何错误,您显示的代码调用 env->NewStringUTF
并使用 s_c7a584936712f32773d3d0a_00101000+0x218
作为参数。
我认为您可以让 Ghidra 解析 jni.h 以使这些类型可用。如果您随后更改 param_1
的类型,这可能足以让 Ghidra 为您执行此映射并生成对 C/C++.