Enable Proguard on Android app

Asked

Viewed 973 times

10

I did an example project, using SQLCipher, and I’m trying to obfuscate the code with the Proguard, however, after exporting and signing the application, and converting the.Dex classes with the dex2jar, I can see practically all the code with the Java Decompiler, because the code has not been overshadowed. I would like to know what I am doing wrong in setting the Proguard. Follows the configuration of proguard-project.txt:

 -injars      bin/classes
 -injars      libs
 -outjars     bin/classes-processed.jar
 -libraryjars C:/adt-bundle-windows-x86_64-20140702/sdk/platforms/android-        13/android.jar

-optimizations  !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
-optimizationpasses 5
-allowaccessmodification
-dontpreverify
-renamesourcefileattribute SourceFile
-keepattributes *Annotation* 
-keepattributes SourceFile,LineNumberTable,Signature
 # Obfuscation
-repackageclasses ''
-flattenpackagehierarchy ''


-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider

-keep public class * extends android.view.View {
 public <init>(android.content.Context);
 public <init>(android.content.Context, android.util.AttributeSet);
 public <init>(android.content.Context, android.util.AttributeSet, int);
 public void set*(...);
}

-keepclasseswithmembers class * {
 public <init>(android.content.Context, android.util.AttributeSet);
 }

-keepclasseswithmembers class * {
 public <init>(android.content.Context, android.util.AttributeSet, int);
 }

-keepclassmembers class * implements android.os.Parcelable {
 static android.os.Parcelable$Creator CREATOR;
 }

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

 -keep public class net.sqlcipher.** {
  *;
  }

-keep public class net.sqlcipher.database.** {
   *;
 }
  • These links may help you: (1): https://gist.github.com/developernotes/3040592 (2): https://github.com/exmo/equizmo-android/wiki/Ofuscando-applications-Android

2 answers

1

Fabio, it is possible that your proguard-project.txt file is not being applied to the project. If you’re using Android Studio and Gradle take a look at build.Radle, look for the entry proguardFiles and make sure your file is listed there. For more detailed instructions please consult here: http://developer.android.com/tools/help/proguard.html

  • Ducarrara, I’m using Eclipse, not Android Studio.

  • Fabio checks the project.properties file at the root of the project and sees if the proguard.config entry is pointing to your proguard file.

  • It looks like this: proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

  • Fabio is running out of Ideas :P. You could post an example snippet of a class before the obfuscation and after applying Java?

  • I ask this because it depends on what you have in mind as a result of the obfuscation. This post has an interesting explanation about assunot: http://stackoverflow.com/questions/11706084/android-apk-decompilation-seems-to-easy

  • Ducarrara, I posted the code in response.

  • 1

    Fabio, it seems the proguard is doing his job. The proguard obfuscates the code (changes variable names, methods), removes unused code and so on. As you can see there are some variables that have had their names changed and those that did not are because they fall into -Keep (like activities and classes of sqlcipher). As quoted in the post I put up if you want to make your code more "safe" so to speak only proguard obfuscation will not be enough.

  • 1

    This is a very difficult work, by the way, has an interesting material here: http://pt.slideshare.net/godfreynolan/protecting-source-code or https://www.guardsquare.com/dexguard or http://www.excelsior-usa.com/articles/java-obfuscators.html . But you need to search and see what really applies to your app.

Show 3 more comments

0

Original code :

package com.example.sqlcipher_exemplo;

import java.io.File;

