ios开发逆向安全防抓包

  1. 防止抓包

    • 使用SSL Pinning(证书绑定):在客户端内置服务器证书或公钥,在建立SSL/TLS连接时进行验证,防止中间人攻击。

    • 避免使用明文传输:所有网络请求使用HTTPS,并且确保正确的证书验证。

  2. 代码混淆

    • 使用工具对Objective-C代码进行混淆,增加逆向难度。例如,类名、方法名、属性名使用无意义的字符串替换。
  3. 反调试

    • 使用系统API检测是否被调试,如果被调试则采取相应措施(如退出应用)。
  4. 完整性检查

    • 检查应用是否被重签名或篡改,可以通过比较嵌入的签名或检查文件完整性来实现。
  5. 字符串加密

    • 对敏感字符串进行加密,防止在二进制文件中直接显示。
  6. 使用C代码

    • 将敏感逻辑用C/C++实现,因为C/C++编译后的代码比Objective-C更难逆向。
  7. 动态加载代码

    • 从服务器下载加密的代码,在运行时解密执行,增加静态分析的难度。
  8. 使用安全框架

    • 使用第三方安全框架,如Obfuscator、Themis等。

下面是一些具体的实现示例:

1. SSL Pinning

在iOS中,可以使用NSURLSessionAFNetworking等网络库来实现SSL Pinning。

使用NSURLSession的示例:

  • (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {

if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {

SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;

// 加载内置的证书

NSString *certPath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"];

NSData *certData = [NSData dataWithContentsOfFile:certPath];

SecCertificateRef cert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certData);

// 设置锚点证书

SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)@[(__bridge id)cert]);

SecTrustResultType result;

SecTrustEvaluate(serverTrust, &result);

if (result == kSecTrustResultProceed || result == kSecTrustResultUnspecified) {

NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];

completionHandler(NSURLSessionAuthChallengeUseCredential, credential);

} else {

completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);

}

CFRelease(cert);

} else {

completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);

}

}

2. 代码混淆

可以使用脚本在编译阶段对类名、方法名进行替换。例如,使用一个宏定义来替换方法名:

// 定义一个混淆宏,在预编译阶段将方法名替换为随机字符串

#define OBFUSCATE(string) [NSString stringWithUTF8String:obfuscateCString(string)]

// 随机字符串生成函数

const char* obfuscateCString(const char* string) {

// 实现一个简单的混淆算法,例如异或操作

// 注意:这里只是示例,实际使用时需要更复杂的算法

static char obfuscated[256];

for (int i = 0; i < strlen(string); i++) {

obfuscated[i] = string[i] ^ 0x55;

}

obfuscated[strlen(string)] = '\0';

return obfuscated;

}

// 使用示例

NSString *secretKey = OBFUSCATE("mySecretKey");

但是,这种方法需要谨慎使用,因为可能会引起运行时错误。更常见的做法是使用第三方工具,如Obfuscator-iOS。

3. 反调试

通过ptrace系统调用可以防止调试器附加。但是,ptrace是私有API,使用它可能会导致App Store审核被拒。因此,在发布版本中不建议使用。

#import <sys/types.h>

#import <sys/sysctl.h>

#import <unistd.h>

// 检查是否被调试

static int checkDebugger() {

int name[4];

struct kinfo_proc info;

size_t info_size = sizeof(info);

name[0] = CTL_KERN;

name[1] = KERN_PROC;

name[2] = KERN_PROC_PID;

name[3] = getpid();

if (sysctl(name, 4, &info, &info_size, NULL, 0) == -1) {

NSLog(@"sysctl failed");

return -1;

}

return (info.kp_proc.p_flag & P_TRACED) ? 1 : 0;

}

// 在应用启动时调用

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

// 如果检测到调试器,可以采取相应措施,如退出应用

if (checkDebugger()) {

exit(0);

}

return YES;

}

4. 完整性检查

检查签名是否匹配:

  • (BOOL)isValidSignature {

// 获取嵌入的签名

NSString *embeddedSignature = @"your_embedded_signature"; // 从服务器获取或内置

// 计算当前应用的签名(这里简化,实际需要获取代码签名信息)

// 可以使用SecCodeCopySigningInformation等函数

// 比较两个签名是否一致

return [embeddedSignature isEqualToString:currentSignature];

}

5. 字符串加密

对敏感字符串进行加密,运行时解密:

// 加密字符串(示例:Base64编码,实际可以使用更复杂的加密)

#define ENCRYPT(string) [[string dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0]

#define DECRYPT(string) [[NSString alloc] initWithData:[[NSData alloc] initWithBase64EncodedString:string options:0] encoding:NSUTF8StringEncoding]

// 使用

NSString *encrypted = ENCRYPT(@"secret string");

NSString *decrypted = DECRYPT(encrypted);

6. 使用C代码

将敏感算法用C实现,并编译成静态库,增加逆向难度。

7. 动态加载代码

从服务器下载加密的代码(如JavaScript代码,通过JavaScriptCore执行),或者使用动态库(但iOS限制较多)。

8. 使用安全框架

集成第三方安全框架,如Themis(提供安全存储、加密通信等功能)。

请注意,没有任何方法可以完全防止逆向工程,但通过多种措施组合可以增加逆向的难度。同时,要平衡安全性和用户体验,以及避免使用私有API导致审核被拒。

iOS逆向安全防抓包需要从多个层面进行防护,以下是Objective-C实现的关键方案:

一、网络层防护

1. SSL/TLS证书绑定

// SSLPinningManager.h

@interface SSLPinningManager : NSObject

  • (instancetype)sharedManager;
  • (void)setupSSLPinning;

@end

// SSLPinningManager.m

@implementation SSLPinningManager

  • (void)setupSSLPinning {

// 方法1:公钥绑定

self setupPublicKeyPinning\]; // 方法2:证书绑定 \[self setupCertificatePinning\]; } - (void)setupPublicKeyPinning { // 使用AFNetworking或原生NSURLSession实现 AFSecurityPolicy \*policy = \[AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey\]; policy.allowInvalidCertificates = NO; policy.validatesDomainName = YES; // 设置公钥哈希数组 NSArray \*pinnedKeys = @\[ @"sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", // 替换为实际公钥哈希 \]; policy.pinnedCertificates = \[NSSet setWithArray:pinnedKeys\]; \[AFHTTPSessionManager manager\].securityPolicy = policy; } - (void)setupCertificatePinning { // 原生NSURLSession实现 NSURLSessionConfiguration \*config = \[NSURLSessionConfiguration defaultSessionConfiguration\]; config.TLSMinimumSupportedProtocol = kTLSProtocol12; // 添加自定义SSL验证 \[NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil\]; } #pragma mark - NSURLSessionDelegate - (void)URLSession:(NSURLSession \*)session didReceiveChallenge:(NSURLAuthenticationChallenge \*)challenge completionHandler:(void (\^)(NSURLSessionAuthChallengeDisposition, NSURLCredential \*))completionHandler { if (\[challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust\]) { SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; // 1. 设置策略 SecPolicyRef policy = SecPolicyCreateSSL(true, (__bridge CFStringRef)challenge.protectionSpace.host); SecTrustSetPolicies(serverTrust, policy); // 2. 验证证书链 SecTrustResultType result; SecTrustEvaluate(serverTrust, \&result); // 3. 自定义验证:检查是否包含预置证书 BOOL isTrusted = \[self validateCertificate:serverTrust\]; if (isTrusted) { NSURLCredential \*credential = \[NSURLCredential credentialForTrust:serverTrust\]; completionHandler(NSURLSessionAuthChallengeUseCredential, credential); } else { completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); } } } - (BOOL)validateCertificate:(SecTrustRef)trust { // 获取证书链 CFIndex certificateCount = SecTrustGetCertificateCount(trust); // 加载预置证书 NSString \*certPath = \[\[NSBundle mainBundle\] pathForResource:@"your_certificate" ofType:@"der"\]; NSData \*certData = \[NSData dataWithContentsOfFile:certPath\]; SecCertificateRef embeddedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certData); for (CFIndex i = 0; i \< certificateCount; i++) { SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, i); // 比较证书 if (CFEqual(certificate, embeddedCertificate)) { CFRelease(embeddedCertificate); return YES; } } CFRelease(embeddedCertificate); return NO; } @end #### 2. 双向认证 (mTLS) // MutualTLSAuthManager.h @interface MutualTLSAuthManager : NSObject - (void)setupClientCertificate; @end // MutualTLSAuthManager.m @implementation MutualTLSAuthManager { NSData \*_clientCertificate; SecIdentityRef _identity; } - (void)setupClientCertificate { // 从Keychain或加密存储中加载客户端证书 NSString \*encryptedCertPath = \[\[NSBundle mainBundle\] pathForResource:@"client_cert_encrypted" ofType:@"p12"\]; NSData \*encryptedData = \[NSData dataWithContentsOfFile:encryptedCertPath\]; // 解密证书 NSData \*decryptedData = \[self decryptData:encryptedData\]; // 导入证书到Keychain \[self importPKCS12Data:decryptedData\]; } - (void)importPKCS12Data:(NSData \*)pkcs12Data { CFArrayRef items = NULL; NSDictionary \*options = @{ (__bridge id)kSecImportExportPassphrase: \[self getDecryptionKey

};

