Hacking one Android application

    Recently, I intensively developed my application for Android, and in the process of protecting the paid version I realized that it is quite difficult to secure the application from hacking. For the sake of sports interest, I decided to try to remove ads from one free application in which it is proposed to hide the banner if you pay money through an In-App Purchase.


    In this article I will describe how I managed to remove ads for free and in the end - a few words about how to complicate the task of crackers.

    Step 1. Get the "readable" application code.
    To get the APK application from the phone, you need root privileges. We pull the application from the phone using adb (let us have a greatapp.apk application for conspiracy):
    adb pull /data/app/greatapp.apk

    Habrauser overmoveHe told me that root is optional, you can backup any application using Astro, and it will be copied to / mnt / sdcard.
    Habrauser MegaDiablo told me that Astro is optional. The list of installed applications and their apk files can be found through the utility pmin the shell, and when the file name is already known, it can be pulled through adb pull /data/app/app.filename.apk.

    APK is a ZIP archive, we get the file classes.dexwith the compiled code that interests us from there .
    We will use the smali / baksmali assembler / disassembler for our dirty deeds.
    java -jar baksmali-1.3.2.jar classes.dex

    At the output, we get the out directory with a bunch of files *.smali. Each of them corresponds to a file .class. Naturally, I don’t want everything obfuscated for the most, this directory looks like this:


    Let's try to understand where in this obfuscated heap "says" about advertising. At first I just did a search with the text " AdView" (View showing ads from the AdMob SDK) across all the files. Found himself AdView.smali, R$id.smaliand a certain one d.smali. AdView.smaliIt’s not very interesting to watch, R.$idI somehow ignored it at first, and immediately went into the mysterious d.smali.

    Step 2. Go the wrong way.
    Here is the method a()in the file d.smaliwith the first mention AdView(I decided it’s better to take a screenshot, otherwise it’s very sad to read without formatting):


    The method does not return anything, so without thinking twice, I decided to just insert it closer to the beginning return-void. When I put everything together and ran it, the application happily crashed. Log from adb logcat:

    E/AndroidRuntime(14262): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.greatapp/com.greatapp.GreatApp}: android.view.InflateException: Binary XML file line #22: Error inflating class com.google.ads.AdView

    It’s clear that ourAdViewas a result of manipulations, it was not properly created. Forget about it for now d.smali.

    Step 3. Roll back all the changes and look at the previously missed R$id. Here’s the line with AdView: It looks like this is the View identifier with ads. Let's search where it is used by doing a search by value . We get only two results: the same and . In GreatApp.smali, the text is already much more interesting (my comments): It can be seen that this identifier is used for search (line 588) and literally immediately the AdView is deleted from the screen (line 595). Apparently deleted if the user paid for the lack of advertising? If you look a little higher, your gaze clings to line 558 with the "keywords": robotmedia
    # static fields
    .field public static final adView:I = 0x7f080006


    0x7f080006R$idGreatApp.smali


    View
    invoke-static {v7, v8}, Lnet/robotmedia/billing/BillingController;->isPurchased(Landroid/content/Context;Ljava/lang/String;)Z

    - a third-party (open source) library, designed to simplify the work with in-app billing in android. Why wasn’t she completely obfuscated? Oh well, lucky.
    It can be seen that the method isPurchased()returns a string, which with the help is Boolean.valueOf()converted to a Boolean object and, finally, to a regular booleanone through booleanValue().
    And here the most interesting thing, in line 572 we go to a certain one :cond_32, if the value of the result == false. Otherwise, the already searched search and delete code begins AdView.

    Step 4. Minimum change, assemble and run.
    Well, the case for small - to remove this key string, collect application and immediately To install the phone: (
    java -jar ..\smali\smali-1.3.2.jar ..\smali\out -o classes.dex
    apkbuilder C:\devel\greatapp\greatapp_cracked.apk -u -z C:\devel\greatapp\greatapp_noclasses.apk -f C:\devel\greatapp\classes.dex
    jarsigner -verbose -keystore my-release-key.keystore -storepass testtest -keypass testtest greatapp_cracked.apk alias_name
    adb install greatapp_cracked.apk


    greatapp_noclasses.apk- this is the original APK of the application from which classes.dex is removed, certificates are created using the Android SDK).
    And hurray, run the application, no ads!

    Now about how to complicate the task for freebie fans (this is just what I remembered from the video about piracy with Google IO 2011, link below):
    • Do not verify payment or licensing in Activity classes, and especially onCreate () methods and the like. These "entry points" are always started at a certain time and are not obfuscated, you can always look at them and understand what happens with the various elements of the UI
    • It’s best to check not in the main thread and at random times
    • Check CRC file classes.dex, and store it encrypted
    • Keep the license or purchase verification code compiled and encrypted as an application resource, dynamically download and run it through reflection


    I hope it was interesting. In conclusion, a few useful links on the topic:

    Also popular now: