5

I read a very interesting blog about implementing some anti-piracy protection into your apps. Some of them dont work anymore, some of them do. The 2 ones that still are effective to an extent are the 2 last ones listed. http://shmoopi.wordpress.com/2011/06/19/27/

The one I'm interested in is the very last one. Code below. I've implemented this in my AppDelegate.m

Anti piracy via the encryption check.

Required Headers

#import <dlfcn.h>
#import <mach-o/dyld.h>
#import <TargetConditionals.h>

Encryption Struct

#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

Needed Methods

int main (int argc, char *argv[]);

static BOOL is_encrypted () 
{
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) 
        {
            return NO;
        }
        return YES;
    }

    cmd = (struct load_command *) ((uint8_t *) cmd + cmd->cmdsize);
}   
return NO;
}

This method checks to see if the binary is still encrypted.

When I run this on the device attached to x-code it gives me a false positive on this line

if (crypt_cmd->cryptid < 1) 
{
    NSLog(@"Pirated from (crypt_cmd->cryptid < 1) ");
    return NO;
} 

I was wondering is it possible that the builds xcode puts onto the device for debugging purposes not encrypted? And its only encrypted when the build is submitted to Apple for use on iTunes. Hence why I am getting this false positive when check the code.

Many Thanks, -Code

4 Answers4

5

This code won't work successfully on a 64-bit device like the iPhone 5s. The header has been changed from mach_header to mach_header_64 and the command ID is now LC_ENCRYPTION_INFO_64.

What I did was to read the header and then see what the magic number was. If it's MH_MAGIC_64 then you're on a 64-bit device and you need to use the mach_header_64 struct and look for LC_ENCRYPTION_INFO_64 (defined as 0x2C) instead of LC_ENCRYPTION_INFO.

Szymon
  • 42,577
  • 16
  • 96
  • 114
August
  • 51
  • 1
  • 1
4

A better otool command to see whether a file is encrypted or not is:

otool -arch armv7 -l YourAppName | grep crypt
jek
  • 41
  • 2
1

I have been looking into this recently as well and tested with the same results. It turns out this code is telling you YES or NO based on whether the binary is encrypted with Apple's FairPlay DRM. Any debug or ad-hoc builds you do will say NO.

You can see the same information on your binary or any iPhone apps you have purchased using the otool command-line tool.

For your own binaries, find the binary in your project under e.g. build/Debug-iphoneos/MyApp.app and run (from Terminal)

otool -l MyApp | more

Scan through for cryptid in the LC_ENCRYPTION_INFO section. Since this is a debug build it will be 0. If you have synched your phone to your computer, check under ~/Music/iTunes/Mobile Applications and pick an .ipa file. Unzip it and try otool against the binary from the .ipa and it should have 1 for the cryptid.

Eric Hedstrom
  • 1,627
  • 10
  • 13
0

It looks like this is looking for the signature block in the dyload header. This means that you're only going to see this on code which is signed. Chances are that your code isn't being automatically signed for debugging (unnecessary), although it will be signed when it goes to the device.

You might want to make this entire check conditional on the project running on an iOS device instead of in the simulator. Any binary sent to an iOS device must be signed.

#if !(TARGET_IPHONE_SIMULATOR)
your check
#endif // 
gaige
  • 17,263
  • 6
  • 57
  • 68
  • Even on my test-device it acts the same. I'm wondering is it the fact that the encryption is applied by Apple when they make it app-store ready. So its not applied when we build it ourselves on our local devices. –  Aug 12 '11 at 14:01