OSStatus status = SecPKCS12Import((__bridge CFDataRef)pkcs12Data,

(__bridge CFDictionaryRef)options,

&items);

if (status == errSecSuccess) {

CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);

_identity = (SecIdentityRef)CFDictionaryGetValue(identityDict,

kSecImportItemIdentity);

CFRetain(_identity);

}

if (items) CFRelease(items);

}

// 在NSURLSessionDelegate中使用

  • (void)URLSession:(NSURLSession *)session

didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge

completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler {

if (challenge.previousFailureCount == 0 && _identity) {

SecCertificateRef certificate = NULL;

SecIdentityCopyCertificate(_identity, &certificate);

NSArray *certs = @[(__bridge id)certificate];

NSURLCredential *credential = [NSURLCredential credentialWithIdentity:_identity

certificates:certs

persistence:NSURLCredentialPersistenceForSession];

completionHandler(NSURLSessionAuthChallengeUseCredential, credential);

if (certificate) CFRelease(certificate);

} else {

completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);

}

}

二、防代理检测

// ProxyDetectionManager.h

@interface ProxyDetectionManager : NSObject

  • (BOOL)isProxyEnabled;

  • (BOOL)isVPNConnected;

@end

// ProxyDetectionManager.m

#import <SystemConfiguration/SystemConfiguration.h>

@implementation ProxyDetectionManager

  • (BOOL)isProxyEnabled {

CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings();

NSDictionary *settings = (__bridge NSDictionary *)proxySettings;

BOOL enabled = NO;

// 检查HTTP代理

NSString *httpProxy = settings[(NSString *)kCFNetworkProxiesHTTPProxy];

NSString *httpsProxy = settings[(NSString *)kCFNetworkProxiesHTTPSProxy];

if (httpProxy || httpsProxy) {

enabled = YES;

}

// 检查PAC代理

NSString *pacURL = settings[(NSString *)kCFNetworkProxiesProxyAutoConfigURLString];

if (pacURL) {

enabled = YES;

}

CFRelease(proxySettings);

// 额外检查:Charles等工具常用端口

if (enabled) {

enabled = [self checkSpecificProxyPorts];

}

return enabled;

}

  • (BOOL)checkSpecificProxyPorts {

// 常见抓包工具端口检测

NSArray *commonProxyPorts = @[@8888, @8889, @8080, @8081, @9999];

for (NSNumber *port in commonProxyPorts) {

int socketFD = socket(AF_INET, SOCK_STREAM, 0);

if (socketFD == -1) continue;

struct sockaddr_in addr;

memset(&addr, 0, sizeof(addr));

addr.sin_len = sizeof(addr);

addr.sin_family = AF_INET;

addr.sin_port = htons([port intValue]);

addr.sin_addr.s_addr = inet_addr("127.0.0.1");

if (connect(socketFD, (struct sockaddr *)&addr, sizeof(addr)) == 0) {

close(socketFD);

return YES;

}

close(socketFD);

}

return NO;

}

  • (BOOL)isVPNConnected {

// 检查VPN连接状态

CFDictionaryRef cfDict = CFNetworkCopySystemProxySettings();

NSDictionary *dict = (__bridge NSDictionary *)cfDict;

NSArray *keys = [dict[@"SCOPED"] allKeys];

for (NSString *key in keys) {

if ([key containsString:@"tap"] ||

key containsString:@"tun"\] \|\| \[key containsString:@"ppp"\] \|\| \[key containsString:@"ipsec"\]) { CFRelease(cfDict); return YES; } } CFRelease(cfDict); return NO; } @end ### 三、请求保护 #### 1. 参数签名 // RequestSigner.h @interface RequestSigner : NSObject + (NSString \*)signRequestWithParams:(NSDictionary \*)params timestamp:(NSTimeInterval)timestamp; + (NSDictionary \*)signedHeadersForRequest:(NSURLRequest \*)request; @end // RequestSigner.m #import \ @implementation RequestSigner + (NSString \*)signRequestWithParams:(NSDictionary \*)params timestamp:(NSTimeInterval)timestamp { // 1. 参数排序并拼接 NSArray \*sortedKeys = \[\[params allKeys\] sortedArrayUsingSelector:@selector(compare:)\]; NSMutableString \*signString = \[NSMutableString string\]; for (NSString \*key in sortedKeys) { \[signString appendFormat:@"%@=%@\&", key, params\[key\]\]; } // 2. 添加时间戳和随机数 NSString \*nonce = \[self generateNonce\]; \[signString appendFormat:@"timestamp=%f\&nonce=%@", timestamp, nonce\]; // 3. 添加动态密钥(定期更新) NSString \*dynamicKey = \[self getDynamicKey\]; \[signString appendFormat:@"\&dynamic_key=%@", dynamicKey\]; // 4. HMAC签名 NSString \*signature = \[self hmacSHA256:signString secret:\[self getAppSecret\]\]; return signature; } + (NSString \*)generateNonce { // 生成随机字符串 NSString \*uuid = \[\[NSUUID UUID\] UUIDString\]; return \[\[uuid stringByReplacingOccurrencesOfString:@"-" withString:@""

