Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

iPhone Piracy Protection Code 2 - Another Tutorial

ShmoopiShmoopi Posts: 213Tutorial Authors, Registered Users
edited March 2012 in iPhone SDK Tutorials
Welcome back everybody! This is the second tutorial on iPhone/iTouch Anti-Piracy code from all over the world. For those of you who are new to Anti-Piracy, let me get you updated: App Store Piracy today is running ramped, with over 5 Million pirates in counting, Developers are losing millions of dollars in revenue every day. Some companies have reported piracy rates of over 95%, after only one day.

*Since this tutorial is a collection of Anti-Piracy methods from all over, credits go to their respective authors. I would also like to add that I'm not going into the ethics of hacking or Anti-Piracy during this tutorial and would appreciate if comments about the ethics of Piracy and Anti-Piracy be omitted. Great, with that out of the way, Let's do this!

Let's start with something simple this time. Remember those SignerIdentity checks we did last time? Well, they're going to become obsolete soon with newer methods of cracking just on the horizon; so I thought we'd focus on other areas this time:
#if !TARGET_IPHONE_SIMULATOR
int root = getgid();
if (root <= 10) {
	//Pirated
}
#endif
This code is very self explanatory. We are checking to make sure the user is not the iPhone Simulator, we're grabbing the process id, and checking to make sure it's not the root. Basically, whenever someone cracks your application, some automated processes run it as root in order to run gdb. We are simply making sure that user is not the root. This problem with this method is that the app does not have to be run as root, therefore many cracking applications can be adjusted around this.

This next method comes from one of our fellow iPhoneDevSDK'ers: javaconvert:
#define kInfoSize 500
//Place your NSLog Plist Size into the above Define statment
NSString* bundlePath = [[NSBundle mainBundle] bundlePath];
NSString* path = [NSString stringWithFormat:@"%@/Info.plist", bundlePath ];
NSDictionary *fileInfo = [[NSBundle mainBundle] infoDictionary];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSDictionary *fileAttributes = [fileManager fileAttributesAtPath:path traverseLink:YES];

if (fileAttributes != nil) {
	NSNumber *fileSize;
	if(fileSize = [fileAttributes objectForKey:NSFileSize]){
		NSLog(@"File Size:  %qi\n", [fileSize unsignedLongLongValue]);
		//Best to see the File Size and change it accordingly first
		NSString *cSID = [[NSString alloc] initWithFormat:@"%@%@%@%@%@",@"Si",@"gne",@"rIde",@"ntity",@""];
		BOOL checkedforPir = false;
		if([fileInfo objectForKey:cSID] == nil || [fileInfo objectForKey:cSID] != nil) {
			if([fileSize unsignedLongLongValue] == kInfoSize) {
				checkedforPir = true;
			}
		}
		if(!checkedforPir){
			//Pirated
		}
		[cSID release];
	}
}
Basically what we're doing here is combining 2 of the methods I posted in the last tutorial: Checking the plist size and adding a honeytrap.

This is where we get into some new stuff:
NSString* bundlePath = [[NSBundle mainBundle] bundlePath];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:(@"%@/_CodeSignature", bundlePath)];
if (!fileExists) {
	//Pirated
	NSLog(@"Pirated");
}
BOOL fileExists2 = [[NSFileManager defaultManager] fileExistsAtPath:(@"%@/CodeResources", bundlePath)];
if (!fileExists2) {
	//Pirated
	NSLog(@"Pirated2");
}
BOOL fileExists3 = [[NSFileManager defaultManager] fileExistsAtPath:(@"%@/ResourceRules.plist", bundlePath)];
if (!fileExists3) {
	//Pirated
	NSLog(@"Pirated3");
}
Impressed right? I know I am. What we're doing here is checking to see if "_CodeSignature", "CodeResources", and the "ResourceRules.plist" files exist. Whenever someone cracks an application, they usually exclude the following files because they include the cracker's personal information. Once again, not the absolute best, but not easily crackable.

