Android开发Android技术知识Android开发

Android SO(动态库)---安全防护

2018-07-01  本文已影响80人  我是吸血鬼

在日常的APP开发过程中我们都会遇到安全相关的问题,针对不同的安全需求会有不同的解决方案。那么我们今天来看看与Android动态库相关的安全问题。

今天我们以AndroidSO工程为基础,通过实际的例子来解决一些常见的安全需求。

动态库被第三方APP非法使用

我们辛辛苦苦开发了一个动态库,最终却被非授权的第三方APP用了,那么不是很尴尬嘛。

那么如何防止我们的动态库被第三方非法使用呢?客官往下看~

非授权使用的问题本质上是因为我们的动态库没有做验签功能,接下来就带大家实现对SO调用的签名验证功能。

敏感字符串信息可见

native-lib-static.cpp的JNI函数代码如下。

JNIEXPORT jstring JNICALL
Java_com_demon_so_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from static register jni function";
    return env->NewStringUTF(hello.c_str());
}

上面这个图片是我通过IDA(逆向分析工具)打开static-dynamic-so工程生成的libnative-lib.so后截图的信息。

so_string_visible

我们可以很容易看到字符串的信息。与我们代码中的字符串一模一样,很完整被解析出来。

是不是突然感觉很没有安全感,这么随意。。。

我们这个字符串没有什么价值,但是如果我们存放了敏感的字符串信息又如何是好呢?

简单的解决办法有如下两种:

001 定义char数组

字符串信息以数组的方式初始化,比如以下写法:

JNIEXPORT jstring JNICALL
Java_com_demon_so_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    char* hello = ((char[]){'H','e','l','l','o',' ','f','r','o','m',' ','s','t','a','t','i','c',' ','r','e','g','i','s','t','e','r',' ','j','n','i',' ','f','u','n','c','t','i','o','n'});
    return env->NewStringUTF(hello);
}

看到这么一长串的代码是不是要疯了,我擦,一个完整的字符串居然被凌乱掉了。这么写代码要疯掉了。

办法总是有的嘛......

用一个python脚本就可以解决问题了

content = "Hello from static register jni function"
length = len(content)
str = "((char[]){"
for i in range(length):
    str = str+'\''+content[i]+'\''
    if i !=(length-1):
        str=str+','
str = str+"})"
print str

最终输出内容如下:

((char[]){'H','e','l','l','o',' ','f','r','o','m',' ','s','t','a','t','i','c',' ','r','e','g','i','s','t','e','r',' ','j','n','i',' ','f','u','n','c','t','i','o','n'});

注意这种写法只能用在函数内部

002 敏感字符串信息加密

加密分为对称加密非对称加密,常见的对称加密包括DESAES等,非对称加密包括RSA背包算法等。

非对称加密的缺点是加密和解密花费时间长、速度慢,只适合对少量数据进行加密。

对称加密算法的优点是算法公开、计算量小、加密速度快、加密效率高。

在项目针对可以采用DES进行对称加密即可。

JNI函数信息可见

每一个动态库都会包含符号表信息,通过objdump工具在命令行中可以查看到动态库最终包含的符号表。

采用静态方式注册JNI函数会最终会包含在符号表中,那么我们就可以从符号表中看到以Java_开头的所有JNI函数。那么别人就会通过JNI函数来最终分析APK中相应Class对应的动态库文件,进而分析整个APK以及动态库的调用逻辑。

针对AndroidSO工程中的static-dynamic-so工程,我们可以分别设置CMakeLists.txtDYNAMIC_FLAG的取值。

DYNAMIC_FLAG是一个布尔值,为true的时候动态库最终包含native-lib-dynamic.cpp,相反包含native-lib-static.cpp

native-lib-dynamic.cpp采用动态注册JNI的方式,而native-lib-static.cpp采用静态注册JNI的方式。

执行objdump -D libnative-lib.so | grep Java_*
可以查看以Java_开头的符号表信息。

native-lib-static.cpp静态注册输出结果如下:

4118:   52 00 00 ea     b   #328 <Java_com_demon_so_MainActivity_stringFromJNI+0x28>

native-lib-dynamic.cpp动态注册JNI函数输出结果如下:

_ZN7_JavaVM6GetEnvEPPvi:

对比上边的输出结果我们可以很容易看出动态注册的JNI函数就无法看到我们定义的JNI函数了。

采用动态注册的方式即可解决JNI函数可见的问题。

objdump的用法点击直达

Reference:

  1. c/c++字符串混淆方案总结
上一篇 下一篇

猜你喜欢

热点阅读