Android so加载流程分析
使用Frida过应用反调试时,一般都是通过hook android_dlopen_ext来确定反调试代码所在的so文件。
为确定此等方式能够覆盖到全部so文件的加载过程,分析Android so加载流程。
在XRef Android查看AOSP(Android Open Source Project)源码,版本为Android 13。链接:http://xrefandroid.com/
System.load方法在System.java文件中,直接搜索:

(Full Search查找文件,Definition查找方法名)
Android加载so文件主要通过System.loadLibrary(so文件位于apk的lib文件夹下)和System.load(加载任意路径下的so)。
在此,首先分析System.load的函数调用过程:
在System.java文件中查找System.load,可知调用System.load等效于调用Runtime.getRuntime().load0:

在 Runtime.getRuntime().load0 中进行了 filename 是否是绝对路径、空字符串的检查之后,调用 nativeLoad方法加载so:

查看/libcore/ojluni/src/main/native/Runtime.c,可知在native层中将nativeLoad方法动态注册为了Runtime_nativeLoad方法:



Runtime_nativeLoad调用了JVM_NativeLoad方法:

JVM_NativeLoad又调用了JavaVM的LoadNativeLibrary方法:

LoadNativeLibrary方法较复杂,主要逻辑包括三部分:
1.若需要加载的库已被加载,且此次调用传入的加载器(ClassLoader)与原加载器相同,什么也不做,返回,否则报错(java不允许使用不同的加载器加载相同的类);
2.调用OpenNativeLibrary方法加载库;
3.当so被成功加载后,立即调用so的导出函数中的JNI_OnLoad方法(如果其存在)。
查看OpenNtiveLibrary方法,可见条件编译指令,关注#if defined(ART_TARGET_ANDROID)块,因其仅在为Android目标平台编译时才会被包含。即Android设备中执行的是该部分代码。

该部分中先是确定了待加载库的对应的命名空间,再调用android_dlopen_ext(无classloader,即系统基本类库)、TryLoadNativeloaderExtraLib(系统特殊类库,属特殊情况)或OpenNativeLibraryInNamespace(有classloader,应用自行加载的so对应该情况)加载库。
分析OpenNativeLibraryInNamespace方法,其调用了NativeLoaderNamespace类的Load方法。

/art/libnativeloader/native_loader_namespace.h中声明了该方法,其具体实现在/art/libnativeloader/native_loader_namespace.cpp
中,可知,该方法最终依旧调用了android_dlopen_ext:

接下来,分析Systm.loadLibrary:

loadLibrary0方法在其内部进行路径检验和按照不同类型加载器分类后,最终调用nativeLoad方法:

后续代码调用过程见上述System.load部分。
基于上述分析过程,可知,不论使用System.load,亦或是System.loadLibrary,最终均会调用android_dlopen_ext加载so文件。在反调试时hook该方法,能够帮助分析反调试代码所在的so文件。
浙公网安备 33010602011771号