This next method is cutting edge technology:
NSString* bundlePath = [[NSBundle mainBundle] bundlePath];
NSString* path = [NSString stringWithFormat:@"%@/Info.plist", bundlePath];
NSString* path2 = [NSString stringWithFormat:@"%@/AppName", bundlePath];
NSDate* infoModifiedDate = [[[NSFileManager defaultManager] fileAttributesAtPath:path traverseLink:YES] fileModificationDate];
NSDate* infoModifiedDate2 = [[[NSFileManager defaultManager] fileAttributesAtPath:path2 traverseLink:YES] fileModificationDate];
NSDate* pkgInfoModifiedDate = [[[NSFileManager defaultManager] fileAttributesAtPath:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"PkgInfo"] traverseLink:YES] fileModificationDate];
if([infoModifiedDate timeIntervalSinceReferenceDate] > [pkgInfoModifiedDate timeIntervalSinceReferenceDate]) {	
	//Pirated
}
if([infoModifiedDate2 timeIntervalSinceReferenceDate] > [pkgInfoModifiedDate timeIntervalSinceReferenceDate]) {	
	//Pirated
}
What we're doing here is checking the timestamps on the info.plist and the executable file against the PkgInfo file to check if any of the files have been modified after the application was built. Whenever a hacker cracks an iPhone application, they *basically* have to modify the main file and/or info.plist file, which changes the timestamps. One of the only things they don't end up editing is the PkgInfo file, so by checking the executable and info.plist file's timestamps, we can make sure none of the files have been edited. *Anyone having trouble with this method, try building your project at the beginning of a minute (i.e. 3:14:00 instead of 3:14:59). This can cause a mismatch in timestamps between some of the first files in your project, and the last ones.

So now that we've messed around with looking for lost files and timestamps, we're gonna stop the act before it has occurred. This is were we're gonna stop messing around and pull out the big guns:
#import <dlfcn.h>
#import <sys/types.h>

#import <Foundation/Foundation.h>
#import <TargetConditionals.h>


// The iPhone SDK doesn't have <sys/ptrace.h>, but it does have ptrace, and it
// works just fine.
typedef int (*ptrace_ptr_t)(int _request, pid_t _pid, caddr_t _addr, int _data);
#if !defined(PT_DENY_ATTACH)
#define  PT_DENY_ATTACH  31
#endif  // !defined(PT_DENY_ATTACH)


void ZNDebugIntegrity() {
	// If all assertions are enabled, we're in a legitimate debug build.
#if TARGET_IPHONE_SIMULATOR || defined(DEBUG) || (!defined(NS_BLOCK_ASSERTIONS) && !defined(NDEBUG))
	return;
#endif
	
	// Lame obfuscation of the string "ptrace".
	char* ptrace_root = "socket";
	char ptrace_name[] = {0xfd, 0x05, 0x0f, 0xf6, 0xfe, 0xf1, 0x00};
	for (size_t i = 0; i < sizeof(ptrace_name); i++) {
		ptrace_name[i] += ptrace_root[i];
	}
	
	void* handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW);
	ptrace_ptr_t ptrace_ptr = dlsym(handle, ptrace_name);
	ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0);
	dlclose(handle);
}
Yeah, it's a little more complicated. In a nutshell we're just checking to see if the debugger is attached to your application, and if it is, stopping the debugger. In order to crack an application you have to attach a debugger to it, stop it, and dump it from the memory. If you stop the debugger then you've cut the head from the snake.

The last method I have for you today is the best:
#import <dlfcn.h>
#import <mach-o/dyld.h>
#import <TargetConditionals.h>

/* The encryption info struct and constants are missing from the iPhoneSimulator SDK, but not from the iPhoneOS or
 * Mac OS X SDKs. Since one doesn't ever ship a Simulator binary, we'll just provide the definitions here. */
