Hesam
Hesam

Reputation: 53600

Android, what Proguard exactly does?

I'm using Proguard to obfuscate my code. So, I activate it in project.propertise file.

After that I decompiled the APK file by apktool.

There are three items in decompiled file, res, smali and AndroidManifest. In res folder I can see my images clearly :) In smali, It's not easy to understand but I still can find my code. it is something like this:

.method public static u()Ljava/lang/String;
    .locals 1

    const/4 v0, 0x1

    packed-switch v0, :pswitch_data_0

    const-string v0, "https://uat.somewhere.com/ebroking/wecos/mobiletrader/aboutus.html"

    :goto_0
    return-object v0

    :pswitch_0
    const-string v0, "https://www2.somewhere.com/ebroking/wecos/mobiletrader/aboutus.html"

    goto :goto_0

    :pswitch_data_0
    .packed-switch 0x1
        :pswitch_0
    .end packed-switch

If I go to package name (activities), there are several files like a.smali, aa.smali, ab.smali, ac.smali and etc. Also, in this folder I can see all of my activities. For example, in my app I have an activity called MSAboutUs. in smali folder its name is MSAboutUs.smali. When i open it i can see following codes:

    .class public Lcom/pbb/mystock/activities/MSAboutUs;
.super Lcom/pbb/mystock/activities/ay;


# instance fields
.field private j:Landroid/widget/Button;

.field private k:Landroid/webkit/WebView;


# direct methods
.method public constructor <init>()V
    .locals 0

    invoke-direct {p0}, Lcom/pbb/mystock/activities/ay;-><init>()V

    return-void
.end method


# virtual methods
.method public onCreate(Landroid/os/Bundle;)V
    .locals 3

    invoke-super {p0, p1}, Lcom/pbb/mystock/activities/ay;->onCreate(Landroid/os/Bundle;)V

    const v0, 0x7f030004

    invoke-virtual {p0, v0}, Lcom/pbb/mystock/activities/MSAboutUs;->setContentView(I)V

    const-string v0, ""

    const-string v1, "Loading..."

    const/4 v2, 0x1

    invoke-static {p0, v0, v1, v2}, Landroid/app/ProgressDialog;->show(Landroid/content/Context;Ljava/lang/CharSequence;Ljava/lang/CharSequence;Z)Landroid/app/ProgressDialog;

    move-result-object v0

    iput-object v0, p0, Lcom/pbb/mystock/activities/MSAboutUs;->a:Landroid/app/ProgressDialog;

    const v0, 0x7f060008

    invoke-virtual {p0, v0}, Lcom/pbb/mystock/activities/MSAboutUs;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/webkit/WebView;

    iput-object v0, p0, Lcom/pbb/mystock/activities/MSAboutUs;->k:Landroid/webkit/WebView;

    iget-object v0, p0, Lcom/pbb/mystock/activities/MSAboutUs;->k:Landroid/webkit/WebView;

    new-instance v1, Lcom/pbb/mystock/activities/a;

    invoke-direct {v1, p0}, Lcom/pbb/mystock/activities/a;-><init>(Lcom/pbb/mystock/activities/MSAboutUs;)V

    invoke-virtual {v0, v1}, Landroid/webkit/WebView;->setWebViewClient(Landroid/webkit/WebViewClient;)V

    iget-object v0, p0, Lcom/pbb/mystock/activities/MSAboutUs;->k:Landroid/webkit/WebView;

    invoke-static {}, Lcom/pbb/mystock/a/b;->u()Ljava/lang/String;

    move-result-object v1

    invoke-virtual {v0, v1}, Landroid/webkit/WebView;->loadUrl(Ljava/lang/String;)V

    const v0, 0x7f060007

    invoke-virtual {p0, v0}, Lcom/pbb/mystock/activities/MSAboutUs;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/Button;

    iput-object v0, p0, Lcom/pbb/mystock/activities/MSAboutUs;->j:Landroid/widget/Button;

    iget-object v0, p0, Lcom/pbb/mystock/activities/MSAboutUs;->j:Landroid/widget/Button;

    new-instance v1, Lcom/pbb/mystock/activities/b;

    invoke-direct {v1, p0}, Lcom/pbb/mystock/activities/b;-><init>(Lcom/pbb/mystock/activities/MSAboutUs;)V

    invoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V

    const v0, 0x7f060009

    invoke-virtual {p0, v0}, Lcom/pbb/mystock/activities/MSAboutUs;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/Button;

    const v1, 0x7f06000a

    invoke-virtual {p0, v1}, Lcom/pbb/mystock/activities/MSAboutUs;->findViewById(I)Landroid/view/View;

    move-result-object v1

    check-cast v1, Landroid/widget/HorizontalScrollView;

    invoke-virtual {p0, v0, v1}, Lcom/pbb/mystock/activities/MSAboutUs;->a(Landroid/widget/Button;Landroid/widget/HorizontalScrollView;)V

    invoke-virtual {p0}, Lcom/pbb/mystock/activities/MSAboutUs;->d()V

    return-void
.end method

.method public onKeyDown(ILandroid/view/KeyEvent;)Z
    .locals 1

    const/4 v0, 0x4

    if-ne p1, v0, :cond_0

    const/high16 v0, 0x7f04

    invoke-virtual {p0, v0}, Lcom/pbb/mystock/activities/MSAboutUs;->getString(I)Ljava/lang/String;

    move-result-object v0

    invoke-virtual {p0, v0}, Lcom/pbb/mystock/activities/MSAboutUs;->b(Ljava/lang/String;)V

    :cond_0
    const/4 v0, 0x0

    return v0
.end method

This is same to other activities. I can see login activity EditTexts and buttons. I'm sure with spending some hours its possible to understand what is architecture and then manipulate the code.

So my question is what Progaurd is exactly doing? I thought it change name of clases, methods and variables but it seems nothing is changed.

in prject.properties of application i have added this line:

proguard.config=proguard.cfg

and proguard.cfg includes these lines:

# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html

-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-verbose

# Optimization is turned off by default. Dex does not like code run
# through the ProGuard optimize and preverify steps (and performs some
# of these optimizations on its own).
-dontoptimize
-dontpreverify
# Note that if you want to enable optimization, you cannot just
# include optimization flags in your own project configuration file;
# instead you will need to point to the
# "proguard-android-optimize.txt" file instead of this one from your
# project.properties file.

-keepattributes *Annotation*
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService

# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames class * {
    native <methods>;
}

# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
-keepclassmembers public class * extends android.view.View {
   void set*(***);
   *** get*();
}

# We want to keep methods in Activity that could be used in the XML attribute onClick
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}

-keepclassmembers class **.R$* {
    public static <fields>;
}

# The support library contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version.  We know about them, and they are safe.
-dontwarn android.support.**

# Remove all logs
-assumenosideeffects class android.util.Log {
    public static *** v(...);
    public static *** d(...);
    public static *** i(...);
    public static *** w(...);
    public static *** e(...);
}

-keepattributes JavascriptInterface
-keep public class com.pbb.mystock.activities.MSLogin2$MyJavaScriptInterface
-keep public class * implements com.pbb.mystock.activities.MSLogin2$JavaScriptInterface
-keepclassmembers class com.pbb.mystock.activities.MSLogin2$JavaScriptInterface { 
    void processHTML(***); 
}

Upvotes: 1

Views: 1508

Answers (1)

Nikolay Elenkov
Nikolay Elenkov

Reputation: 52936

It does the same thing as it does on other platforms, see the FAQ for details. On Andorid you have to keep the names of Activities, services and other components that are defined in the manifest, because the OS references them by name. Same goes for lifecycle methods such as onCreate(). Resources are not modified in any way. Non-component classes (POJOs) will be renamed, and so will their methods and fields. It ultimately depends on the contents of the config file you use.

As you have noticed, that doesn't perfectly hide your code, nothing does. It just makes it harder to read when decompiled. You can try DexGuard which does a bit more, but ultimately if someone is determined enough, they can revers your code (same goes for native code, etc.)

Upvotes: 4

Related Questions