安卓安全领域,封装核心算法入so库是一个很好的机制,比如应用框架层的HAL,以及APP开发中的NDK。
道高一尺魔高一丈,攻防话题亘古持续。今天从共享库so文件破解的JNI_Onload下断技巧入手,讲解一下so的Android加载时机问题:
首先我在studio中建了一个android ndk工程,然后我写了两个java类,比如
MainActivity.java 和 NativeMethodActivity.java
在MainActivity.java中我加入了静态代码块
static{
System.loadLibrary("hello");
}
而NativeMethodActivity.java则没有加这个代码块
分别用IDA做了两个实验
实验1:
adb shell am start -D -n com.itheima.jnihello/com.itheima.jnihello.MainActivity
实验2:
adb shell am start -D -n com.itheima.jnihello/com.itheima.jnihello.NativeMethodActivity
我观察了IDA Outputwindow的显示,在IDA attch上进程后,IDA主动获得了当前系统已经加载的so库,这些so绝大多数集中
在/system/lib目录下,例如
Autoanalysis subsystem has been initialized.
…
: incompatible saved desktop layout has been ignored
…
40B24000: loaded /system/lib/libdvm.so
…
40252000: loaded /system/lib/libstdc++.so
400DA000: loaded /system/lib/libc.so
B0001000: loaded /system/bin/linker
Shortcut for “SetupData” will be disabled.
The initial autoanalysis has been finished.
Caching ‘Modules’… ok
这些不乏系统 安卓Framework应用框架层要用到的so,属于HAL(硬件抽象)的范畴,所以确实已经提前加载好了,而IDA只是获取并 Caching(缓存了)他们。
接下来,在第一种实验情形下,
1. 先ida打开后,去Module List搜索我要的libhello.so是没有的
2. --》Debugger --》 debugger setup ,再次勾选3项,suspend on library load/onload ,然后点击运行,此时Module List搜索libhello.so仍然没有
3. jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8636此时立即进入了linker,这很正确(so加载底层就是用了linker的dlopen等,代码位于/system/bin/linker)
IDA接下来的log就是
5C5C7000: loaded /data/data/com.itheima.jnihello/lib/libhello.so
Caching 'Modules'... ok
5D1D6000: loaded /system/lib/egl/libGLES_android.so
Caching 'Modules'... ok
然后这时候Module List搜索libhello.so已经有了,(这时候就可以对JNI_Onload下断点然后执行了)
在第二种实验情形下,
1. 先ida打开后,去Module List搜索我要的libhello.so是没有的
2. --》Debugger --》 debugger setup ,再次勾选3项,suspend on library load/onload ,然后点击运行,此时Module List搜索libhello.so仍然没有
3. jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8636此时立即进入了linker,
IDA接下来的log就是
5D1D6000: loaded /system/lib/egl/libGLES_android.so
Caching 'Modules'... ok
然后此时Module List搜索libhello.so仍然没有
这说明一点:
如果APP入口java类中没有声明静态代码块显式加载so库,而且该java类也没有持有其他涉及调用native方法对象的引用,也就是相当于我的NativeMethodActivity。这个时候,启动APP后该so库是得不到加载的
最终我的结论就是:
对于一个so库,APP运行后,除非APP的主入口MainActivity已经System.loadLibrary(“hello”),或者使用了包含System.loadLibrary的类对象,否则so库只会在使用到的时候才会加载。这与系统应用框架层的so库加载不在一个时间段。