Saturday, March 30, 2013

Plague Inc

Synopsis:
---------

Most of my other tutorials deal with registration schemes, and manual ad removal. There's other reasons to reverse software. Let's take for example a game called Plague Inc. I bought this game, and enjoyed playing it while the novelty lasted. One aspect of the game is that they have a lot of unlockable perks, and buyable game types. For shits and giggles, I decided it'd be fun to figure out to see if I could unlock all unlockables and get all game types.


Tools Needed:
-------------

* An android device or emulator with a functional adb connection (ADB setup beyond scope of this tutorial)
* UNIX or unix-like environment with apktool (Use deprecated version 1.4.1)
    (Note: apktool no longer works with baksmali, so you have to use an older version.)
* JDK 1.6
                (Note: 1.7 can be used, but there's an issue with a change of algorithm with the jarsigner, which causes some unneccessary difficulties, namely a "NO_CERTIFICATE_EXISTS" error upon APK installation)

Java 1.7:
---------

Key Creation:
        keytool -genkey -v -keystore testing.keystore -alias testing -keyalg RSA -keysize 2048 -validity 10000

APK Signing:
        jarsigner -verbose -keystore /home/ben/testing.keystore -digestalg SHA1 -sigalg MD5withRSA test.apk testing

Retrieval of APK From Device:
-----------------------------

You first need to establish your adb bridge, make sure your device shows up when you type:
        adb devices

The name of the apk is:
        com.miniclip.plagueinc-1.apk

I'm not sure if that hyphen naming notation is specific to Cyanogenmod or what, but it might be called:
        com.miniclip.plagueinc.apk

With most setups, you should be able to type the following to get the APK:
        adb pull /data/app/com.miniclip.plagueinc-1.apk

So now you have com.miniclip.plagueinc-1.apk in your current directory.


Unbundling:
-----------

First off type:
        apktool

If this gives you command not found, go look up how to do install apktool.


In the directory that contains the target APK file, type the following:
        apktool d com.miniclip.plagueinc-1.apk work


This unbundles an APK into its own directory called 'work'

Go into the 'work' directory, and check out the following tree:

res/   - This directory is where all resources (images, layouts, etc) live.
smali/ - This directory is where disassembled java files go.

Unlockable Discovery:
---------------------

Plague Inc's source files were unobfuscated, and pretty easy to follow. If you look at the application's main activity:
        smali/com/miniclip/plagueinc/PlagueIncActivity.smali


You'll see a lot of references to com/miniclip/nativeJNI, when you look at this directory, you'll see a ton of cocojava classes, with a lot of dollar signs and numbers afterwards. This is a telltale sign of a singleton design. Opening up the cocojava.smali, you start to see some interesting items:

.field public static mTEST_INAPPS:Z

.field protected static mUSE_ADS:Z


I like seeing 'test' in things because often times there's development code left over in applications that allow you to do things most would not allow you to do. I grepped for the use of mTEST_INAPPS, and found a couple of instances:


ben@localdev:~/plagueinc/work/com.miniclip.plagueinc-1/smali/com/miniclip$ grep -R "mTEST_INAPPS" *
nativeJNI/cocojava.smali:.field public static mTEST_INAPPS:Z
nativeJNI/cocojava.smali:    sput-boolean v2, Lcom/miniclip/nativeJNI/cocojava;->mTEST_INAPPS:Z
nativeJNI/cocojava$30.smali:    sget-boolean v0, Lcom/miniclip/nativeJNI/cocojava;->mTEST_INAPPS:Z
nativeJNI/cocojava$29.smali:    sget-boolean v0, Lcom/miniclip/nativeJNI/cocojava;->mTEST_INAPPS:Z
plagueinc/PlagueIncActivity.smali:    sput-boolean v12, Lcom/miniclip/plagueinc/PlagueIncActivity;->mTEST_INAPPS:Z


Ok, so checking out nativeJNI/cocojava$30.smali, I see the following code structure:

   .line 2016  
   :cond_0  
   sget-boolean v0, Lcom/miniclip/nativeJNI/cocojava;->mTEST_INAPPS:Z  
   if-eqz v0, :cond_1  
   .line 2017  
   sget-object v0, Lcom/miniclip/nativeJNI/cocojava;->mContext:Landroid/content/Context;  
   check-cast v0, Lcom/miniclip/nativeJNI/InAppActivity;  
   const-string v1, "android.test.purchased"  
   invoke-virtual {v0, v1}, Lcom/miniclip/nativeJNI/InAppActivity;->requestPurchaseAct(Ljava/lang/String;)V  
   goto :goto_0  
   .line 2019  
   :cond_1  
   sget-object v0, Lcom/miniclip/nativeJNI/cocojava;->mContext:Landroid/content/Context;  




Basically, it's taking the value of this mTEST_INAPPS, if it's 0, it skips a section of code that calls a purchase with a string argument of "android.test.purchased". I want to do this always, so I'm just going to remove the if-eqz which triggers the jump.

Now on to the nativeJNI/cocojava$29.smali:

   .line 1991  
   :cond_0  
   sget-boolean v0, Lcom/miniclip/nativeJNI/cocojava;->mTEST_INAPPS:Z  
   if-eqz v0, :cond_1  
   .line 1992  
   sget-object v0, Lcom/miniclip/nativeJNI/cocojava;->mContext:Landroid/content/Context;  
   check-cast v0, Lcom/miniclip/nativeJNI/InAppActivity;  
   const-string v1, "android.test.purchased"  
   invoke-virtual {v0, v1}, Lcom/miniclip/nativeJNI/InAppActivity;->requestPurchaseActManaged(Ljava/lang/String;)V  
   goto :goto_0  
   .line 1994  
   :cond_1  



Same exact structure, let's go ahead and remove that if-eqz as well. Your job is now done, all doors are now open. A better way to do this would have been to modify the value in the cocojava object.


Rebundling:

You can rebundle the APK by using apktool against the extracted directory

For instance if you have this directory tree:
        com.miniclip.plagueinc-1
        |_ smali
  |_ res
        |_ assets

your directory is com.miniclip.plagueinc-1

You then run the following:
        apktool b com.miniclip.plagueinc-1 hacked.apk

This packages the APK back up. You need to sign it with jarsigner (see signing section) before you can install it by typing:
        adb install hacked.apk

8 comments:

  1. Hi, I followed your tutorial on how to patch the Mobisystem dictionaries, but the files we need to patch are not there anymore. I think they may have changed their structure to make it harder for us to patch. Do you know of any other workaround?

    Thank you! I think your work is amazing ;-)

    ReplyDelete
  2. My mother is visually impaired, bought her a cell phone, but applications for accessibility are very expensive, gives the price of the phone if I buy all. I wonder if you can crack these apps: NNS-1 SLEP (Scanner Leitor Portátil, Tandera Launcher, Mobile Accessibility PT. Someone can help ... If you know any person or sites that crack android apps? albertobruno2003@ig.com.br

    ReplyDelete
  3. I play a few different Mobage games such as Rage of Bahamut and Marvel War of Heroes, which are server based games. In order to really get any good cards or items you have to purchase Mobacoins from Mobage as an in-app purchase. Would you happen to know a way to override the Mobacoin purchase and open up the virtual store to freely acquire items? The Smali code looks similar to that of your Plague game here but, being a coding novice, I really don't know what I am looking at. I have all of the Smali files for your reference if you are up for the challenge. Thanks, Jason

    ReplyDelete
  4. Please keep upload your tutorials. Thanks

    ReplyDelete
  5. Hi, can you try cracking "dummysprite" app?

    ReplyDelete
  6. Hi
    Why dont you continue your great job?
    The diffrence of your tuts and others is that you show how to approach the goal.
    Please make more tuts.
    Waiting....

    ReplyDelete