There used to be a method to check if an application was purchased from the App Store, to protect against cracking:
NSBundle *bundle = [NSBundle mainBundle];
NS
I like Mick's answer personally as it's short and simple.
Greg's response isn't valid -- Mick's code only checks whether the App can open that URL so there should be no chance of crashing.
I've implemented the following in one of my apps before which does a more strict check of whether the app is encrypted or not, if it's not it's most likely a cracked app:
From analytics, this method has prevented thousands of pirated users for me and took maybe 5 minutes to implement so the cost of doing it was almost nothing -- for me, I didn't care if it increased sales (which I was sure it wasn't going to anyway--it's more that I don't want people freeloading off of my hard work). In addition, a good amount of my app's content feeds information after figuring out whether the app is pirated or not and returns junk data if it is.
In 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;
}
The official Apple's answer:
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
I'd suggest a smaller code snippet that does the same thing as @user1353482 suggested (and the same way). I'd write in comments, but code would be unreadable then. Moreover, I may be wrong but it seems that additional defines is not needed anymore even when compiling for simulator (at least this works in xcode 4.5.1, target is 5.0).
Please note that this code returns false on debug and adhoc binary, but we're talking about appstore, right? It's Apple who makes the final encryption and you're supposed to not try this at home :)
#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;
}
While not a check to see if an Application was purchased from the App Store, I use this code to check to see if my application is running on a jailbroken device:
+(BOOL)isJailbroken {
NSURL* url = [NSURL URLWithString:@"cydia://package/com.example.package"];
return [[UIApplication sharedApplication] canOpenURL:url];
}