iOS平台如何确保安全框架不被越狱用户替换?
iOS平台防止安全框架被替换的最佳方案
核心思路:代码签名验证 + 运行时完整性校验
iOS的代码签名机制是基础防护,要确保安全框架被篡改后无法通过系统校验,同时在APP运行时主动完成框架签名与完整性的双重验证——这是应对越狱环境篡改的关键。
一、利用苹果代码签名的基础保障
你的安全框架必须和主APP使用同一开发者账号/签名身份打包编译。正常情况下,iOS系统会拒绝加载未签名、签名非法或与主APP签名身份不匹配的动态框架;但越狱环境下存在工具可绕过系统校验,因此必须补充主动校验逻辑。
二、运行时校验框架签名的实现
在APP启动阶段(建议在框架加载前或初始化时),获取当前框架的签名哈希,与预存的合法签名哈希比对,不一致则触发保护逻辑(终止APP/禁用安全功能)。
1. 获取框架签名哈希的示例代码
#import <Foundation/Foundation.h> #import <Security/Security.h> NSString *getFrameworkSignatureHash(NSString *frameworkPath) { NSURL *frameworkURL = [NSURL fileURLWithPath:frameworkPath]; SecStaticCodeRef staticCode = NULL; OSStatus status = SecStaticCodeCreateWithPath((CFURLRef)frameworkURL, kSecCSDefaultFlags, &staticCode); if (status != errSecSuccess) { CFRelease(staticCode); return nil; } SecCodeRef dynamicCode = NULL; status = SecCodeCopyGuestWithAttributes(staticCode, kSecCSDefaultFlags, NULL, &dynamicCode); if (status != errSecSuccess) { CFRelease(staticCode); CFRelease(dynamicCode); return nil; } CFDictionaryRef info = NULL; status = SecCodeCopySigningInformation(dynamicCode, kSecCSDefaultFlags, &info); if (status != errSecSuccess) { CFRelease(staticCode); CFRelease(dynamicCode); CFRelease(info); return nil; } // 获取SHA-256格式的签名哈希 NSData *signatureHash = (__bridge NSData *)CFDictionaryGetValue(info, kSecCodeInfoSignatureHash); NSString *hashString = [signatureHash base64EncodedStringWithOptions:0]; CFRelease(staticCode); CFRelease(dynamicCode); CFRelease(info); return hashString; }
2. 校验逻辑实现
- 预计算合法框架的签名哈希:将编译后的框架通过上述代码或命令行工具生成哈希值,通过编译时嵌入二进制常量、加密存储到Keychain等方式保存(需做混淆处理,避免明文泄露)。
- 启动校验:在
application:didFinishLaunchingWithOptions:中调用上述方法,获取当前框架的签名哈希并与预存值比对,不一致则立即执行保护逻辑。
三、越狱环境的额外防护
- 越狱检测前置:在签名校验前先检测设备是否越狱,触发检测后直接拒绝加载安全框架:
BOOL isJailbroken() { // 检查越狱标志性文件 NSArray *jailbreakFiles = @[ @"/Applications/Cydia.app", @"/private/var/stash", @"/private/var/lib/apt/" ]; for (NSString *path in jailbreakFiles) { if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { return YES; } } // 检查是否能加载越狱常用动态库 void *handle = dlopen("/usr/lib/libsubstrate.dylib", RTLD_NOW); if (handle != NULL) { dlclose(handle); return YES; } return NO; }
- 启用Hardened Runtime:在Xcode的Build Settings中开启Hardened Runtime,勾选
Disable Debugging和Enable Library Validation——这会阻止第三方调试器附加,同时禁止加载未签名的动态库。 - 代码混淆:对签名校验、越狱检测的核心代码做混淆处理,防止攻击者逆向分析并绕过校验逻辑。
四、入门实施步骤
- 框架签名配置:在框架Target的
Signing & Capabilities中选择与主APP一致的Team和Provisioning Profile,编译后框架会自动完成合法签名。 - 生成合法签名哈希:编译框架后,可通过命令行工具获取哈希:
# 提取签名信息并获取哈希 security cms -D -i /path/to/YourFramework.framework/_CodeSignature/CodeResources | grep -A 5 "Hash"
- 集成校验逻辑:将签名校验与越狱检测代码集成到主APP启动流程,确保框架加载前完成验证。
- 测试验证:
- 正常环境:APP加载框架,校验通过后正常运行。
- 篡改框架:替换为未签名/非法签名的框架,APP检测到哈希不一致并触发保护。
- 越狱环境:APP检测到越狱,拒绝加载安全框架。
注意事项
- 预存的签名哈希不可明文存储,需做加密或混淆处理。
- 校验逻辑必须放在主APP中,不可放在被保护的框架内(否则框架被替换后校验逻辑也会失效)。
- 所有实现需符合苹果App Store审核规则,上述代码使用的均为公开API,Hardened Runtime为苹果官方支持的安全机制。
内容的提问来源于stack exchange,提问作者Tolgay Toklar
相关产品推荐
相关产品推荐

