概述
SwiftShield是一个为iOS项目对象(包括你的Pod和Storyboard)生成不可逆加密名称的工具,以保护你的应用程序免受逆向设计iOS应用程序的工具,如class-dump和Cycript
func cxncjnx8fh83FDJSDd(){
return vPAOSNdcbif372hFKF()
}
}
自动模式(仅限Swift)
使用该-automatic
标记,SwiftShield将使用SourceKit自动模糊整个项目(包括依赖项)。请注意,SwiftShield的自动模式的范围与Xcode的本机重构工具的范围直接相关,后者不会重构所有内容。虽然文档中的特定案例不会被混淆,但SwiftShield将对所有可以进行逆向工程的Swift类和方法进行模糊处理
SourceKit Bugs
- is模式:如果左侧元素是可选(if [].first is Foo),Foo将不会被混淆。所以,左侧的对象必须是非可选的
Bfore
if annotation is MAUserLocation {}
之前annotation是可选类型,MAUserLocation不会被混淆,但是MAUserLocation类又被混淆,所以导致MAUserLocation找不到,也会报错
After
guard let annotation = annotation else { return }
/// 当前定位
if annotation is MAUserLocation {}
- 枚举名称:在模式匹配中明确使用枚举类型可防止其被编入索引(if case MyClass.MyEnum.myCase {}- myCase将被编入索引,但MyClass不会。)
- 包含类型的旧版KeyPath,例如#keyPath(Foo.bar)不会被编入索引。比如:"\(Foo)",Foo必须是变量,不能是表达式
before
"今天 \(String.timeStampTrans(toDate: double, formatter: "HH:mm") ?? "")"
这样混淆后会出现问题,比如会把)或 }一起混淆,导致项目不能运行
After
let temp = String.timeStampTrans(toDate: double, formatter: "HH:mm") ?? ""
"今天 \(temp)"
- 带selector方法的参数中含有中文,尽量用变量或常量代替
Bfore
let item1 = UIBarButtonItem(title: “取消”, style: .plain, target: self, action: #selector(cancelButtonClick(sender:)))
混淆后会报错,混淆后会把)}一起混淆进去,导致项目缺少)}报错
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并不意味着要更改。一旦确定枚举是否与内部框架相关的方式实现,这将再次激活
- 已合并:名称小于四个字符的方法:如果在全局范围内声明操作符,则仅对其进行索引。由于大多数人使用public static func,他们被索引为常规方法。为防止运算符被混淆,名称短于四个字符的方法将不会被混淆
- 属性:属性暂停一段时间,因为它们会破坏派生Codable类型。虽然混淆正常,但如果构建Codable类型以在后端的json之上工作,则解析将因为不同的属性名称而失败。
- 模块名称:尚未实现!
手动模式(Swift / OBJ-C
这里自己参考Github上的介绍,因为我当时项目已成型,改变需要混淆的方法或变量会比较耗时就放弃手动
步骤
- 从此存储库下载最新版本,然后单击此处查看如何设置SwiftShield。
- 打开终端,cd到下载的Swiftsheild文件夹下(直接把下载的Swiftsheild拖到终端就行)
- sudo chmod -R 777 (下载的swiftsheild文件路径,再拖一次就行),给swiftsheild运行的权限,否者会报错
- chmod -R 774 PATHTOPROJECTFOLDER(项目路径)
解锁项目(如果使用CocoaPods)默认情况下,CocoaPods源被锁定。SwiftShield需要解锁它们以便能够混淆您的项目。要解锁项目,您可以运行 - 修改可能影响SwiftShield的脚本,因为我当时的项目里用到了swiftlint脚本,用来规范swift项目语法,导致混淆失败
您所要做的就是将它们包装在一个"$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:您的应用程序的主要.xcodeproj / .xcworkspace文件路径。
- -automatic-project-scheme myScheme:从你的建设的主要方案-automatic-project-file,写项目名称就行了
- -ignore-modules:防止某些模块被混淆,用逗号分隔。如果某个模块无法正确混淆,请使用此选项。请注意,这应该是导入模块的确切名称(而不是目标名称!)。
例:MyLib,MyAppRichNotifications,MyAppWatch_Extensio,我当时就是忽略所有的Pods里的第三方库(开源没必要),以及一些不能混淆的文件,比如与H5定好的交互方法,混淆后会找不到报错,不用混淆
注意点
如果项目已成型,不知道改哪里,可以先混淆一遍,然后运行会报错,在一个个去改,我当时项目第一次报了200多个错误,看起来很多,很多都是不需要改的,比如,混淆了)}导致一系列报错,改一个就好了
大概也就改了几十处地方,工作量不是很大