zima url shortening Official 'Cool Guy'

Categories

Tags

Blogroll

Download OPML file OPML

Fighting AppStore Piracy with MonoTouch

So you've got the great MonoTouch SDK that's letting you write C# code on your iPhone. You thought of the coolest app ever in the world, you put it out in the AppStore - you see lots of activity on the REST API that you built it on; but your AppStore stats don't seem to match up. WTF?!? You're thinking well looks like your app has become a victim of piracy. With Apple and all of it's infinite wisdom decided that all that was really needed to protect iPhone apps was their DRM, because the iPhone OS is secure :) Well the problem with that of course is that the iPhone OS isn't secure and it's very easy to write programs to exploit the fact that the DRM is removed by the device itself when the app goes to run. In an over simplified version of how to crack an app on the iPhone, when the iPhone app is ran it's loaded into memory and then decrypted, well the cracking program simply dumps the contents of the memory, then the header on the app is changed to decrypted (instead of the default encrypted). Voila! DRM Free app easy as 1-2-3. So there are some things that you can do to prevent debuggers and such from running while your app is executing; but those are all pretty advanced concepts. What I wanted to present with this blog is some easy to implement bigger style iPhone app protection.

So lets examine the constants between all pirated iPhone applications (this actually only applies to the current batch of pirated iPhone apps a few of these things have been addressed by one iPhone cracker; but no cracking applications support his new protocols).

MODIFICATIONS TO THE INFO.PLIST FILE

Checking the Info.plist file is the most common way to see if an application has been pirated. It contains essential configuration information for a bundled executable.

Information about the Info.plist (known as Information Property List File) can be obtained here.

The Info.plist file has to be modified so the resulting cracked .ipa can be installed on the iDevice. For that the key-pair {SignerIdentity, Apple iPhone OS Application Signing} is added to it.

In that process the Info.plist is converted from binary to plaintext XML and the key-pair is added.

So we have many options to check the Info.plist:

a) The size of Info.plist:

b) The date it was created or changed

c) If Info.plist is plaintext XML:

d) For the keypair key-pair {SignerIdentity, Apple iPhone OS Application Signing}

I am providing some sample MonoTouch code for checking options C/D please note that these should not be used in a commercial AppStore application, this is merely a proof of concept of protecting your code with MonoTouch. First any strings that reference Info.plist should be obfuscated (doing this will make it harder for the cracker to simply search for this string and patch)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

            
public bool IsInfoplistPlainText()
{
//        The Info.plist file has to be modified so the resulting cracked .ipa can be installed on the iDevice. 
//        For that the key-pair {SignerIdentity, Apple iPhone OS Application Signing} is added to it. In that process the 
//        Info.plist is converted from binary to plaintext XML and the key-pair is added. 
//                c) If Info.plist is plaintext XML:
var basedir = Path.Combine (Environment.GetFolderPath (System.Environment.SpecialFolder.Personal), "..");
string appName = "ApplicationName.app";
try
{
XmlDocument doc = new XmlDocument();
string xmlFile = (basedir + "/" + appName + "/info.plist");
XmlTextReader reader = new XmlTextReader(xmlFile);
doc.Load(reader);return true; } catch { return false; } }
Pastie #627949 linked directly from Pastie.


