来自反编译器的函数声明的差异?

逆向工程 艾达 拆卸 C 安卓 爪哇
2021-06-16 12:58:40

我正在分析的 Android 应用程序调用本机库以生成特定值。这是来自 SMALI(反编译 Java)的本地库函数声明的示例:

.method private native createAlgorithmSolver(II)J
.end method

.method private native solveAlgorithm(Ljava/lang/String;IJ)[I
.end method

这是有道理的。createAlgorithmSolver 接受两个整数,并返回一个长整数。solveAlgorithm 接受 32 个字符的字符串,例如“SM1r0WeJH6qxdfNua2zg7t8ITwQUZYn5”,它接受一个 int 和一个 long,并返回一个 int 数组。

当我用 IDA Hex-rays 反编译器反编译实际的“.so”文件时,我得到这个:

createAlgorithmSolver(int a1, int a2, unsigned int a3, int a4)
solveAlgorithm(int a1, int a2, int a3, unsigned int a4, signed int a5)

当我将“Retargetable Decompiler”(https://retdec.com)与 Python 伪代码一起使用时,我得到以下函数声明:

def createAlgorithmSolver(a1, a2):
def solveAlgorithm(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17):

是什么导致了这些奇怪的差异?

1个回答

JNI 方法采用 JNIEnv* 类型的额外参数,它是指向函数指针表的指针。这就是 JNI 方法可以调用 JVM 的方式,这是执行任何重要操作所必需的。

所以这说明了您列出的函数的第一个 int 参数。

此外,这些函数是非静态的,因此它们显然采用隐藏this参数。这说明了第二个论点。之后是方法的源级参数。在第一种情况下,它只是两个整数。在第二种情况下,它是一个 String 对象(即一个 jstring 指针)、一个 int 和一个 long。

但是,反编译器不够聪明,无法猜测参数的实际类型是什么——它只是查看在寄存器和堆栈中传递了多少值。因此,所有指针都显示为整数,而 long 显示为一对整数。