substringToIndex:16];

}

  • (NSString *)getDynamicKey {

// 从服务器获取或本地生成的动态密钥

// 可以定期更新,增加破解难度

NSTimeInterval interval = [[NSDate date] timeIntervalSince1970];

NSInteger hour = (NSInteger)(interval / 3600);

// 基于时间的动态密钥

NSString *baseKey = @"base_secret_key";

NSString *timeKey = [NSString stringWithFormat:@"%ld", (long)hour];

return [self hmacSHA256:timeKey secret:baseKey];

}

  • (NSString *)hmacSHA256:(NSString *)data secret:(NSString *)secret {

const char *cData = [data cStringUsingEncoding:NSUTF8StringEncoding];

const char *cSecret = [secret cStringUsingEncoding:NSUTF8StringEncoding];

unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];

CCHmac(kCCHmacAlgSHA256, cSecret, strlen(cSecret), cData, strlen(cData), cHMAC);

NSData *hmacData = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];

return [hmacData base64EncodedStringWithOptions:0];

}

  • (NSDictionary *)signedHeadersForRequest:(NSURLRequest *)request {

NSTimeInterval timestamp = [[NSDate date] timeIntervalSince1970];

NSString *nonce = [self generateNonce];

// 获取请求体

NSData *bodyData = request.HTTPBody;

NSString *bodyString = [[NSString alloc] initWithData:bodyData encoding:NSUTF8StringEncoding];

// 生成签名

NSString *signature = [self signRequestWithBody:bodyString

timestamp:timestamp

nonce:nonce];

return @{

@"X-Timestamp": @(timestamp).stringValue,

@"X-Nonce": nonce,

@"X-Signature": signature,

@"X-App-Version": [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"],

@"X-Device-ID": [self getDeviceUniqueID]

};

}

@end

2. 请求加密

// RequestEncryptor.h

@interface RequestEncryptor : NSObject

  • (NSData *)encryptRequestData:(NSDictionary *)params;

  • (NSDictionary *)decryptResponseData:(NSData *)data;

@end

// RequestEncryptor.m

#import <CommonCrypto/CommonCryptor.h>

@implementation RequestEncryptor

  • (NSData *)encryptRequestData:(NSDictionary *)params {

// 1. JSON序列化

NSError *error;

NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params

options:0

error:&error];

// 2. AES加密

NSData *encryptedData = [self aes256Encrypt:jsonData];

// 3. Base64编码

NSString *base64String = [encryptedData base64EncodedStringWithOptions:0];

// 4. 添加混淆(可选)

base64String = [self obfuscateString:base64String];

return [base64String dataUsingEncoding:NSUTF8StringEncoding];

}

  • (NSData *)aes256Encrypt:(NSData *)data {

char keyPtr[kCCKeySizeAES256 + 1];

bzero(keyPtr, sizeof(keyPtr));

// 动态密钥生成

NSString *dynamicKey = [self generateDynamicKey];

dynamicKey getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding\]; NSUInteger dataLength = \[data length\]; size_t bufferSize = dataLength + kCCBlockSizeAES128; void \*buffer = malloc(bufferSize); size_t numBytesEncrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, keyPtr, kCCKeySizeAES256, NULL, \[data bytes\], dataLength, buffer, bufferSize, \&numBytesEncrypted); if (cryptStatus == kCCSuccess) { return \[NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted\]; } free(buffer); return nil; } + (NSString \*)generateDynamicKey { // 基于设备指纹和应用状态的动态密钥 NSString \*deviceID = \[self getDeviceID\]; NSString \*appVersion = \[\[NSBundle mainBundle\] objectForInfoDictionaryKey:@"CFBundleVersion"\]; NSTimeInterval time = floor(\[\[NSDate date\] timeIntervalSince1970\] / 3600); NSString \*baseString = \[NSString stringWithFormat:@"%@\|%@\|%.0f", deviceID, appVersion, time\]; // SHA256哈希作为密钥 const char \*cStr = \[baseString UTF8String\]; unsigned char result\[CC_SHA256_DIGEST_LENGTH\]; CC_SHA256(cStr, (CC_LONG)strlen(cStr), result); NSData \*hashData = \[NSData dataWithBytes:result length:CC_SHA256_DIGEST_LENGTH\]; return \[hashData base64EncodedStringWithOptions:0\]; } + (NSString \*)obfuscateString:(NSString \*)string { // 简单混淆:交换字符位置 NSMutableString \*obfuscated = \[NSMutableString stringWithString:string\]; NSInteger length = obfuscated.length; for (int i = 0; i \< length / 2; i++) { unichar temp = \[obfuscated characterAtIndex:i\]; \[obfuscated replaceCharactersInRange:NSMakeRange(i, 1) withString:\[NSString stringWithFormat:@"%c", \[obfuscated characterAtIndex:length - i - 1\]\]\]; \[obfuscated replaceCharactersInRange:NSMakeRange(length - i - 1, 1) withString:\[NSString stringWithFormat:@"%c", temp\]\]; } return obfuscated; } @end ### 四、代码混淆与保护 #### 1. 字符串加密 // StringObfuscator.h @interface StringObfuscator : NSObject + (NSString \*)decryptString:(const unsigned char \*)encryptedData length:(size_t)length; @end // StringObfuscator.m @implementation StringObfuscator // 加密字符串的宏(在编译前执行) #define OBFUSCATE(key) \[StringObfuscator decryptString:obf_##key length:sizeof(obf_##key)

// 加密后的字符串数据(示例)

static const unsigned char obf_api_key[] = {0xAA, 0xBB, 0xCC, ...};

static const unsigned char obf_secret[] = {0xDD, 0xEE, 0xFF, ...};

  • (NSString *)decryptString:(const unsigned char *)encryptedData

length:(size_t)length {

// XOR解密

unsigned char *decrypted = malloc(length + 1);

for (int i = 0; i < length; i++) {

decrypted[i] = encryptedData[i] ^ 0x55; // 简单XOR,可以使用更复杂算法

}

decrypted[length] = '\0';

NSString *result = [NSString stringWithUTF8String:(const char *)decrypted];

free(decrypted);

return result;

}

// 使用示例

  • (void)makeRequest {

NSString *apiKey = OBFUSCATE(api_key);

NSString *secret = OBFUSCATE(secret);

// 使用解密后的字符串

}

@end

2. 防Hook检测

// HookDetectionManager.h

@interface HookDetectionManager : NSObject

  • (BOOL)isMethodHooked:(Class)className selector:(SEL)selector;

  • (void)addAntiHookProtection;

@end

// HookDetectionManager.m

#import <objc/runtime.h>

#import <mach-o/dyld.h>

@implementation HookDetectionManager

  • (BOOL)isMethodHooked:(Class)className selector:(SEL)selector {

Method originalMethod = class_getInstanceMethod(className, selector);

// 获取方法实现地址

IMP originalIMP = method_getImplementation(originalMethod);

// 检查IMP是否指向预期代码段

Dl_info info;

if (dladdr((void *)originalIMP, &info)) {

// 检查是否在系统库中

const char *imageName = info.dli_fname;

NSString *imagePath = [NSString stringWithUTF8String:imageName];

// 如果不在主程序镜像中,可能被Hook

if (![imagePath containsString:[[NSBundle mainBundle] bundlePath]]) {

return YES;

}

}

return NO;

}

  • (void)addAntiHookProtection {

// 1. 检查关键方法是否被Hook

self checkCriticalMethods\]; // 2. 添加反Hook代码 \[self installTrampolines\]; // 3. 检测Cydia Substrate等框架 \[self detectInjectionFrameworks\]; } + (void)checkCriticalMethods { NSArray \*criticalSelectors = @\[ @"encryptData:", @"decryptData:", @"signRequest:", @"getApiKey" \]; for (NSString \*selectorName in criticalSelectors) { SEL selector = NSSelectorFromString(selectorName); if (\[self isMethodHooked:\[self class\] selector:selector\]) { \[self takeProtectiveAction\]; } } } + (void)installTrampolines { // 使用汇编保护关键函数 __attribute__((always_inline)) void protectedFunction() { // 内联汇编保护 #ifdef __arm64__ __asm__ volatile( "mov x0, #0\\n" "ret\\n" ); #endif } } + (void)detectInjectionFrameworks { // 检查动态库注入 uint32_t count = _dyld_image_count(); for (uint32_t i = 0; i \< count; i++) { const char \*imageName = _dyld_get_image_name(i); NSString \*imagePath = \[NSString stringWithUTF8String:imageName\]; // 检测常见注入框架 NSArray \*injectionKeywords = @\[ @"MobileSubstrate", @"CydiaSubstrate", @"cynject", @"libhooker", @"ElleKit", @"Substitute" \]; for (NSString \*keyword in injectionKeywords) { if (\[imagePath containsString:keyword\]) { \[self takeProtectiveAction\]; break; } } } } + (void)takeProtectiveAction { // 触发保护机制 \[self clearSensitiveData\]; \[self crashRandomly\]; // 或执行其他混淆行为 exit(0); // 最后退出 } @end ### 五、综合防护方案 // SecurityManager.h @interface SecurityManager : NSObject + (void)initializeSecurity; + (BOOL)isEnvironmentSafe; @end // SecurityManager.m @implementation SecurityManager + (void)initializeSecurity { static dispatch_once_t onceToken; dispatch_once(\&onceToken, \^{ // 1. 检查运行环境 if (!\[self isEnvironmentSafe\]) { \[self handleUnsafeEnvironment\]; return; } // 2. 设置网络防护 \[\[SSLPinningManager sharedManager\] setupSSLPinning\]; \[\[MutualTLSAuthManager sharedManager\] setupClientCertificate\]; // 3. 检测代理 if (\[ProxyDetectionManager isProxyEnabled\] \|\| \[ProxyDetectionManager isVPNConnected\]) { \[self handleProxyDetected\]; } // 4. 防Hook保护 \[HookDetectionManager addAntiHookProtection\]; // 5. 定时检查 \[self scheduleSecurityChecks\]; }); } + (BOOL)isEnvironmentSafe { // 越狱检测 if (\[self isJailbroken\]) return NO; // 调试器检测 if (\[self isDebuggerAttached\]) return NO; // 重签名检测 if (\[self isResigned\]) return NO; // 模拟器检测 #if TARGET_IPHONE_SIMULATOR return NO; #endif return YES; } + (BOOL)isJailbroken { // 常见越狱文件检测 NSArray \*jailbreakPaths = @\[ @"/Applications/Cydia.app", @"/Library/MobileSubstrate/MobileSubstrate.dylib", @"/bin/bash", @"/usr/sbin/sshd", @"/etc/apt" \]; for (NSString \*path in jailbreakPaths) { if (\[\[NSFileManager defaultManager\] fileExistsAtPath:path\]) { return YES; } } // 尝试写入系统目录 NSString \*testPath = @"/private/test.txt"; NSError \*error; \[@"test" writeToFile:testPath atomically:YES encoding:NSUTF8StringEncoding error:\&error\]; \[\[NSFileManager defaultManager\] removeItemAtPath:testPath error:nil\]; return (error == nil); } + (BOOL)isDebuggerAttached { // ptrace反调试 #ifndef PT_DENY_ATTACH #define PT_DENY_ATTACH 31 #endif // 方法1:ptrace typedef int (\*ptrace_ptr_t)(int _request, pid_t _pid, caddr_t _addr, int _data); ptrace_ptr_t ptrace_ptr = (ptrace_ptr_t)dlsym(RTLD_DEFAULT, "ptrace"); if (ptrace_ptr) { ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0); } // 方法2:syscall syscall(26, 31, 0, 0, 0); // 方法3:检测父进程 struct kinfo_proc info; size_t size = sizeof(info); int name\[4\]; name\[0\] = CTL_KERN; name\[1\] = KERN_PROC; name\[2\] = KERN_PROC_PID; name\[3\] = getppid(); if (sysctl(name, 4, \&info, \&size, NULL, 0) != -1) { if (strcmp(info.kp_proc.p_comm, "debugserver") == 0 \|\| strcmp(info.kp_proc.p_comm, "lldb") == 0) { return YES; } } return NO; } + (void)scheduleSecurityChecks { // 定时执行安全检查 dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 30 \* NSEC_PER_SEC, 1 \* NSEC_PER_SEC); dispatch_source_set_event_handler(timer, \^{ if (!\[self isEnvironmentSafe\]) { \[self handleUnsafeEnvironment\]; } if (\[ProxyDetectionManager isProxyEnabled\]) { \[self handleProxyDetected\]; } }); dispatch_resume(timer); } + (void)handleUnsafeEnvironment { // 清理敏感数据 \[self clearSensitiveData\]; // 上报安全事件 \[self reportSecurityEvent:@"unsafe_environment"\]; // 混淆行为或优雅退出 dispatch_async(dispatch_get_main_queue(), \^{ UIAlertController \*alert = \[UIAlertController alertControllerWithTitle:@"安全警告" message:@"检测到不安全环境,应用即将退出" preferredStyle:UIAlertControllerStyleAlert\]; \[\[UIApplication sharedApplication\].keyWindow.rootViewController presentViewController:alert animated:YES completion:\^{ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 \* NSEC_PER_SEC), dispatch_get_main_queue(), \^{ exit(0); }); }\]; }); } @end ### 六、使用建议 1. **分层防护**:不要依赖单一防护措施 2. **动态更新**:定期更新加密算法和密钥 3. **服务端配合**:与服务端协同实现完整防护 4. **性能平衡**:在安全和性能间取得平衡 5. **持续更新**:跟踪最新的逆向技术并更新防护 ### 七、注意事项 1. **审核风险**:部分技术可能违反App Store审核条款 2. **用户体验**:避免过度防护影响正常使用 3. **维护成本**:安全方案需要持续维护和更新 4. **法律合规**:确保符合相关法律法规

相关推荐
shdwak....sad4 小时前
CVE-2025-41253复现
安全
AI_Auto6 小时前
智能制造- 安全标准(三)
安全·制造
SPIRT008 小时前
信息收集系列一
安全
AI_Auto8 小时前
智能制造- 安全标准(二)
安全·制造
老赵聊算法、大模型备案8 小时前
《人工智能拟人化互动服务管理暂行办法(征求意见稿)》深度解读:AI“拟人”时代迎来首个专项监管框架
人工智能·算法·安全·aigc
深盾安全10 小时前
C++错误处理的现代化方式:深入理解std::error_code
安全
FreeBuf_10 小时前
“lc“键漏洞:LangChain高危缺陷(CVE-2025-68664)使提示注入攻击可窃取机密
安全·web安全·langchain
全知科技10 小时前
API安全国家标准发布丨《数据安全技术 数据接口安全风险监测方法》
大数据·人工智能·安全
白帽子黑客罗哥11 小时前
网络安全防护技术与实战策略:从基础防御到前沿应对
安全·web安全·php