This next example is checking for the key signer pair that must be added to all cracked apps, again this shouldn't be used as is in any commercial application; any strings should be obfuscated & this also shows the technique of not using standard coding practices to deal with xml, more likely to throw off the would be cracker :)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

            
public bool InfoplistSignerKeyPairExists ()
{
//        The Info.plist file has to be modified so the resulting cracked .ipa can be installed on the iDevice. 
//        For that the key-pair {SignerIdentity, Apple iPhone OS Application Signing} is added to it. In that process the 
//        Info.plist is converted from binary to plaintext XML and the key-pair is added. So there are many options to 
//        check the Info.plist:
//                a) The size of Info.plist: mostly done using NSFileSize
//                b) The date it was created or changed
//                c) If Info.plist is plaintext XML:
//                d) For the keypair key-pair {SignerIdentity, Apple iPhone OS Application Signing}
var basedir = Path.Combine (Environment.GetFolderPath (System.Environment.SpecialFolder.Personal), "..");
string appName = "ApplicationName.app";
string xmlFile = (basedir + "/" + appName + "/info.plist");
TextReader tr = new StreamReader(xmlFile);
string filecontents = tr.ReadToEnd ();if (filecontents.IndexOf ("SignerIdentity") >= 0) { if (filecontents.IndexOf ("Apple iPhone OS Application Signing") >=0 ) { return true; } else { return false; } } else { return false; } }
Pastie #627951 linked directly from Pastie.

REMOVING OF THE ITUNESMETADATA.PLIST

The iTunesMetadata.plist is removed because it contains information about the person who bought the app (Name, AppStore account info, ...). We only has to check if the file exists and the application will know if it’s a valid or pirated version. The code is uber simple :)


    
public bool iTunesMetaDataExists ()
{
//        In pirated apps the iTunesMetadata.plist is removed because it contains information about the person who bought the app 
//        (Name, AppStore account info, …). So a simple check for this file would be one indicator if it was valid install or not
//        NOTE: The String "iTunesMetaData.plist" should be obsfucated to prevent tampering
var basedir = Path.Combine (Environment.GetFolderPath (System.Environment.SpecialFolder.Personal), "..");return File.Exists (basedir + "/iTunesMetaData.plist"); }
Pastie #627956 linked directly from Pastie.

PRESENCE OF THE _CODESIGNATURE FOLDER AND CODERESOURCES

Every legit app has a folder called _CodeSignature with a file named CodeResources in it. It is removed because it might contain information about the buyer. Again we can easily check if the folder and/or the file exist.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

            
public bool CodeSignatureFolderExists ()
{
//        Every legit app has a folder _CodeSignature in the AppName.app Bundle
//        However this folder is removed in pirated apps, because it may contain information about the buyer
//        NOTE: The String "_CodeSignature" should be obsfucated to prevent tampering
var basedir = Path.Combine (Environment.GetFolderPath (System.Environment.SpecialFolder.Personal), "..");
return Directory.Exists(basedir + "/" + appName + "/_CodeSignature");
}
public bool CodeResourcesFileExists ()
{
// Every legit app has a file CodeResources in the folder _CodeSignature in the AppName.app Bundle
// However this file is removed in pirated apps, because it may contain information about the buyer
// NOTE: The String "CodeResources" should be obsfucated to prevent tampering
var basedir = Path.Combine (Environment.GetFolderPath (System.Environment.SpecialFolder.Personal), "..");
if ( CodeSignatureFolderExists () )
return File.Exists (basedir + "/" + appName + "/_CodeSignature/CodeResources");
else
return false; }
Pastie #627962 linked directly from Pastie.

CRYPTID: LC_ENCRYPTION_INFO

This is the most advanced check (at least for AppStore applications). We have already learned that in order to remove Apple’s DRM the decrypted binary (except the header) is dumped from the RAM. Then the encrypted part (the header is never encrypted) of the original binary is replaced with the dumped data. Finally, the cryptID in the header is changed from 1 (encrypted) to 0 (decrypted). What we do then is check if the cryptID is 0. For example they open the binary and start checking for the cryptID at 0x1000 upwards. This is one technique not isn't widely used from I can tell so I will not be posting any code samples as I do not want to encourage crackers to add this to their arsenal of defeated checks. If you want to dig deeper take a look at the Mach-O file format reference here.

September 23, 2009 07:52 by martin bowling
E-mail | Permalink | Comments (1) | Comment RSSRSS comment feed

Related posts

Comments

November 16. 2009 22:36

pingback

Pingback from viperchill.com

Definitive Guide to Becoming Likeable Online

viperchill.com

Comments are closed