iOS開發系列--代碼混淆

因爲iOS系統的封閉性,相對於安卓來講,iOS開發過程當中代碼混淆可能就顯得並非得非有不可了。可是在安全性(可經過class-dump反編譯暴露出類的方法名)和特殊需求上(例如馬甲包的混淆過審)仍是有必定需求的!
此腳本借鑑於kaich/codeobscure。在使用原做者腳本的過程當中,發現了一些BUG和不足,好比正則表達式的判斷不許確,生成過多無用的替換宏,須要花費過多時間去人工排錯...
因爲本人對python並非很熟,因此只是在原做者的基礎上做了一些完善修改。python

優化內容:

  • 修改正則表達式,更精準地找出關鍵詞。
  • 替換規則更改:隨機字符串==>隨機生成2個單詞拼接。防止蘋果審覈過程被誤認加入混淆亂碼。
  • 增長-k選項,經過ignoreKey.txt文件添加須要過濾的關鍵詞,可避免每次生成都要手動刪除部分關鍵詞的麻煩。
  • 增長property關鍵詞、懶加載方法名過濾,減小無用宏的生成。
  • 增長IBAction方法關鍵詞的二次過濾(原腳本存在自定義方法跟IBAction方法重名,沒法排除的狀況)。

如下內容大部分來源於kaich/codeobscure

實現原理

其實插件的實現方式十分簡單,提取用戶編寫的文件中的方法名,使用宏定義將其更換爲任意的無規則字符串。但這種方式有一些須要注意的點:git

  1. 對於系統庫產生的方法名,不可替換;對於系統使用到的關鍵字,也不能夠替換;不然會報錯;
  2. Swift混編的項目,Swift中的代碼不可替換;同時Swift調用Objective-C的特定方法名也不能夠輕易替換;
  3. 第三方庫暴露的頭文件的方法名,不可替換;

根據上面的規則(可能有遺漏),該腳本採用了相對簡單的方法來避免:github

  1. 只掃描.h和.m文件,只掃描方法名。(對於屬性名,嘗試過掃描,但因爲屬性的訪問方式多樣,並不建議作混淆,會產生額外的工做量);
  2. 對於系統庫,讓用戶手動指定,這個是能夠提取的,直接拿到系統庫的頭文件便可,腳本會自動掃描到全部的系統關鍵字,直接作排除處理。(以iOS11的SDK爲例,系統關鍵字約6萬個);
  3. 對於Swift代碼,能夠直接排除在掃描目錄外;
  4. 對於第三方庫,用戶能夠手動指定目錄,腳本會自動掃描提取關鍵字,在混淆時避免這些關鍵字。

依據上述原理,基本能夠避免多數狀況下產生的混淆錯誤;固然,因爲各類項目的複雜性,有一些複雜的混淆錯誤沒法避免,須要後續手動調整代碼。正則表達式

使用方式

  1. clone本倉庫;
  2. 你須要安裝python3的運行環境,這個可使用brew進行安裝,這裏再也不贅述。
  3. 你首先須要肯定如下幾項:
  • 提取一份你當前項目編譯環境的SDK庫頭文件目錄;(Demo中提取了iOS11的SDK頭文件目錄)
  • 你須要混淆的代碼的目錄;
  • 你不須要混淆的代碼的目錄;
  • 你須要提取關鍵字作排除混淆的目錄;(例如Pod倉庫、第三方頭文件)
  • Swift代碼目錄;(理論上不會掃描替換,能夠用於排除橋接文件)
  • 輸出文件目錄;腳本運行後會產生多個log文件,以及最終須要使用到的混淆頭文件;
注:建議目錄使用絕對路徑,相對路徑容易出問題。
  1. 肯定以上幾項後,找到倉庫根目錄的Confuse.py文件,使用如下命令行模板運行:
