概述
SwiftShield是一個為iOS項目對象(包括你的Pod和Storyboard)生成不可逆加密名稱的工具,以保護你的應(yīng)用程序免受逆向設(shè)計iOS應(yīng)用程序的工具,如class-dump和Cycript
func cxncjnx8fh83FDJSDd(){
return vPAOSNdcbif372hFKF()
}
}
自動模式(僅限Swift)
使用該-automatic標記,SwiftShield將使用SourceKit自動模糊整個項目(包括依賴項)。請注意,SwiftShield的自動模式的范圍與Xcode的本機重構(gòu)工具的范圍直接相關(guān),后者不會重構(gòu)所有內(nèi)容。雖然文檔中的特定案例不會被混淆,但SwiftShield將對所有可以進行逆向工程的Swift類和方法進行模糊處理
SourceKit Bugs
- is模式:如果左側(cè)元素是可選(if [].first is Foo),F(xiàn)oo將不會被混淆。所以,左側(cè)的對象必須是非可選的
Bfore
if annotation is MAUserLocation {}
之前annotation是可選類型,MAUserLocation不會被混淆,但是MAUserLocation類又被混淆,所以導(dǎo)致MAUserLocation找不到,也會報錯
After
guard let annotation = annotation else { return }
/// 當前定位
if annotation is MAUserLocation {}
- 枚舉名稱:在模式匹配中明確使用枚舉類型可防止其被編入索引(if case MyClass.MyEnum.myCase {}- myCase將被編入索引,但MyClass不會。)
- 包含類型的舊版KeyPath,例如#keyPath(Foo.bar)不會被編入索引。比如:"\(Foo)",F(xiàn)oo必須是變量,不能是表達式
before
"今天 \(String.timeStampTrans(toDate: double, formatter: "HH:mm") ?? "")"
這樣混淆后會出現(xiàn)問題,比如會把)或 }一起混淆,導(dǎo)致項目不能運行
After
let temp = String.timeStampTrans(toDate: double, formatter: "HH:mm") ?? ""
"今天 \(temp)"
- 帶selector方法的參數(shù)中含有中文,盡量用變量或常量代替
Bfore
let item1 = UIBarButtonItem(title: “取消”, style: .plain, target: self, action: #selector(cancelButtonClick(sender:)))
混淆后會報錯,混淆后會把)}一起混淆進去,導(dǎo)致項目缺少)}報錯
After
let cencelTitle = "取消"
let item1 = UIBarButtonItem(title: cencelTitle, style: .plain, target: self, action: #selector(cancelButtonClick(sender:)))
- 混淆適配-objc protocol,不可以是optional
Bfore
protocol BottomSheetViewDelegate: NSObjectProtocol {
@objc optional func bottomSheet(bottomSheet: BottomSheetView, willDisplay state: BottomSheetState)
}
混淆后會報錯
After
protocol BottomSheetViewDelegate: NSObjectProtocol {
@objc func bottomSheet(bottomSheet: BottomSheetView, willDisplay state: BottomSheetState)
}
不會混淆的類型
- Typealiases和Associated Types:不會被被混淆(-Foo typealias Foo = UIImage | extension Foo {}被忽略并被索引為UIImage)。請注意,這些不能進行逆向工程,因為它們純粹是編輯器,所以不需要采取任何措施!
- 枚舉案例和名稱:雖然它們被正確編入索引,但是某些枚舉CodingKeys并不意味著要更改。一旦確定枚舉是否與內(nèi)部框架相關(guān)的方式實現(xiàn),這將再次激活
- 已合并:名稱小于四個字符的方法:如果在全局范圍內(nèi)聲明操作符,則僅對其進行索引。由于大多數(shù)人使用public static func,他們被索引為常規(guī)方法。為防止運算符被混淆,名稱短于四個字符的方法將不會被混淆
- 屬性:屬性暫停一段時間,因為它們會破壞派生Codable類型。雖然混淆正常,但如果構(gòu)建Codable類型以在后端的json之上工作,則解析將因為不同的屬性名稱而失敗。
- 模塊名稱:尚未實現(xiàn)!
手動模式(Swift / OBJ-C
這里自己參考Github上的介紹,因為我當時項目已成型,改變需要混淆的方法或變量會比較耗時就放棄手動
步驟
- 從此存儲庫下載最新版本,然后單擊此處查看如何設(shè)置SwiftShield。
- 打開終端,cd到下載的Swiftsheild文件夾下(直接把下載的Swiftsheild拖到終端就行)
- sudo chmod -R 777 (下載的swiftsheild文件路徑,再拖一次就行),給swiftsheild運行的權(quán)限,否者會報錯
- chmod -R 774 PATHTOPROJECTFOLDER(項目路徑)
解鎖項目(如果使用CocoaPods)默認情況下,CocoaPods源被鎖定。SwiftShield需要解鎖它們以便能夠混淆您的項目。要解鎖項目,您可以運行 - 修改可能影響SwiftShield的腳本,因為我當時的項目里用到了swiftlint腳本,用來規(guī)范swift項目語法,導(dǎo)致混淆失敗
您所要做的就是將它們包裝在一個"$SWIFTSHIELDED" != "true"條件中。例如,我的SwiftGen腳本:
if [ "$SWIFTSHIELDED" != "true" ]; then
$PODS_ROOT/SwiftGen/bin/swiftgen images --output $SRCROOT/Asset.swift $SRCROOT/Assets.xcassets
fi
- 運行命令
swiftshield -automatic -project-root /app/MyApp -automatic-project-file /app/MyApp/MyApp.xcworkspace -automatic-project-scheme MyApp-AppStore
- -automatic:啟用自動模式。
- -project-root:項目的根目錄。SwiftShield將使用它來搜索您的項目文件。
- automatic-project-file:您的應(yīng)用程序的主要.xcodeproj / .xcworkspace文件路徑。
- -automatic-project-scheme myScheme:從你的建設(shè)的主要方案-automatic-project-file,寫項目名稱就行了
- -ignore-modules:防止某些模塊被混淆,用逗號分隔。如果某個模塊無法正確混淆,請使用此選項。請注意,這應(yīng)該是導(dǎo)入模塊的確切名稱(而不是目標名稱?。?。
例:MyLib,MyAppRichNotifications,MyAppWatch_Extensio,我當時就是忽略所有的Pods里的第三方庫(開源沒必要),以及一些不能混淆的文件,比如與H5定好的交互方法,混淆后會找不到報錯,不用混淆
注意點
如果項目已成型,不知道改哪里,可以先混淆一遍,然后運行會報錯,在一個個去改,我當時項目第一次報了200多個錯誤,看起來很多,很多都是不需要改的,比如,混淆了)}導(dǎo)致一系列報錯,改一個就好了
大概也就改了幾十處地方,工作量不是很大