import net.sqlcipher.Cursor;
import net.sqlcipher.database.SQLiteDatabase;
import net.sqlcipher.database.SQLiteDatabaseHook;
import android.app.Activity;
import android.content.ContentValues;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends Activity 
{

    EventDataSQLHelper eventsData;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if ("google_sdk".equals( Build.PRODUCT ) || Build.FINGERPRINT.startsWith("generic")) 
        {

               Log.i("EMULADOR", "rodando no emulador");

        } 
        else 
        {
               Log.i("DISPOSITIVO", "rodando no dispositivo");
        }

        SQLiteDatabase.loadLibs(this);
        String password = "123";
        eventsData = new EventDataSQLHelper(this);
        SQLiteDatabase db = eventsData.getWritableDatabase(password);   
        for(int i=1; i<100; i++)
        {
            addEvent("Hello Android Event "+i, db); 
        }
        db.close();
        db = eventsData.getReadableDatabase(password);
        Cursor cursor = getEvents(db);
        showEvents(cursor);
        db.close();
    }

    private void addEvent (String title, SQLiteDatabase db)
    {
        ContentValues values = new ContentValues();
        values.put(EventDataSQLHelper.TIME, System.currentTimeMillis());
        values.put(EventDataSQLHelper.TITLE, title);
        db.insert(EventDataSQLHelper.TABLE, null, values);
    }

    private Cursor getEvents(SQLiteDatabase db)
    {
        Cursor cursor = db.query(EventDataSQLHelper.TABLE, null, null, null, null, null, null);

        startManagingCursor(cursor);
        return cursor;
    }

    private void showEvents(Cursor cursor)
    {
        StringBuilder ret = new StringBuilder("Saved Events:\n\n");
        while (cursor.moveToNext())
        {
            long id = cursor.getLong(0);
            long time = cursor.getLong(1);
            String title = cursor.getString(2);
            ret.append(id+": "+time+":"+title+"\n");
        }
        Log.i("sqldemo", ret.toString());
    }

    /*
    private void decryptDatabase() 
    {
          File unencryptedFile = getDatabasePath("events.db");
          unencryptedFile.delete();
          File databaseFile = getDatabasePath("events.db");
          SQLiteDatabaseHook hook = new SQLiteDatabaseHook() {
           public void preKey(SQLiteDatabase sqLiteDatabase) {
            sqLiteDatabase
              .rawExecSQL("PRAGMA cipher_default_use_hmac = off;");
           }

           public void postKey(SQLiteDatabase sqLiteDatabase) 
           {

           }
          };
          SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(
            databaseFile, "123", null, hook); // Exception 
          if (database.isOpen()) 
          {
           database.rawExecSQL(String.format(
             "ATTACH DATABASE '%s' as plaintext KEY '';",
             unencryptedFile.getAbsolutePath()));
           database.rawExecSQL("SELECT sqlcipher_export('plaintext');");
           database.rawExecSQL("DETACH DATABASE plaintext;");
           android.database.sqlite.SQLiteDatabase sqlDB = android.database.sqlite.SQLiteDatabase
             .openOrCreateDatabase(unencryptedFile, null);
           sqlDB.close();
           database.close();
          }

          databaseFile.delete();
    }*/
}

Code after the Proguard:

package com.example.sqlcipher_exemplo;

import android.app.Activity;
import android.content.ContentValues;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import net.sqlcipher.Cursor;
import net.sqlcipher.database.SQLiteDatabase;

public class MainActivity
  extends Activity
{
  a a;

  private Cursor a(SQLiteDatabase paramSQLiteDatabase)
  {
    paramSQLiteDatabase = paramSQLiteDatabase.query("events", null, null, null, null, null, null);
    startManagingCursor(paramSQLiteDatabase);
    return paramSQLiteDatabase;
  }

  private void a(String paramString, SQLiteDatabase paramSQLiteDatabase)
  {
    ContentValues localContentValues = new ContentValues();
    localContentValues.put("time", Long.valueOf(System.currentTimeMillis()));
    localContentValues.put("title", paramString);
    paramSQLiteDatabase.insert("events", null, localContentValues);
  }

  private void a(Cursor paramCursor)
  {
    StringBuilder localStringBuilder = new StringBuilder("Saved Events:\n\n");
    for (;;)
    {
      if (!paramCursor.moveToNext())
      {
        Log.i("sqldemo", localStringBuilder.toString());
        return;
      }
      long l1 = paramCursor.getLong(0);
      long l2 = paramCursor.getLong(1);
      String str = paramCursor.getString(2);
      localStringBuilder.append(l1 + ": " + l2 + ":" + str + "\n");
    }
  }

  protected void onCreate(Bundle paramBundle)
  {
    super.onCreate(paramBundle);
    setContentView(2130903040);
    int i;
    if (("google_sdk".equals(Build.PRODUCT)) || (Build.FINGERPRINT.startsWith("generic")))
    {
      Log.i("EMULADOR", "rodando no emulador");
      SQLiteDatabase.loadLibs(this);
      this.a = new a(this);
      paramBundle = this.a.getWritableDatabase("123");
      i = 1;
    }
    for (;;)
    {
      if (i >= 100)
      {
        paramBundle.close();
        paramBundle = this.a.getReadableDatabase("123");
        a(a(paramBundle));
        paramBundle.close();
        return;
        Log.i("DISPOSITIVO", "rodando no dispositivo");
        break;
      }
      a("Hello Android Event " + i, paramBundle);
      i += 1;
    }
  }
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.