Advertise Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

sdkIQ for iPhone
($4.99)

Your First iPhone App
($1.99)

iPhone Code Generator
($9.99)

Dual Matches
($0.99)

Calcuccino Programmers' Calculator
($2.99)

SDKtoday
(free)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Tutorials

Reply
 
LinkBack Thread Tools Display Modes
Old 12-22-2009, 06:35 PM   #1 (permalink)
Shmoopi Gaming
 
Shmoopi's Avatar
 
Join Date: Jun 2009
Posts: 183
Lightbulb iPhone Piracy Protection Code 2 - Another Tutorial

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:
Code:
#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:
Code:
#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:
Code:
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:
Code:
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:
Code:
#import 
#import 

#import 
#import 


// The iPhone SDK doesn't have , 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:
Code:
#import 
#import 
#import 

/* 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...
__________________
Check out Shmoopi Gaming in the App Store!

Last edited by Shmoopi; 12-29-2009 at 04:29 PM.
Shmoopi is offline   Reply With Quote
Old 12-22-2009, 06:36 PM   #2 (permalink)
Shmoopi Gaming
 
Shmoopi's Avatar
 
Join Date: Jun 2009
Posts: 183
Default Continued...

The absolute last thing I have for you today is some not so covert exits:
Code:
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
__________________
Check out Shmoopi Gaming in the App Store!

Last edited by Shmoopi; 12-22-2009 at 06:42 PM.
Shmoopi is offline   Reply With Quote
Old 12-22-2009, 07:19 PM   #3 (permalink)
Registered Member
 
Join Date: May 2009
Posts: 72
Default

thanks!
F.R.E.E. is offline   Reply With Quote
Old 12-24-2009, 01:28 AM   #4 (permalink)
Registered Member
 
Join Date: Sep 2009
Posts: 126
Default

I feel so cool right now . Great tutorial, lot of interesting stuff in there, thanks for sharing.
javaconvert is offline   Reply With Quote
Old 12-28-2009, 01:06 PM   #5 (permalink)
Registered Member
 
Join Date: Jul 2009
Location: Champaign, IL
Age: 19
Posts: 14
Default

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!
niharG is offline   Reply With Quote
Old 12-28-2009, 02:21 PM   #6 (permalink)
Pro. Game Developer
iPhone Dev SDK Supporter
 
Join Date: Feb 2009
Location: żLa Islas Hermosas?
Posts: 1,669
Default

Quote:
Originally Posted by niharG View Post
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...
__________________
Have I helped you? Say thanks here.

kalimba interactive
Kalimba is offline   Reply With Quote
Old 12-28-2009, 02:36 PM   #7 (permalink)
Registered Member
 
Join Date: Jul 2009
Location: Champaign, IL
Age: 19
Posts: 14
Default

Quote:
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).
niharG is offline   Reply With Quote
Old 12-28-2009, 03:46 PM   #8 (permalink)
Registered Member
 
Join Date: Jul 2009
Posts: 96
Default

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.
hellrider is offline   Reply With Quote
Old 12-28-2009, 04:22 PM   #9 (permalink)
Registered Member
 
Join Date: Nov 2009
Posts: 37
Default

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.
Mizonnz is offline   Reply With Quote
Old 12-28-2009, 05:27 PM   #10 (permalink)
Shmoopi Gaming
 
Shmoopi's Avatar
 
Join Date: Jun 2009
Posts: 183
Default

Quote:
Originally Posted by niharG View Post
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!
__________________
Check out Shmoopi Gaming in the App Store!

Last edited by Shmoopi; 12-28-2009 at 05:38 PM.
Shmoopi is offline   Reply With Quote
Old 12-28-2009, 11:48 PM   #11 (permalink)
Registered Member
 
Join Date: Oct 2009
Posts: 7
Default

Thanks~~~
But I have some problem.
If I want to test those function is workable, I need to crack my app first, right??
shuefeng is offline   Reply With Quote
Old 12-29-2009, 01:08 AM   #12 (permalink)
Registered Member
 
Join Date: Jul 2009
Location: Champaign, IL
Age: 19
Posts: 14
Default

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.
niharG is offline   Reply With Quote
Old 12-29-2009, 08:43 AM   #13 (permalink)
Shmoopi Gaming
 
Shmoopi's Avatar
 
Join Date: Jun 2009
Posts: 183
Default

Quote:
Originally Posted by shuefeng View Post
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.
__________________
Check out Shmoopi Gaming in the App Store!
Shmoopi is offline   Reply With Quote
Old 12-29-2009, 11:18 AM   #14 (permalink)
Registered Member
 
Join Date: Jun 2009
Posts: 59
Question

Quote:
Originally Posted by Shmoopi View Post

The last method I have for you today is the best:
Code:
#import 
#import 
#import 

/* 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
FerrariX is offline   Reply With Quote
Old 12-29-2009, 11:54 AM   #15 (permalink)
Registered Member
 
lavabits's Avatar
 
Join Date: Dec 2009
Location: Orlando
Posts: 6
Default

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?
__________________

AirPianoBreathMeter
lavabits is offline   Reply With Quote
Old 12-29-2009, 03:03 PM   #16 (permalink)
Shmoopi Gaming
 
Shmoopi's Avatar
 
Join Date: Jun 2009
Posts: 183
Default

Quote:
Originally Posted by FerrariX View Post
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!

Quote:
Originally Posted by lavabits View Post
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.
__________________
Check out Shmoopi Gaming in the App Store!
Shmoopi is offline   Reply With Quote
Old 12-29-2009, 03:58 PM   #17 (permalink)
Registered Member
 
Join Date: Jan 2009
Location: Dublin
Posts: 5
Default File Timestamps Check doesn't work as Expected

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.

Last edited by Damian; 12-29-2009 at 04:09 PM.
Damian is offline   Reply With Quote
Old 12-29-2009, 04:22 PM   #18 (permalink)
Shmoopi Gaming
 
Shmoopi's Avatar
 
Join Date: Jun 2009
Posts: 183
Default

Quote:
Originally Posted by Damian View Post
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!
__________________
Check out Shmoopi Gaming in the App Store!
Shmoopi is offline   Reply With Quote
Old 12-29-2009, 04:23 PM   #19 (permalink)
Registered Member
 
Join Date: Jan 2009
Location: Dublin
Posts: 5
Default

Quote:
Originally Posted by Shmoopi View Post

The last method I have for you today is the best:
Code:
#import 
#import 
#import 

/* 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.
Damian is offline   Reply With Quote
Old 12-29-2009, 04:27 PM   #20 (permalink)
Registered Member
 
Join Date: Jan 2009
Location: Dublin
Posts: 5
Default

Quote:
Originally Posted by Shmoopi View Post
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.
Damian is offline   Reply With Quote
Old 12-29-2009, 04:31 PM   #21 (permalink)
Shmoopi Gaming
 
Shmoopi's Avatar
 
Join Date: Jun 2009
Posts: 183
Default

Quote:
Originally Posted by Damian View Post
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.
__________________
Check out Shmoopi Gaming in the App Store!

Last edited by Shmoopi; 12-30-2009 at 03:54 PM.
Shmoopi is offline   Reply With Quote
Old 12-29-2009, 04:45 PM   #22 (permalink)
Registered Member
 
Join Date: Jan 2009
Location: Dublin
Posts: 5
Default

Quote:
Originally Posted by Damian View Post
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
Code:
if(fabs([infoModifiedDate timeIntervalSinceReferenceDate] - [pkgInfoModifiedDate timeIntervalSinceReferenceDate]) > 600) {	
		 //Pirated
	}
if(fabs([infoModifiedDate2 timeIntervalSinceReferenceDate] - [pkgInfoModifiedDate timeIntervalSinceReferenceDate]) > 600) {	
		 //Pirated
	}
Damian is offline   Reply With Quote
Old 12-29-2009, 07:40 PM   #23 (permalink)
Registered Member
 
Join Date: May 2009
Posts: 72
Default

Quote:
Originally Posted by hellrider View Post
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.
F.R.E.E. is offline   Reply With Quote
Old 12-30-2009, 09:16 AM   #24 (permalink)
Registered Member
 
Join Date: Jun 2009
Posts: 59
Question

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
FerrariX is offline   Reply With Quote
Old 12-30-2009, 09:56 AM   #25 (permalink)
Registered Member
 
Join Date: Nov 2008
Posts: 96
Default

Hey Schmoopi... thanks for going to all this trouble.
gonk is offline   Reply With Quote
Reply

Bookmarks

Tags
debugger, iphone, piracy, prevention, protection

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is On
Trackbacks are On
Pingbacks are On
Refbacks are On


» Advertisements
» Online Users: 379
23 members and 356 guests
AdamSubach, anonymous@, benoitr007, bensj, Danneman, Duncan C, gtyt38, gustavo7sexton, Jeremy1026, lifeCoder45, maxus182, mox, Ovidius, Paul10, pofak, raheel, Sega dude, squidboy, timle8n1, ufbobbo, ultrayard077
Most users ever online was 965, 06-30-2010 at 04:26 AM.
» Stats
Members: 41,860
Threads: 49,768
Posts: 213,052
Top Poster: BrianSlick (3,138)
Welcome to our newest member, gustavo7sexton
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 06:51 PM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0