python3 Confuse.py \
-i 你須要混淆的代碼的目錄,能夠是多個目錄,以`,`分隔 \
-s 當前項目編譯環境的SDK庫頭文件目錄,能夠是多個目錄,以`,`分隔 \
-e 你不須要混淆的代碼的目錄,Swift代碼目錄,能夠是多個目錄,以`,`分隔 \
-c 你須要提取關鍵字作排除混淆的目錄,能夠是多個目錄,以`,`分隔 \
-k 可選,用於存放須要過濾的key(增長內容)
-o 輸出文件目錄
注:各參數的意義以下:
  • -i(input_dirs):必須,項目須要處理的主要文件所在的目錄
  • -s(system_dirs):可選,配置系統Framework文件的目錄,通常用於作排除字典,避免替換系統關鍵字
  • -e(exclusive_dirs):可選,用於存放不掃描處理的文件的目錄,好比Swift文件目錄
  • -c(clean_dirs):可選,用於存放排除關鍵字的文件的目錄,例如Pods下的目錄,或者靜態庫(頭文件修改後會出錯)
  • -k(ignore_key_dir):可選,用於存放須要過濾的key(增長內容)
  • -o(output_dir):必須,輸出文件的目錄,用於輸出關鍵字、日誌以及最後生成的混淆頭文件的目錄
  1. 運行後會在你指定的輸出目錄下產生一份Confuse.h文件,內容通常以下:
#ifndef NEED_CONFUSE_h
#define NEED_CONFUSE_h
// 生成時間: 2018-04-03 17:20:51
#define Function1 linotypistStonecrop
#define function1 exactingnessMimologist
#define function2 sheepmanSupersublimated
#define functionWithTitle kensititeCratinean
#define subTitle icelandicUntell
#endif

這份文件包含了一堆的宏定義,將須要替換的方法名都替換爲了一些隨機的字符串,由於宏定義是全局替換,咱們只須要將該文件引入到本身的項目中,並在PCH文件中進行引入便可。objective-c

引入該文件後,Command+B測試編譯,若是沒法避免而產生編譯錯誤則須要手動調整;因爲將全部的替換歸集到了頭文件中了,因此遇到有錯誤的地方嘗試刪除對應宏定義替換信息從新編輯便可。shell

另外附上一個系統系統庫路徑:安全

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks

圖文教程

瞭解完原理,接下來用圖文來詳細介紹使用方法:
首先去個人Github上獲取下源代碼資源文件。app

注:關鍵文件以下:

  • Confuse.h最終生成的替換文件就是這個了,該文件裏記錄了全部須要混淆的方法名和與之對應的替換字符串
  • Confuse.py該文件是腳本內容所在,全部實現方法都在這。
  • ignoreKey.txt該文件下記錄須要過濾的特殊key,每一個key換行讀取
  • start.sh開始執行腳本 ,在此腳本內更改路徑

如今開始集成:

首先須要一個pch文件,至於pch的用法自行百度吧.。iphone

#ifndef TMPrefixHeader_pch
#define TMPrefixHeader_pch
//代碼混淆關鍵導入文件頭,註釋後不混淆
#import "Confuse.h"
#endif /* TMPrefixHeader_pch */

根據自行需求添加特殊keyignoreKey.txt文件內
測試

經過start.sh腳本快速執行

終端執行內容大概以下:

生成的混淆文件:

編譯結果:對無參數、無返回值、多參數等方法名完成識別替換。

接下來咱們用class-dump來反編譯一下:

class-dump -H /Users/wuaming/Library/Developer/Xcode/DerivedData/TMConfuse-becmpkjuhzbzfldtqwaiznqcmmxq/Build/Products/Debug-iphonesimulator/TMConfuse.app -o /Users/wuaming/Desktop/heads

對比結果:

附上我的Github:https://github.com/TMWu/TMCon...

簡書:https://www.jianshu.com/p/c90...

最後仍是要感謝下幾位大佬!
相關連接:
Objective-C Class-dump 安裝和使用方法(原創)
iOS安全攻防(二十三):Objective-C代碼混淆
感謝原做者的Github

相關文章
相關標籤/搜索