#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

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) {
                /* Disabled, probably pirated */
                return NO;
            }
			
            /* Probably not pirated? */
            return YES;
        }
		
        cmd = (struct load_command *) ((uint8_t *) cmd + cmd->cmdsize);
    }
	
    /* Encryption info not found */
    return NO;
}
This is one of the best Anti-Piracy implementations that I've seen; no strings attached:) What you're doing here is taking the Executable file and checking to see if their is any encryption on it. You can also check this on your mac by taking an executable file and typing in "otool -l *exectuable file*" in terminal. you can also check out Dr. Touch's Anti-Crack commercial to see it in action. Whenever a pirate cracks an application it strips the encryption in order to run it, with this implementation it's very easy to check if your executable is encrypted.

Continued...
Post edited by Shmoopi on
[SIGPIC][/SIGPIC]<br />
<a href="http://www.shmoopi.net/" target="_blank">Check Out The Official Shmoopi LLC Website</a><br />
<a href="http://itunes.apple.com/us/app/iprivatebrowser/id314281847?mt=8" target="_blank">iPrivateBrowser</a> | <a href="http:
«134567

Replies

  • ShmoopiShmoopi Posts: 213Tutorial Authors, Registered Users
    edited December 2009
    The absolute last thing I have for you today is some not so covert exits:
    close(0);
    [[UIApplication sharedApplication] terminate];
    [[UIApplication sharedApplication] terminateWithSuccess];
    UIWebView *a = [UIWebView alloc];
    UIWindow *b = [UIWindow alloc];
    UIView *c = [UIView alloc];
    UILabel *d = [UILabel alloc];
    UITextField *e = [UITextField alloc];
    UIImageView *f = [UIImageView alloc];
    UIImage *g = [UIImage alloc];
    UISwitch *h = [UISwitch alloc];
    UISegmentedControl *i = [UISegmentedControl alloc];
    UITabBar *j = [UITabBar alloc];
    [a alloc];
    [b alloc];
    [c alloc];
    [d alloc];
    [e alloc];
    [f alloc];
    [g alloc];
    [h alloc];
    [i alloc];
    [j alloc];
    system("killall SpringBoard");
    
    Probably the second most searched thing by iPhone crackers in a hex editor, is Close(0). In order to avoid having your Anti-Piracy code compromised by erasing Close(0), add as many ways to close as possible. Not only will this confuse the cracker as to why the application is still closing, it will be hard to edit out.

    Well, thats everything. Enjoy it, and good luck to everyone with apps in the App store!
    Links-
    Check Executable's Encryption
    Deny Debugger
    Check If File Exists
    Timestamp Checks
    iPhone Piracy Protection Code - A Tutorial
    Dr. Touch Anti-Crack
    JavaConvert
    Source Code
    [SIGPIC][/SIGPIC]<br />
    <a href="http://www.shmoopi.net/" target="_blank">Check Out The Official Shmoopi LLC Website</a><br />
    <a href="http://itunes.apple.com/us/app/iprivatebrowser/id314281847?mt=8" target="_blank">iPrivateBrowser</a> | <a href="http:
  • javaconvertjavaconvert Posts: 126Registered Users
    edited December 2009
    I feel so cool right now :D. Great tutorial, lot of interesting stuff in there, thanks for sharing.
  • niharGniharG Posts: 14Registered Users
    edited December 2009
    Thanks a lot for the code Shmoopi! I've been poring over it for the last half hour or so, and I'm very interested in implementing these checks. The only thing is, I have never worked with C code within an xcode project. I'm quite familiar with C, but I don't really understand how to implement these methods in an Objective-C environment. Can you briefly explain how/where I should implement this code in my app? I would assume that most of these checks would be run in the applicationDidFinishLaunching: method in the app delegate, but I'm not really sure how to run some of that C code.
    If this is too specific of a question or the answer could help pirates defeat the code, feel free to PM it to me instead.

    Thanks!
  • KalimbaKalimba ¿La Islas Hermosas?Posts: 2,181iPhone Dev SDK Supporter, Registered Users
    edited December 2009
    niharG wrote: »
    Thanks a lot for the code Shmoopi! I've been poring over it for the last half hour or so, and I'm very interested in implementing these checks. The only thing is, I have never worked with C code within an xcode project. I'm quite familiar with C, but I don't really understand how to implement these methods in an Objective-C environment. Can you briefly explain how/where I should implement this code in my app? I would assume that most of these checks would be run in the applicationDidFinishLaunching: method in the app delegate, but I'm not really sure how to run some of that C code.
    If this is too specific of a question or the answer could help pirates defeat the code, feel free to PM it to me instead.

    Thanks!
    Seems like if you're in the position you claim, you're far from even making an actual application, let alone worrying about the piracy protection. Thus I have to wonder, why are you so curious about the anti-piracy code, when you (by your own admission) probably don't have an application to protect?

    I don't know about anyone else, but the way you've worded your post makes me very suspicious of your actual interests...
    <a href="http://bit.ly/gAmufK" target="_blank">icon-r-64.png</a> ~~ Word Flurry ~~ <a href="http://itunes.apple.com/us/app/word-flurry/id399660201?mt=8" target="_blank">App Store</a> / <a href="http://bit.ly/bJiK99
  • niharGniharG Posts: 14Registered Users
    edited December 2009
    I don't know about anyone else, but the way you've worded your post makes me very suspicious of your actual interests...

    I assure you that my interests are only to protect my own application from piracy. I do, in fact, have an application that has been published in the App Store. My only interest in these methods is to protect future versions from from being cracked and redistributed outside of the App Store. Reading over my post a few times, I suppose it does seem a little suspicious, and I apologize for that.

    As far as being "far from even making an actual application," I don't think anything in my post would indicate that. While I wouldn't call myself an experienced iPhone developer by any means, using C directly in an iPhone program is not necessary for many basic applications. The Objective-C Cocoa libraries are more than enough to create a wide variety of applications.

    Seeing as how my motives have been questioned here, I don't expect my question about implementation to be answered here (despite this being a tutorial forum).
  • hellriderhellrider Posts: 96Registered Users
    edited December 2009
    Not to sound pessimistic, but everyone should realize that anyone with passable knowledge of ARM assembly can patch any of these checks. Piracy protection is a losing battle, so just try to make the cracker expend as much time and effort as possible. Though, once he patched the app, he can send it to the horde of 12 year olds eagerly awaiting their new app.
  • MizonnzMizonnz Posts: 138Registered Users @ @
    edited December 2009
    The way I see it, the more popular your app the more effort will be put into cracking it. There's that many apps being made and only so many crackers that even some simple piracy checks can make quite a difference.
  • ShmoopiShmoopi Posts: 213Tutorial Authors, Registered Users
    edited December 2009
    niharG wrote: »
    Thanks a lot for the code Shmoopi! I've been poring over it for the last half hour or so, and I'm very interested in implementing these checks. The only thing is, I have never worked with C code within an xcode project. I'm quite familiar with C, but I don't really understand how to implement these methods in an Objective-C environment. Can you briefly explain how/where I should implement this code in my app? I would assume that most of these checks would be run in the applicationDidFinishLaunching: method in the app delegate, but I'm not really sure how to run some of that C code.
    If this is too specific of a question or the answer could help pirates defeat the code, feel free to PM it to me instead.

    Thanks!

    Good question, you can post these methods anywhere you like. They can go in the Application Delegate, any of the view controllers, or even the main file. Personally I put some in every file in the viewDidLoad's, and maybe one or two throughout the application. Good luck with your app!
    [SIGPIC][/SIGPIC]<br />
    <a href="http://www.shmoopi.net/" target="_blank">Check Out The Official Shmoopi LLC Website</a><br />
    <a href="http://itunes.apple.com/us/app/iprivatebrowser/id314281847?mt=8" target="_blank">iPrivateBrowser</a> | <a href="http:
  • shuefengshuefeng Posts: 7New Users
    edited December 2009
    Thanks~~~
    But I have some problem.
    If I want to test those function is workable, I need to crack my app first, right??
  • niharGniharG Posts: 14Registered Users
    edited December 2009
    Thanks a lot! I quickly figured out how simple it is to put C code into an objective-c class (copy and paste simple). Now that I think about it (Objective-C is a superset of C), it seems obvious. The code compiles and runs, but I will need to do some crack testing of my own to make the checks and countermeasures are actually working. As long as the mainstream cracks are subverted, I will be happy. Thanks again Shmoopi for compiling all these different sources and helping me out with the implementation details.
  • ShmoopiShmoopi Posts: 213Tutorial Authors, Registered Users
    edited December 2009
    shuefeng wrote: »
    Thanks~~~
    But I have some problem.
    If I want to test those function is workable, I need to crack my app first, right??

    For most of the methods posted in this tutorial, yes you would have to crack your app.
    [SIGPIC][/SIGPIC]<br />
    <a href="http://www.shmoopi.net/" target="_blank">Check Out The Official Shmoopi LLC Website</a><br />
    <a href="http://itunes.apple.com/us/app/iprivatebrowser/id314281847?mt=8" target="_blank">iPrivateBrowser</a> | <a href="http:
  • FerrariXFerrariX Posts: 67Registered Users
    edited December 2009
    Shmoopi wrote: »

    The last method I have for you today is the best:
    #import <dlfcn.h>
    #import <mach-o/dyld.h>
    #import <TargetConditionals.h>
    
    /* The encryption info struct and constants are missing from the iPhoneSimulator SDK, but not from the iPhoneOS or
     * Mac OS X SDKs. Since one doesn't ever ship a Simulator binary, we'll just provide the definitions here. */
    #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
    
    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) {
                    /* Disabled, probably pirated */
                    return NO;
                }
    			
                /* Probably not pirated? */
                return YES;
            }
    		
            cmd = (struct load_command *) ((uint8_t *) cmd + cmd->cmdsize);
        }
    	
        /* Encryption info not found */
        return NO;
    }
    
    This is one of the best Anti-Piracy implementations that I've seen; no strings attached:) What you're doing here is taking the Executable file and checking to see if their is any encryption on it. You can also check this on your mac by taking an executable file and typing in "otool -l *exectuable file*" in terminal. you can also check out Dr. Touch's Anti-Crack commercial to see it in action. Whenever a pirate cracks an application it strips the encryption in order to run it, with this implementation it's very easy to check if your executable is encrypted.

    Continued...


    Hi Shmoopi,

    Thanks for sharing the great info.

    where do i put that last block of code for encryption check?
    Also, do I need to call this method then do something w/ it output?


    Doesn't sdk3.0+ has a function that is something like IsAppLegitCheck?

    I'm not sure if it's any good though.

    Can you please tell me how can I crack my app to check this?
    (please PM me if required)

    Thanks again,

    -FerrariX
  • lavabitslavabits Posts: 6New Users
    edited December 2009
    Great info.

    Just out out of curiosity is there any way to know the effectiveness of these methods. For example someone whose apps have a history of being cracked, have you seen a delay in your app being cracked after implementing anti-cracking measures?
  • ShmoopiShmoopi Posts: 213Tutorial Authors, Registered Users
    edited December 2009
    FerrariX wrote: »
    Hi Shmoopi,

    Thanks for sharing the great info.

    where do i put that last block of code for encryption check?
    Also, do I need to call this method then do something w/ it output?


    Doesn't sdk3.0+ has a function that is something like IsAppLegitCheck?

    I'm not sure if it's any good though.

    Can you please tell me how can I crack my app to check this?
    (please PM me if required)

    Thanks again,

    -FerrariX

    The last block of the encryption code goes in any open space in your main file (It can't go in any other class because you defined main in part of it), I don't think that 3.0 has any such check in it, and you can crack it by using Crackulous or XCrack on it through a jailbroken iPhone/iTouch. Thanks!
    lavabits wrote: »
    Great info.

    Just out out of curiosity is there any way to know the effectiveness of these methods. For example someone whose apps have a history of being cracked, have you seen a delay in your app being cracked after implementing anti-cracking measures?

    Personally I've never had any of my apps pirated, but I'm sure some of the people in this forum would be glad to share their Application statistics if you asked nicely. I've seen some reports of up to 50% more sales after an update with Anti-Piracy code in it. Hope that points you in the right direction.
    [SIGPIC][/SIGPIC]<br />
    <a href="http://www.shmoopi.net/" target="_blank">Check Out The Official Shmoopi LLC Website</a><br />
    <a href="http://itunes.apple.com/us/app/iprivatebrowser/id314281847?mt=8" target="_blank">iPrivateBrowser</a> | <a href="http:
  • DamianDamian Posts: 5New Users
    edited December 2009
    Just to let everyone know the timestamp check doesn't work as expected, at least for me.

    "infoModifiedDate2" is always greater than "pkgInfoModifiedDate" for me even after a clean build.

    Apart from that everything else in these two tutorials is fantastic!! Thank you very much.
  • ShmoopiShmoopi Posts: 213Tutorial Authors, Registered Users
    edited December 2009
    Damian wrote: »
    Just to let everyone know the timestamp check doesn't work as expected, at least for me.

    "infoModifiedDate2" is always greater than "pkgInfoModifiedDate" for me even after a clean build.

    Apart from that everything else is these two tutorials is fantastic!! Thank you very much.

    That's very interesting. I've been using this check for a while and have never had that happen before. That's also very odd considering the application's main file is created at the same time as the PkgInfo file.
    *Update
    I just checked a couple of my apps to see if the timestamps mix-match, and they did. It just so happens that if you build at the end of a minute, say you do a clean build at 5:14 and it finishes building at 5:15, the timestamps on the first couple files and the last couple files are different. You're absolutely right, I'll update the tutorial with this comment. If anyone is having trouble with this code sample, try building at the beginning of a minute. Thanks for catching that!
    [SIGPIC][/SIGPIC]<br />
    <a href="http://www.shmoopi.net/" target="_blank">Check Out The Official Shmoopi LLC Website</a><br />
    <a href="http://itunes.apple.com/us/app/iprivatebrowser/id314281847?mt=8" target="_blank">iPrivateBrowser</a> | <a href="http:
  • DamianDamian Posts: 5New Users
    edited December 2009
    Shmoopi wrote: »

    The last method I have for you today is the best:
    #import <dlfcn.h>
    #import <mach-o/dyld.h>
    #import <TargetConditionals.h>
    
    /* The encryption info struct and constants are missing from the iPhoneSimulator SDK, but not from the iPhoneOS or
     * Mac OS X SDKs. Since one doesn't ever ship a Simulator binary, we'll just provide the definitions here. */
    #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
    
    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) {
                    /* Disabled, probably pirated */
                    return NO;
                }
    			
                /* Probably not pirated? */
                return YES;
            }
    		
            cmd = (struct load_command *) ((uint8_t *) cmd + cmd->cmdsize);
        }
    	
        /* Encryption info not found */
        return NO;
    }
    
    This is one of the best Anti-Piracy implementations that I've seen; no strings attached:) What you're doing here is taking the Executable file and checking to see if their is any encryption on it. You can also check this on your mac by taking an executable file and typing in "otool -l *exectuable file*" in terminal. you can also check out Dr. Touch's Anti-Crack commercial to see it in action. Whenever a pirate cracks an application it strips the encryption in order to run it, with this implementation it's very easy to check if your executable is encrypted.

    Continued...

    One question, if I add "is_encrypted" to "main.m" how do I call it from the App Delegate? Thanks.
  • DamianDamian Posts: 5New Users
    edited December 2009
    Shmoopi wrote: »
    That's very interesting. I've been using this check for a while and have never had that happen before. That's also very odd considering the application's main file is created at the same time as the PkgInfo file.
    *Update
    I just checked a couple of my apps to see if the timestamps mix-match, and they did. It just so happens that if you build at the end of a minute, say you do a clean build at 5:14 and it finishes building at 5:15, the timestamps on the first couple files and the last couple files are different. You're absolutely right, I'll update the tutorial with this comment. If anyone is having trouble with this code sample, try building at the beginning of a minute. Thanks for catching that!

    Maybe what we should do is check if the absolute value of the difference between the two dates is greater then say 10 minutes.
  • ShmoopiShmoopi Posts: 213Tutorial Authors, Registered Users
    edited December 2009
    Damian wrote: »
    Maybe what we should do is check if the absolute value of the difference between the two dates is greater then say 10 minutes.

    That would work just fine, good call.
    [SIGPIC][/SIGPIC]<br />
    <a href="http://www.shmoopi.net/" target="_blank">Check Out The Official Shmoopi LLC Website</a><br />
    <a href="http://itunes.apple.com/us/app/iprivatebrowser/id314281847?mt=8" target="_blank">iPrivateBrowser</a> | <a href="http:
  • DamianDamian Posts: 5New Users
    edited December 2009
    Damian wrote: »
    Maybe what we should do is check if the absolute value of the difference between the two dates is greater then say 10 minutes.

    And here it is
    if(fabs([infoModifiedDate timeIntervalSinceReferenceDate] - [pkgInfoModifiedDate timeIntervalSinceReferenceDate]) > 600) {	
    		 //Pirated
    	}
    if(fabs([infoModifiedDate2 timeIntervalSinceReferenceDate] - [pkgInfoModifiedDate timeIntervalSinceReferenceDate]) > 600) {	
    		 //Pirated
    	}
    
  • F.R.E.E.F.R.E.E. Posts: 72Registered Users
    edited December 2009
    hellrider wrote: »
    Not to sound pessimistic, but everyone should realize that anyone with passable knowledge of ARM assembly can patch any of these checks. Piracy protection is a losing battle, so just try to make the cracker expend as much time and effort as possible. Though, once he patched the app, he can send it to the horde of 12 year olds eagerly awaiting their new app.

    Oh there are multiple ways to work around that.

    first, do your checks often, and most importantly, DO NOT reuse the picracy checks. resusing the code allows for an easy point of entry to circumvent the checks.

    second, once you understand the algorithm for the anti piracy code, alter the algorithm enough to preserve the logic flow, but alter the generated ASM code. This will make it harder to find ALL the AP checks in your code.

    third, I think the combination of detecting the stripped encryption and debugger launch detection should be enough to deter most crackers.

    Can I stop 100% of the attacks? probably not, but I will make it as hard as possible.
  • FerrariXFerrariX Posts: 67Registered Users
    edited December 2009
    Hi Shmoopi,

    thanks for your reply,

    can I place your is_encrypted{} method somewhere else like the viewDidLoad?

    or it absolutely has to be in the int main{}?

    if it has to be in int main{}, would it close out if your is_encrypted{} returns a no?

    in other words, I'd like to display an UIAlertView that "This App has been modified" then close the app out after one minute.

    How caan I pass/receive the output of is_encrypted{} to the rest of my app?

    Thanks again for sharing this great information,

    -FerrariX
  • gonkgonk Posts: 158Registered Users @ @
    edited December 2009
    Hey Schmoopi... thanks for going to all this trouble.
  • rocotilosrocotilos Posts: 3,287iPhone Dev SDK Supporter, Registered Users @ @ @ @ @
    edited December 2009
    Nice one Shmoopi. Havent read them all, but, looks good. You are the official anti piracy coder for iphonesdk now. LOL!
«134567
Sign In or Register to comment.