
IOSSecuritySuite v2.3.0
iOS平台安全与防篡改Swift库
⭐️ 想要成为认证的 iOS 应用安全工程师吗?⭐️
了解我们实用且完全在线的课程:https://courses.securing.pl/courses/iase

ISS 描述

作者 @_r3ggi
🌏 iOS Security Suite 是一个高级且易于使用的平台安全与防篡改库,完全使用纯 Swift 编写!如果你正在为 iOS 开发,并且希望根据 OWASP MASVS 标准(第 v8 章)保护你的应用,那么这个库可以为你节省大量时间。🚀
ISS 检测的内容:
- 越狱 🧨
- 附加调试器 👨🏻🚀
- 应用是否在模拟器中运行 👽
- 设备上正在运行的常见逆向工程工具 🔭
设置
有四种方式可以开始使用 IOSSecuritySuite
1. 添加源代码
将 IOSSecuritySuite/*.swift 文件添加到你的项目中
2. 使用 CocoaPods 设置
pod 'IOSSecuritySuite'
3. 使用 Carthage 设置
github "securing/IOSSecuritySuite"
4. 使用 Swift Package Manager 设置
.package(url: "https://github.com/securing/IOSSecuritySuite.git", from: "1.5.0")
更新 Info.plist
将 ISS 添加到项目后,你还需要更新主 Info.plist。越狱检测模块中有一个检查使用了 canOpenURL(_:) 方法,并且需要指定将要查询的 URL。
<key>LSApplicationQueriesSchemes</key>
<array>
<string>undecimus</string>
<string>sileo</string>
<string>zbra</string>
<string>filza</string>
</array>
定价
详情请查看我们的 EULA 许可协议。
简而言之: 如果你的公司员工人数:
- 0-99 人 - 免费使用
- 100-1000 人 - 3千欧元/年
- 1000 人以上 - 1万欧元/年
如果你想销售一个使用了 iOS Security Suite 的模块(并非直接在应用中使用) - 1万欧元/年
注意
iOS Security Suite 旨在用于 iOS/iPadOS。不应在 Apple Silicon 的 Mac 上使用。
如何使用
越狱检测模块
- 最简单的方法 如果你只想了解设备是否越狱,返回 True/False
if IOSSecuritySuite.amIJailbroken() {
print("此设备已越狱")
} else {
print("此设备未越狱")
}
- 详细模式,如果你还想知道识别出了哪些指示器
let jailbreakStatus = IOSSecuritySuite.amIJailbrokenWithFailMessage()
if jailbreakStatus.jailbroken {
print("此设备已越狱")
print("因为:\(jailbreakStatus.failMessage)")
} else {
print("此设备未越狱")
}
failMessage 是一个字符串,包含逗号分隔的指示器,如下例所示:
sileo:// URL scheme detected, Suspicious file exists: /Library/MobileSubstrate/MobileSubstrate.dylib, Fork was able to create a new process
- 详细且可过滤,如果你还想例如识别出过去越狱但现在已恢复的设备
let jailbreakStatus = IOSSecuritySuite.amIJailbrokenWithFailedChecks()
if jailbreakStatus.jailbroken {
if (jailbreakStatus.failedChecks.contains { $0.check == .existenceOfSuspiciousFiles }) && (jailbreakStatus.failedChecks.contains { $0.check == .suspiciousFilesCanBeOpened }) {
print("这是真正的越狱设备")
}
}
调试器检测模块
let amIDebugged: Bool = IOSSecuritySuite.amIDebugged()
完全拒绝调试器
IOSSecuritySuite.denyDebugger()
模拟器检测模块
let runInEmulator: Bool = IOSSecuritySuite.amIRunInEmulator()
逆向工程工具检测模块
- 最简单的方法 如果你只想了解设备是否存在逆向工程证据,返回 True/False
if IOSSecuritySuite.amIReverseEngineered() {
print("此设备存在逆向工程证据")
} else {
print("此设备不存在逆向工程证据")
}
- 详细且可过滤,如果你还想获取已执行检查的列表
let reverseStatus = IOSSecuritySuite.amIReverseEngineeredWithFailedChecks()
if reverseStatus.reverseEngineered {
// 查看 reverseStatus.failedChecks 获取更多详情
}
系统代理检测模块
现在你还可以检测应用是否连接到 VPN
let amIProxied: Bool = IOSSecuritySuite.amIProxied(considerVPNConnectionAsProxy: true)
锁定模式检测模块
let amIInLockdownMode: Bool = IOSSecuritySuite.amIInLockdownMode()
实验性功能
运行时 Hook 检测模块
let amIRuntimeHooked: Bool = amIRuntimeHook(dyldWhiteList: dylds, detectionClass: SomeClass.self, selector: #selector(SomeClass.someFunction), isClassMethod: false)
符号 Hook 拒绝模块
// 如果我们想拒绝 Swift 函数的符号 Hook,必须传递该函数的混淆名称
denySymbolHook("$s10Foundation5NSLogyySS_s7CVarArg_pdtF") // 拒绝 Hook NSLog 函数
NSLog("Hello Symbol Hook")
denySymbolHook("abort")
abort()
MSHook 检测模块
// 函数声明
func someFunction(takes: Int) -> Bool {
return false
}
// 定义 FunctionType:@convention(thin) 表示“瘦”函数引用,使用 Swift 调用约定,没有特殊的“self”或“context”参数。
typealias FunctionType = @convention(thin) (Int) -> (Bool)
// 获取要验证的函数的指针地址
func getSwiftFunctionAddr(_ function: @escaping FunctionType) -> UnsafeMutableRawPointer {
return unsafeBitCast(function, to: UnsafeMutableRawPointer.self)
}
let funcAddr = getSwiftFunctionAddr(someFunction)
let amIMSHooked = IOSSecuritySuite.amIMSHooked(funcAddr)
MSHook 拒绝模块
// 函数声明
func denyDebugger(value: Int) {
}
// 定义 FunctionType:@convention(thin) 表示“瘦”函数引用,使用 Swift 调用约定,没有特殊的“self”或“context”参数。
typealias FunctionType = @convention(thin) (Int)->()
// 获取原始函数地址
let funcDenyDebugger: FunctionType = denyDebugger
let funcAddr = unsafeBitCast(funcDenyDebugger, to: UnsafeMutableRawPointer.self)
if let originalDenyDebugger = denyMSHook(funcAddr) {
// 使用 1337 作为 Int 参数调用原始函数
unsafeBitCast(originalDenyDebugger, to: FunctionType.self)(1337)
} else {
denyDebugger()
}
文件完整性验证模块
// 判断应用程序是否被篡改
if IOSSecuritySuite.amITampered([.bundleID("biz.securing.FrameworkClientApp"),
.mobileProvision("2976c70b56e9ae1e2c8e8b231bf6b0cff12bbbd0a593f21846d9a004dd181be3"),
.machO("IOSSecuritySuite", "6d8d460b9a4ee6c0f378e30f137cebaf2ce12bf31a2eef3729c36889158aa7fc")]).result {
print("我已遭篡改。")
}
else {
print("我未遭篡改。")
}
// 手动验证已加载 dylib 的 SHA256 哈希值
if let hashValue = IOSSecuritySuite.getMachOFileHashValue(.custom("IOSSecuritySuite")), hashValue == "6d8d460b9a4ee6c0f378e30f137cebaf2ce12bf31a2eef3729c36889158aa7fc" {
print("我未遭篡改。")
}
else {
print("我已遭篡改。")
}
// 检查主可执行文件的 SHA256 哈希值
// 提示:你的应用程序可以从服务器获取此值
if let hashValue = IOSSecuritySuite.getMachOFileHashValue(.default), hashValue == "your-application-executable-hash-value" {
print("我未遭篡改。")
}
else {
print("我已遭篡改。")
}
断点检测模块
func denyDebugger() {
// 在此处设置断点
}
typealias FunctionType = @convention(thin) ()->()
let func_denyDebugger: FunctionType = denyDebugger // `: FunctionType` 是必需的
let func_addr = unsafeBitCast(func_denyDebugger, to: UnsafeMutableRawPointer.self)
let hasBreakpoint = IOSSecuritySuite.hasBreakpointAt(func_addr, functionSize: nil)
if hasBreakpoint {
print("在指定函数中发现了断点")
} else {
print("在指定函数中未发现断点")
}
观察点检测模块
// 在 testWatchpoint 函数设置断点
func testWatchpoint() -> Bool{
// lldb: watchpoint set expression ptr
var ptr = malloc(9)
// lldb: watchpoint set variable count
var count = 3
return IOSSecuritySuite.hasWatchpoint()
}
安全考虑
在使用此工具和其他平台安全检查器之前,你需要了解:
- 将此工具包含到项目中并不是提升应用安全性的唯一方法!你可以在此处阅读通用的移动安全白皮书 此处。
- 检测设备是否越狱是在设备本地完成的。这意味着任何越狱检测器都可能被绕过(包括这个)!
- 通常认为 Swift 代码比 Objective-C 更难动态操作。由于此库是用纯 Swift 编写的,IOSSecuritySuite 的方法不应暴露给 Objective-C 运行时(这使得绕过更加困难 ✅)。你需要知道攻击者仍然能够对 Swift 符号进行 MSHookFunction/MSFindSymbol 并动态改变 Swift 代码执行流程。
贡献 ❤️
当然可以!如果你有更好的想法或只想改进这个项目,请在 Twitter 或 LinkedIn 上联系我。非常欢迎 Pull Request!
特别感谢:👏🏻
- kubajakowski 指出了
canOpenURL(_:)方法的问题 - olbartek 代码审查和 pull request
- benbahrenburg 各种 ISS 改进
- fotiDim 添加了新的文件路径检查
- gcharita 添加了 Swift Package Manager 支持
- rynaardb 创建了
amIJailbrokenWithFailedChecks()方法 - undeaDD 各种 ISS 改进
- fnxpt 添加了多个越狱检测
- TannerJin MSHook、RuntimeHook、SymbolHook 和观察点检测模块
- NikoXu 添加了文件完整性模块
- hellpf 修复了悬挂 socket 问题
- Ant-tree 改进了 hook 抵抗性
- izmcm 实现了
amIReverseEngineeredWithFailedChecks()方法 - sanu 提供了新的文件检查
- marsepu 带来了新改进的优质 PR
- mkj-is 提交了提升 ISS 性能的 PR 🚄
- LongXiangGuo 提交了添加隐私清单的 PR
- Coeur 进行了 ISS 改进和错误修复
- Adobels 调整 ISS 以适应苹果的新要求
TODO
- 研究 Installer5 和 Zebra 包管理器检测(Cydia 替代品)
- Dopamine hidejb 检测器
许可
参见 LICENSE 文件。
参考
在创建此工具时,我使用了:
- 🔗 https://github.com/TheSwiftyCoder/JailBreak-Detection
- 🔗 https://github.com/abhinashjain/jailbreakdetection
- 🔗 https://gist.github.com/ddrccw/8412847
- 🔗 https://gist.github.com/bugaevc/4307eaf045e4b4264d8e395b5878a63b
- 📚 "iOS Application Security" by David Thiel