views:

9521

answers:

5

How do you determine (programatically) if an iPhone/iPod is:

  1. Jail broken
  2. Running a cracked copy of your software

Pinch Media can detect if a phone is jail broken or the software running is cracked, does anyone know how they do this? Are there any libraries?

+14  A: 

Here is one of the ways to detect if your app was cracked: http://thwart-ipa-cracks.blogspot.com/2008/11/detection.html

In short: the cracking usually requires changing the Info.plist. Since it's regular file you have access to, it's pretty easy to determine such changes.

zakovyrya
Unfortunately, there's a workaround that breaks this detection mechanism. Once the app is installed, the SignerIdentity key is no longer necessary, so the cracker can simply ssh into their jailbroken phone and edit the plist to remove it.
Kevin Ballard
All piracy-prevention methods are always going to be an arms race. If you can make a security mechanism, someone else can make a way to beat it. The top anti-cracking experts in the games industry acknowledge this; they state that their goal is not to eliminate cracking, which will never happen, but to 1) raise the bar of difficulty for cracking to make it less worth the trouble of performing, and 2) eliminate day-1 cracks - in other words extend the delta of time between a game's release and a game being cracked to be as long as possible. This is the only sane attitude towards cracking.
IQpierce
+11  A: 

Detecting a jailbroken phone is as easy as checking for the presence of /private/var/lib/apt/ folder. Although this doesn't detect Installer-only users, by now most have have installed Cydia, Icy or RockYourPhone (all of which use apt)

To detect pirated users, the easiest way is to check for the presence of a SignerIdentity key in your app's Info.plist. Since advanced crackers can easily find the standard [[[NSBundle mainBundle] infoDictionary] objectForKey: @"SignerIdentity"] checks, it is best to obscure these calls using the Objective C runtime available via #import <objc/runtime.h> or use alternative equivalents.

rpetrich
+6  A: 

Just to expand on zakovyrya's reply, you could use the following code:

if ([[[NSBundle mainBundle] infoDictionary] objectForKey: @"SignerIdentity"] != nil) {
  // Jailbroken
}

HOWEVER, the person jailbreaking your app can hexedit your program and as such, they could edit the string @"SignerIdentity" to read @"siNGeridentity" or something else which would return nil, and thus pass.

So if you use this (or any of the other suggestions from http://thwart-ipa-cracks.blogspot.com/2008/11/detection.html):

  • Don't expect it to work forever
  • Don't use this information to break/hinder your app in any way (otherwise they'll have cause to hexedit it, so your app won't know it is jailbroken)
  • Probably wise to obfuscate this bit of the code. For example, you could put the base64 encoded reversed string in your code, and then decode it in the app by reversing the process.
  • Validate your validation later in your code (e.g. when I said SignerIdentity, did it actually say SignerIdentity or siNGeridentity?)
  • Don't tell people on a public website like stackoverflow how you do it
  • Keep in mind it is only a guide and is not fool-proof (nor cracker-proof!) - with great power comes great responsibility.
Benjie Gillam
A: 

I'm trying to figure out how to protect my app from cracking. I know the story behind the SignerIdentity, however, when I looked at the cracked IPA of my app, I don't see the SignerIdentity in the info.plist. I've seen here that the SignerIdentity presence does not seem to be required anymore to run a cracked app :

http://www.theiphonespot.net/2009/09/07/c4syncapp-the-next-level-in-iphone-cracking/

Morever, it looks like if http://www.install0us.com does not requires the info.plist to be changed, so how can we detect the crack in such a case ? :(

So , in that case, what is the way to detect a cracked app ?

yonel
Check the cryptid. That always works. Always.
chpwn
Thanks for the hint, I'll have a look at this one.
yonel
I juste have found this page that refers to cryptid: http://www.iphonedevsdk.com/forum/iphone-sdk-tutorials/36330-iphone-piracy-protection-code-2-another-tutorial.htmlWhat it seems to do : /* Fetch the dlinfo for main() *//* Compute the image size and search for a UUID *//* Encryption info segment *//* Check if binary encryption is enabled */Is that what you're referring to ? In case you have another "better" page that explains the underlying mechasnims don't hesite to post ... :/
yonel
I think I found a code that checks the crypt part of the application : http://landonf.bikemonkey.org/code/iphone/iPhone_Preventing_Piracy.20090213.html However, as this is not part of the public SDK doc, I wonder how safe it is to use it (side effect could that at some stage, this assumption changes and is not reliable anymore, creating side effect for "paid" users.... :( )
yonel
+2  A: 

To expand on yonel's and Benjie's comments above:

1) Landon Fuller's method relying on encryption check, linked above by yonel, seem to be the only one still not defeated by automated cracking tools. I would not be overly worried about Apple changing the state of the LC_ENCRYPTION_INFO header any time soon. It does seem to have some unpredictable effects on jailbroken iphones (even when the user has purchased a copy...)

At any rate, I would not take any rash action against a user based on that code...

2) To complement Benjie's comment re. obfuscation (an absolute necessity when dealing with any string values in your anti-piracy code): a similar but perhaps even easier way is to always check a salted *hashed* version of the value you are looking for. For example (even though that check is no longer efficient), you would check each MainBundle's key name as md5(keyName + "some secret salt") against the appropriate constant... Rather basic, but sure to defeat any attempt at locating the string.

Of course, this requires you to be able to indirectly query the value you want to compare (for example by going through an array containing it). But this is most often the case.

Dave