在剥离的动态 ELF 库中查找函数

逆向工程 安卓 手臂 小精灵 爪哇 符号
2021-06-20 21:14:41

我目前正在对一个 android 应用程序进行逆向工程,该应用程序通过Java Native Interface名为“libcms.so”(来自 TikTok)ARM 32 位 ELF 库中调用名为“getUserInfo”的函数

我的问题是:无法找到该函数,readelf --syms libcms.so或者readelf --dyn-syms libcms.so因为 libcms.so 被剥离并且该函数不包含在符号表中。

该应用程序可以调用此函数,所以我知道该函数在那里。如何找到函数的十六进制位置?

1个回答

有两种广泛的方法可以声明JNI函数。

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

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

对于您的 binary libcms.so,它使用第二种方法。

RegisterNatives 有以下原型

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

如果你分析你的代码,JNI_OnLoad你会遇到RegisterNatives像下面这样的调用。

在此处输入图片说明

第三个参数指向一个JNINativeMethod结构数组,它被声明为

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

第一个成员是指向表示函数名称的空终止字符串的指针。但是,在您的情况下,所有名称和签名都已加密。

在此处输入图片说明 在此处输入图片说明

这些在运行时由.datadiv_decodeXXXXXXXX函数系列解密.init_array部分包含指向这些解密函数的指针,这意味着它们将在启动时被调用。

在此处输入图片说明

然而,这还不是全部。二进制文件还始终采用控制流扁平化混淆,因此执行路径可能不容易识别,如下所示。

在此处输入图片说明

要分析二进制文件,最好使用诸如Frida 之类的工具求助于动态分析技术

进一步阅读: