我目前正在对一个Android应用程序进行反向工程,该应用程序通过Java本机接口在ARM 32位ELF库(名为“ libcms.so”(来自TikTok))中调用了名为“ getUserInfo”的函数。 :无法使用readelf --syms libcms.soreadelf --dyn-syms libcms.so找到该函数,因为libcms.so被剥离并且该功能未包含在符号表中。如何找到函数的十六进制位置?

#1 楼

可以使用两种广泛的方法来声明JNI函数。

第一个是更明显的方法,其中JNI函数必须遵循特定的命名约定,例如JNIEXPORT void JNICALL Java_com_app_foo_bar。您可以使用readelf轻松识别此类功能。

另一种不太明显的方法是使用RegisterNatives。在这里,您的函数可以具有任何签名,并且进一步,它们不需要从共享库中导出。通常,您可以从RegisterNatives调用JNI_OnLoad将本机函数注册到Java运行时。

对于二进制libcms.so,它使用第二种方法。以下原型

jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint Methods);


如果分析RegisterNatives的代码,则会遇到类似下面的JNI_OnLoad调用。 />第三个参数指向一个声明为

typedef struct {
    char *name; 
    char *signature;
    void *fnPtr;
} JNINativeMethod;


RegisterNatives结构数组。但是,对于您而言,所有名称和签名都是加密的。

JNINativeMethod部分包含指向这些解密器功能的指针,这意味着它们将在启动时被调用。



但是,还不是全部。二进制文件在整个过程中还采用了“控制流扁平化”混淆,因此执行路径可能不容易看出,如下所示。使用诸如Frida之类的工具进行动态分析技术。

进一步阅读:


https://developer.android.com/training/articles/perf- jni#native-libraries
在JNI_OnLoad的汇编代码中查找RegisterNatives函数调用
https://stackoverflow.com/questions/13509961/which-method-eventually-calls-jni-onload
https://stackoverflow.com/questions/51811348/find-manually-registered-obfuscated-native-function-address
https://stackoverflow.com/questions/1010645/what-does-the-registernatives-method -do
如何恢复存储在.ctors节中的信息?


评论


我不明白,是否可以动态加载它以获得该功能?还是我错过了重点?

–杜松子酒
19-10-10在4:16

@GinMay若要解密函数名称,您可以运行/模拟.datadiv_decode系列函数。

– 0xec
19-10-13在7:51