在日常的APP開發(fā)過程中我們都會遇到安全相關(guān)的問題,針對不同的安全需求會有不同的解決方案除破。那么我們今天來看看與Android動態(tài)庫相關(guān)的安全問題。
今天我們以AndroidSO工程為基礎(chǔ),通過實際的例子來解決一些常見的安全需求固灵。
動態(tài)庫被第三方APP非法使用
我們辛辛苦苦開發(fā)了一個動態(tài)庫缅帘,最終卻被非授權(quán)的第三方APP用了轴术,那么不是很尷尬嘛。
那么如何防止我們的動態(tài)庫被第三方非法使用呢股毫?客官往下看~
非授權(quán)使用的問題本質(zhì)上是因為我們的動態(tài)庫沒有做驗簽功能膳音,接下來就帶大家實現(xiàn)對SO調(diào)用的簽名驗證功能。
敏感字符串信息可見
native-lib-static.cpp的JNI函數(shù)代碼如下铃诬。
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
后截圖的信息祭陷。
我們可以很容易看到字符串的信息。與我們代碼中的字符串一模一樣趣席,很完整被解析出來兵志。
是不是突然感覺很沒有安全感,這么隨意宣肚。想罕。。
我們這個字符串沒有什么價值霉涨,但是如果我們存放了敏感的字符串信息又如何是好呢按价?
簡單的解決辦法有如下兩種:
001 定義char數(shù)組
字符串信息以數(shù)組的方式初始化,比如以下寫法:
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
最終輸出內(nèi)容如下:
((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'});
注意這種寫法只能用在函數(shù)內(nèi)部
002 敏感字符串信息加密
加密分為對稱加密和非對稱加密框产,常見的對稱加密包括DES
凄杯、AES
等,非對稱加密包括RSA
秉宿、背包算法
等戒突。
非對稱加密的缺點是加密和解密花費時間長、速度慢描睦,只適合對少量數(shù)據(jù)進行加密膊存。
對稱加密算法的優(yōu)點是算法公開、計算量小忱叭、加密速度快膝舅、加密效率高。
在項目針對可以采用DES
進行對稱加密即可窑多。
JNI函數(shù)信息可見
每一個動態(tài)庫都會包含符號表信息仍稀,通過objdump工具在命令行中可以查看到動態(tài)庫最終包含的符號表。
采用靜態(tài)方式注冊JNI函數(shù)會最終會包含在符號表中埂息,那么我們就可以從符號表中看到以Java_
開頭的所有JNI函數(shù)技潘。那么別人就會通過JNI函數(shù)來最終分析APK中相應(yīng)Class
對應(yīng)的動態(tài)庫文件,進而分析整個APK以及動態(tài)庫的調(diào)用邏輯千康。
針對AndroidSO工程中的static-dynamic-so工程享幽,我們可以分別設(shè)置CMakeLists.txt中DYNAMIC_FLAG
的取值。
DYNAMIC_FLAG
是一個布爾值拾弃,為true的時候動態(tài)庫最終包含native-lib-dynamic.cpp,相反包含native-lib-static.cpp值桩。
native-lib-dynamic.cpp采用動態(tài)注冊JNI的方式,而native-lib-static.cpp采用靜態(tài)注冊JNI的方式豪椿。
執(zhí)行objdump -D libnative-lib.so | grep Java_*
可以查看以Java_
開頭的符號表信息奔坟。
native-lib-static.cpp靜態(tài)注冊輸出結(jié)果如下:
4118: 52 00 00 ea b #328 <Java_com_demon_so_MainActivity_stringFromJNI+0x28>
native-lib-dynamic.cpp動態(tài)注冊JNI函數(shù)輸出結(jié)果如下:
_ZN7_JavaVM6GetEnvEPPvi:
對比上邊的輸出結(jié)果我們可以很容易看出動態(tài)注冊的JNI函數(shù)就無法看到我們定義的JNI函數(shù)了。
采用動態(tài)注冊的方式即可解決JNI函數(shù)可見的問題搭盾。
objdump的用法點擊直達
Reference: