如何提升代码的安全性 —— 代码混淆
目錄
- 一、背景
- 1.1 Android應用安全存在多重隱患
- 二、代碼混淆
- 2.1 代碼混淆的原理
- 2.2 代碼混淆的方法
- 2.3 常見的代碼混淆方式
- 三、 C/C++ 代碼混淆
- 3.1 Obfuscator-LLVM實現C/C++混淆
- 3.1.1 常見的混淆方法
- 3.1.2其他常見的C/C++混淆手段:
- 四、代碼混淆可能帶來的問題
一、背景
1.1 Android應用安全存在多重隱患
-
代碼可逆向:客戶端App的邏輯能夠被輕易獲取和逆向,得到代碼和程序中的敏感數據;
-
功能泄漏:客戶端App中高權限行為和功能被其他未授權的應用程序調用訪問;
-
可調試:客戶端App能夠被調試,動態地提取、修改運行時的程序數據和邏輯;
-
日志信息泄漏:客戶端App將開發時輔助調試信息打印泄露,包含敏感參數等信息;
-
可二次打包:客戶端App可能被修改代碼,重新打包發布在市場上供用戶下載;
-
密碼學誤用:客戶端App代碼中使用了不安全的密碼學實現,例如固定硬編碼的對稱加密,ECB模式的對稱加密,CBC模式中IV固定等;
-
敏感信息泄漏:客戶端App代碼中泄漏敏感數據,如認證使用的共享密鑰、不應被暴露的后臺服務器管理地址等;
-
通信數據明文傳輸:客戶端App與服務器端交互的數據通過明文的通信信道傳輸,或者加密傳輸,但數據依然可以被解密;
移動應用代碼安全非常重要,代碼逆向會導致代碼邏輯被獲取,進一步導致控制流被hook,安全防線被破,給APP安全帶來巨大風險,因此開發者一般都會進行代碼混淆保護。本文主要介紹了代碼混淆的原理、方法、以及常見代碼混淆的方式和工具。
二、代碼混淆
2.1 代碼混淆的原理
代碼混淆是將計算機程序的代碼,轉換成功能上等價,但是難于閱讀和理解形式的行為?;煜褪菍Πl布出去的程序進行重新組織和處理,使得處理后的代碼與處理前代碼完成相同的功能,而混淆后的代碼很難被反編譯,即使反編譯成功也很難得出程序的真正語義,通過進行代碼混淆可以有效提升應用被逆向破解的難度。
2.2 代碼混淆的方法
字符串加密:對應用程序中使用到的字符串進行加密,防止通過IDA等工具獲取關鍵詞定位核心業務代碼;
類名、方法名混淆:將代碼中類名、方法名、屬性名替換為無意義符號,增加代碼逆向難度;將有意義的類,字段、方法名稱更改為無意義的字符串。生成的新名稱越短,字節代碼越小。在名稱混淆的字節代碼中,包,類,字段和方法名稱已重命名,并且永遠不能恢復原始名稱。不過這種方法混淆后,控制流程仍然清晰可見
程序結構混淆加密:對應用程序邏輯結構進行打亂混排,保證源碼可讀性降到最低。用于if, switch, while,for等關鍵字,對字節碼進行細微的修改,模糊控制流,而不改變代碼在運行時的行為。通常情況下,選擇和循環等邏輯構造會被更改。流模糊的字節碼通常強制反編譯器將一系列標簽和非法的goto語句插入到它們生成的源代碼中。源代碼有時會因為反編譯錯誤而變得更加模糊。
2.3 常見的代碼混淆方式
常見的代碼混淆方式包括Java代碼混淆、C/C++代碼混淆以及h5 腳本混淆等。
三、 C/C++ 代碼混淆
下圖為C++代碼的混淆,保護之后控制流大幅度偽造,逆向難度非常高。當然控制流偽造也會影響運營效率,所以一般也只是對核心的一些功能做保護。
混淆的過程中添加的一些字串的保護如下圖:
介紹一個c/c++代碼混淆工具,逆向對抗利器—LLVM。LLVM不僅僅提供混淆實現,通過多重Optimize(優化器),實現多種效果,例如代碼控制流扁平化、虛假控制流、字符串加密、符號混淆、指令替換等。
代碼混淆是將計算機程序的代碼,轉換成功能上等價,但是難于閱讀和理解形式的行為。代碼混淆可以有效提升反編譯的難度。
3.1 Obfuscator-LLVM實現C/C++混淆
3.1.1 常見的混淆方法
利用Obfuscator-LLVM工具實現C/C++混淆方法:
-
控制流平坦化:在不改變源代碼功能的前提下,將C、C++等語言中的if、while、for、do等控制語句轉化為switch分支選擇語句??刂屏髌教够悬c像虛擬機保護,case塊相當于vm的handle,case值相當于vm的opcode。
-
指令替換:生成條件跳轉指令有兩種方法,一種稱為opaque predicate,另一種稱為bogus control flow。
假設基本塊 偽代碼如下:
block0;opaque predicate指令替換后:
/* opaque predicate 指令替換 */ if (恒等式) {block0; } else {垃圾代碼 } /* 或者另一種方式 */ if (恒不等式) {垃圾代碼 } else {block0; }bogus control flow指令替換后:
if (隨機條件) {block0; } else {block1; /* 基本塊block1復制于block0 */ }- 控制流偽造
3.1.2其他常見的C/C++混淆手段:
-
多重分支
-
基本塊分割:把基本塊分成多個基本塊。有兩種方法:一種是根據概率對基本塊的當前指令進行分割;另一種是計算基本塊的總指令數,標記為a,隨機生成小于a的數,標記為b,基本塊b條指令后進行分割,a減掉b,進行多次迭代直至a等于1。
-
字符串加密
-
常量隱藏
-
常量展開
-
常量數組隨機化:讓常量在數組中的索引隨機化。假設常量數組a[],索引值i,隨機生成索引數組b[]、c[]、d[](可生成更多),循環用z[b[c[d[i]]]] = a[i]生成隨機后的常量數組z[],然后用z[b[c[d[i]]]]替換a[i]。
-
表達式變換:對邏輯操作not、and、or、xor,可以先把操作數抽取分成多個更小的數進行操作,最后用or連接起來,當然這四個操作可以用與非門或是或非門來完成。還有其它常見的運算可以把操作數看成大數然后進行大數運算,還有一些運算可以轉變為SIMD指令進行運算。至于浮點數,有很多浮點數的軟件實現可供參考。
四、代碼混淆可能帶來的問題
被混淆的代碼難于理解,因此調試以及除錯也變得困難起來。開發人員通常需要保留原始的未混淆的代碼用于調試。對于支持反射的語言,代碼混淆有可能與反射發生沖突。代碼混淆并不能真正阻止反向工程,只能增大其難度。因此,對于對安全性要求很高的場合,僅僅使用代碼混淆并不能保證源代碼的安全。
總結
以上是生活随笔為你收集整理的如何提升代码的安全性 —— 代码混淆的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Confluence 6 手动备份站点
- 下一篇: 网管第一课——网络组建与管理 目录