背景
字符串加密是一個非常傳統的代碼保護方案,在Android的逆向過程中會涉及到Java代碼和CC++代碼,通常在對APP做逆向過程中第一步一般就是反編譯后查看代碼中是否有包含一些可以作為突破口分析的字符串信息。
作為開發者一般應用中的字符串信息都是保存相對敏感的信息,字符串一般信息會保存著如客戶端和服務端通信信息,操作文件相關信息。
(so部分的字符串加密)
(java部分的字符串加密)
由于字符串信息中存儲著很多關鍵的信息,因此在做逆向的過程中從字符串入手可以猜測、分析定位出一些關鍵的加解密算法、關鍵的邏輯結構。因此字符串也是一種提高被靜態逆向分析的一個很重要的門檻。
字符串信息的加密的影響只到靜態的逆向分析這一步,字符串信息信息在實際業務運行過程中必然需要進行對字符串的操作,那這個就涉及到了對加密字符串的解密過程。這個運行態也就是在對app進行利用動態調試分析過程中都是赤裸裸的展現出來。這是時候字符串的加密就顯得蒼白無力了。因此可以通過反調試和字符串加密這兩者的入門的動態和靜態方式結合,稍微提高代碼的安全性。
字符串加密算法基礎
所謂字符串加密技術是指將一個信息(或稱明文)經過加密鑰匙及加密函數轉換,變成無意義的密文,而接收方則將此密文經過解密函數、解密鑰匙還原成原字符串。
字符串加密免不了采用加解密的算法,加解密算法的加解密方式和加解密強度直接決定了被攻破的時間成本。
字符串加密算法有簡單的異或方式;通用的AES、DES、RSA、Base64、MD5散列函數等等;相對有難度的自實現加解密算法、冷門的加解密算法。
不過一般情況下,作為開發者一般不太可能自己去造輪子寫加解密算法,一般都是直接就套用網絡上穩定的、標準的加解密算法。其實如果從相對安全性來說,可以找那些冷門的加解密算法用于保護字符串。這樣相對網絡公開資料比較少,并且分析的人相對比較少,分析起來時間成本就相對比較高。
下面就分析下so文件加密用的比較多的字符串加密是怎么實現的。
ollvm字符串加密原理
Ollvm中字符串加密的公開版本有很多個版本,并且每個版本功能實現雖然大同小異,但是各個版本也各有缺點。
這些缺點有:
1.無法加密字符串數組;
2.無法加密unicode編碼和非const的字符串數組;
3.無法加密全局char和wchar字符串常量和結構體變量。
基于以上原因,實現自己定制修改字符串加密功能代碼就顯得很重要了。
下面就分析下ollvm中基于某版本字符串加密的實現和調用
Ollvm項目中,字符串加密實現主要功能在項目存儲在如下的路徑中
聲明和實現的代碼
ollvmincludellvmTransformsObfuscationStringObfuscation.h
ollvmlibTransformsObfuscationStringObfuscation.cpp
初始化隨機數因子和調用字符串加密
ollvmlibTransformsIPOPassManagerBuilder.cpp
添加編譯StringObfuscation.cpp文件
ollvmlibTransformsObfuscationCMakeLists.txt
CMakeLists.txt配置要編譯的StringObfuscation.cpp文件
下面的聲明的靜態全局變量,主要是為了實現編譯時候識別 -mllvm -sobf指令的標識,全局開關通過參數來判斷是否要開啟字符串加密。
隨機數因子的初始化。
在populateModulePassManager 函數中,新增掛載新的pass代碼,這樣就可以根據全局開關來判斷是否啟用當前pass。
StringObfuscation.h文件分析
這個函數就聲明了createStringObfuscation函數,看起來非常簡單,這個函數也就是這個字符串加密的關鍵函數。
StringObfuscation.cpp文件分析(基于Armariris版本的字符串加密)
這個版本的加密效果:可加密所有類型的ANSI, UNICODE字符串常量, 但是無法加密字符串數組, 因為字符串數組的全局符號名不是.str開頭。
這個文件中主要有字符串加密函數和字符串解密函數2個函數組成的。
上文截圖代碼根據.str和.str.名稱判斷是否為字符串,并且過濾掉特定區段:Llvm.metadata,__objec_methname不進行字符串加密。
上面截圖中的代碼,可以看到字符串加密的就是進行簡單的字符串異或加密。
用于往字符串加密的程序插入以“.datadiv_decode+隨機數”為結構的加密函數,用于實現對字符串進行加密處理。
防止破解者能夠快速識別是基于ollvm實現的字符串加密,可以重點修改下這個函數的實現和“.datadiv_decode+隨機數”的特征。
有了以上的關鍵調用和流程,那么就可以基于以上的流程和規則進行做字符串加密功能的定制實現了,可以通過添加一些邏輯代碼加強字符串加密的強度。
ollvm字符串加密后表現
1.直接用標準的ollvm的字符串加密,在字符串信息和導出函數中和init_arrayq區段會存在.datadiv_decode,這種采用的是一個字節和一個字節進行隨機異或的加密方式。
數據都存儲在數據段中,程序運行前就是初始化的時候就將加密的字符串全部解密出來,等待著使用。
2.通過基于ollvm的源代碼,簡單修改定制olllvm的源碼,將解密函數名字修改成為非標準的,但是這種的字符串加密在init_array區段中依然會有展示,只不過展示的是非標準的函數信息。這種加密也是通過疑惑的方式進行加密。
字符串數據都存儲在數據段中,程序運行起來后就是初始化時候,就一次性全部將字符串解密。
3.通過基于ollvm的源代碼進行定制,字符串信息都存儲在.bss區段中,程序運行初始化的時候并沒有進行做解密,只有在程序運行使用到那里才會解密到那里。其它的沒使用的字符串是沒有進行解密的。
小結
從字符串成為破解者第一道門檻的的痛點,在到字符串加密僅是為了提高破解者靜態分析的成本的大背景下進行,全文大篇幅的主要是以ollvm這個項目中的字符串加密為主線進行展開的,展開的方向主要以加密的實現原理和加密后的表現形式。
對ollvm字符串的解密相信是對大家來說比字符串加密是更感興趣,篇幅有限先以字符串加密進行簡單做下原理性的分析,后面再分享ollvm字符串解密。
審核編輯:湯梓紅
-
Android
+關注
關注
12文章
3935瀏覽量
127352 -
JAVA
+關注
關注
19文章
2966瀏覽量
104707 -
字符串
+關注
關注
1文章
578瀏覽量
20508
原文標題:ollvm|Android字符串加密淺析
文章出處:【微信號:哆啦安全,微信公眾號:哆啦安全】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論