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

作者: 我是吸血鬼 | 来源:发表于2018-07-01 16:07 被阅读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++字符串混淆方案总结

    相关文章

      网友评论

        本文标题:Android SO(动态库)---安全防护

        本文链接:https://www.haomeiwen.com/subject/qzrfsftx.html