如何检测应用程序是否已经被破解,而不检查SignerIdentity?

过去有一种方法来检查应用程序是否从App Store购买,以防止破解:

NSBundle *bundle = [NSBundle mainBundle]; NSDictionary *info = [bundle infoDictionary]; if ([info objectForKey: @"SignerIdentity"] != nil) { /* do something */ } 

但这种方法不再有效,因为破解者已经find了改变Info.plist的方法。 我意识到这个较老的问题 ,但是那里提出的答案依赖于上述技术,这已经不再有效。

你怎么能检测你的应用程序是否被破解或从App Store合法购买,而无需从Info.plist中读取SignerIdentity?

虽然没有检查是否从App Store购买了应用程序,但是我使用此代码来检查我的应用程序是否在越狱设备上运行:

 +(BOOL)isJailbroken { NSURL* url = [NSURL URLWithString:@"cydia://package/com.example.package"]; return [[UIApplication sharedApplication] canOpenURL:url]; } 

我个人喜欢米克的回答,因为它简短而简单。

格雷格的回应是无效的 – 米克的代码只检查应用程序是否可以打开该URL,所以不应该有崩溃的机会。

我已经在我的一个应用程序中实现了以下function,之前对应用程序是否encryption进行了更严格的检查,如果这不是最有可能的破解应用程序:

从分析来看,这种方法已经阻止了成千上万的盗版用户,并花了5分钟的时间来执行,所以这样做的代价几乎没有什么 – 对我来说,我不在乎是否增加了销售额(我确信它没有不pipe怎么说 – 我不希望有人因为我的辛勤工作而感到厌烦)。 此外,我的应用程序的内容提供了很多信息后,找出应用程序是否是盗版的,如果是的话,返回垃圾数据。

在main.m

 #import <dlfcn.h> #import <mach-o/dyld.h> #import <TargetConditionals.h> #if TARGET_IPHONE_SIMULATOR && !defined(LC_ENCRYPTION_INFO) #define LC_ENCRYPTION_INFO 0x21 struct encryption_info_command { uint32_t cmd; uint32_t cmdsize; uint32_t cryptoff; uint32_t cryptsize; uint32_t cryptid; }; #endif static BOOL isEncrypted(); static BOOL isEncrypted () { const struct mach_header *header; Dl_info dlinfo; /* Fetch the dlinfo for main() */ if (dladdr(main, &dlinfo) == 0 || dlinfo.dli_fbase == NULL) { //NSLog(@"Could not find main() symbol (very odd)"); return NO; } header = dlinfo.dli_fbase; /* Compute the image size and search for a UUID */ struct load_command *cmd = (struct load_command *) (header+1); for (uint32_t i = 0; cmd != NULL && i < header->ncmds; i++) { /* Encryption info segment */ if (cmd->cmd == LC_ENCRYPTION_INFO) { struct encryption_info_command *crypt_cmd = (struct encryption_info_command *) cmd; /* Check if binary encryption is enabled */ if (crypt_cmd->cryptid < 1) { /* Disabled, probably pirated */ return NO; } /* Probably not pirated <-- can't say for certain, maybe theres a way around it */ return YES; } cmd = (struct load_command *) ((uint8_t *) cmd + cmd->cmdsize); } /* Encryption info not found */ return NO; } 

苹果官方的回答是:

 Hello Dmitry, Thank you for contacting Apple Developer Technical Support (DTS). DTS does not provide code-level support for DRM issues. Please try posting your inquiry to Apple Development Forum: <https://devforums.apple.com> While you were initially charged a Technical Support Incident (TSI) for this request, we have assigned a replacement TSI back to your account. Thank you for understanding our support policies. Best Regards, Apple Developer Support Worldwide Developer Relations 

我会build议一个较小的代码片段,它和@ user1353482所build议的一样(同样的方法)。 我会写评论,但代码将是不可读的。 此外,我可能是错的,但似乎额外的定义是不再需要了,即使编译模拟器(至less这在xcode 4.5.1,目标是5.0)。

请注意,这个代码在debugging和adhoc二进制文件上返回false,但是我们正在讨论appstore,对吧? 这是苹果谁做最后的encryption,你应该不要在家里尝试这个:)

 #include <execinfo.h> #import <mach-o/ldsyms.h> bool executableEncryption() { const uint8_t *command = (const uint8_t *) (&_mh_execute_header + 1); for (uint32_t idx = 0; idx < _mh_execute_header.ncmds; ++idx) { if (((const struct load_command *) command)->cmd == LC_ENCRYPTION_INFO) { struct encryption_info_command *crypt_cmd = (struct encryption_info_command *) command; if (crypt_cmd->cryptid < 1) return false; return true; } else { command += ((const struct load_command *) command)->cmdsize; } } return false; }