venerdì 22 febbraio 2013

Offuscare il codice Java di Android con ProGuard

All'interno dell SDK di Android e' contenuto uno strumento per offuscare il codice Java in modo da evitare quando descritto nel precedente post Decompilare un apk

Un file di configurazione generale e' riportato in sdk/tools/proguard/proguard-android.txt mentre un altro file di configurazione, specifico per ogni progetto, e' nella root del progetto come proguard-project.txt. La configurazione di base solitamente e' sufficiente

Per attivare l'offuscamento del codice si deve togliere il commento alla riga di Proguard in project.properties

project.properties
-----------------------------------------

# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
------------------------------------------

Una volta esportata il progetto creando il file .apk si osserva la creazione della directory proguard; importante conservare il contenuto perche' con questi file e' possibile effettuare il deoffuscamento del codice




provando ad effettuare la decompilazione dell'apk mediante il metodo del precedente post utilizzando la stessa applicazione si ha che la MainActivity risulta essere

Decompilazione con offuscamento
-------------------------------------------
package com.luca.innocenti.well.test;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.os.Bundle;
import android.text.Html;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity
{
  private Button a;
  private Button b;
  private TextView c;
  private TextView d;
  private TextView e;
  private TextView f;
  private TextView g;
  private TextView h;
  private TextView i;
  private TextView j;
  private int k = 1;
  private Button l;
  private TextView m;
  private TextView n;
  private TextView o;
  private TextView p;
  private TextView q;

  public void onCreate(Bundle paramBundle)
  {
    super.onCreate(paramBundle);
    setContentView(2130903041);
    this.b = ((Button)findViewById(2131165187));
    this.a = ((Button)findViewById(2131165188));
    this.l = ((Button)findViewById(2131165186));
    this.q = ((TextView)findViewById(2131165192));
    this.c = ((TextView)findViewById(2131165195));
    this.d = ((TextView)findViewById(2131165196));
    this.e = ((TextView)findViewById(2131165205));
    this.f = ((TextView)findViewById(2131165206));
    this.g = ((TextView)findViewById(2131165209));
    this.h = ((TextView)findViewById(2131165194));
    this.i = ((TextView)findViewById(2131165212));
    this.j = ((TextView)findViewById(2131165213));
    this.m = ((TextView)findViewById(2131165216));
    this.n = ((TextView)findViewById(2131165217));
    this.o = ((TextView)findViewById(2131165220));
    this.p = ((TextView)findViewById(2131165221));
    this.a.setOnClickListener(new a(this));
    this.l.setOnClickListener(new b(this));
    this.b.setOnClickListener(new c(this));
  }

  public boolean onCreateOptionsMenu(Menu paramMenu)
  {
    paramMenu.add(1, 1, 0, "Reference");
    paramMenu.add(1, 2, 1, "Help");
    return true;
  }

  public boolean onOptionsItemSelected(MenuItem paramMenuItem)
  {
    switch (paramMenuItem.getItemId())
    {
    default:
      return false;
    case 1:
      AlertDialog.Builder localBuilder2 = new AlertDialog.Builder(this);
      localBuilder2.setTitle("Reference");
      localBuilder2.setMessage(Html.fromHtml("Theory of Well Tests on <a href=\"http://en.wikipedia.org/wiki/Well_test\">Wikipedia</a>."));
      localBuilder2.setPositiveButton("Ok", new d(this));
      localBuilder2.create().show();
      return true;
    case 2:
    }
    AlertDialog.Builder localBuilder1 = new AlertDialog.Builder(this);
    localBuilder1.setTitle("Help");
    localBuilder1.setMessage(Html.fromHtml("App developed by Luca Innocenti (lucainnoc@gmail.com).<a href=\"http://github.com/c1p81\">Source Code</a>. Help: <a href=\"http://debiaonoldcomputers.blogspot.it/2012/10/drawdown-well-test.html\">My Blog</a>"));
    localBuilder1.setPositiveButton("Ok", new e(this));
    localBuilder1.create().show();
    return true;
  }
}
-------------------------------------------

Decompilazione senza offuscamento
-------------------------------------------
package com.luca.innocenti.well.test;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity
{
  private Button btncancella;
  private Button btngraph;
  private Button btnsalva;
  private int gradino = 1;
  private TextView portata1;
  private TextView portata2;
  private TextView portata3;
  private TextView portata4;
  private TextView portata5;
  private TextView soggiacenza1;
  private TextView soggiacenza2;
  private TextView soggiacenza3;
  private TextView soggiacenza4;
  private TextView soggiacenza5;
  private TextView txtportata;
  private TextView txtsoggiacenza;

  public void onCreate(Bundle paramBundle)
  {
    super.onCreate(paramBundle);
    setContentView(2130903041);
    this.btngraph = ((Button)findViewById(2131165191));
    this.btnsalva = ((Button)findViewById(2131165217));
    this.btncancella = ((Button)findViewById(2131165189));
    this.txtportata = ((TextView)findViewById(2131165190));
    this.txtsoggiacenza = ((TextView)findViewById(2131165188));
    this.portata1 = ((TextView)findViewById(2131165199));
    this.soggiacenza1 = ((TextView)findViewById(2131165200));
    this.portata2 = ((TextView)findViewById(2131165203));
    this.soggiacenza2 = ((TextView)findViewById(2131165204));
    this.portata3 = ((TextView)findViewById(2131165207));
    this.soggiacenza3 = ((TextView)findViewById(2131165208));
    this.portata4 = ((TextView)findViewById(2131165211));
    this.soggiacenza4 = ((TextView)findViewById(2131165212));
    this.portata5 = ((TextView)findViewById(2131165215));
    this.soggiacenza5 = ((TextView)findViewById(2131165216));
    this.btnsalva.setOnClickListener(new View.OnClickListener()
    {
      public void onClick(View paramAnonymousView)
      {
        switch (MainActivity.this.gradino)
        {
        default:
          return;
        case 1:
          MainActivity.this.portata1.setText(MainActivity.this.txtportata.getText());
          MainActivity.this.soggiacenza1.setText(MainActivity.this.txtsoggiacenza.getText());
          MainActivity.this.txtportata.setText("");
          MainActivity.this.txtsoggiacenza.setText("");
          MainActivity.this.txtportata.requestFocus();
          MainActivity localMainActivity5 = MainActivity.this;
          localMainActivity5.gradino = (1 + localMainActivity5.gradino);
          return;
        case 2:
          MainActivity.this.portata2.setText(MainActivity.this.txtportata.getText());
          MainActivity.this.soggiacenza2.setText(MainActivity.this.txtsoggiacenza.getText());
          MainActivity.this.txtportata.setText("");
          MainActivity.this.txtsoggiacenza.setText("");
          MainActivity.this.txtportata.requestFocus();
          MainActivity localMainActivity4 = MainActivity.this;
          localMainActivity4.gradino = (1 + localMainActivity4.gradino);
          return;
        case 3:
          MainActivity.this.portata3.setText(MainActivity.this.txtportata.getText());
          MainActivity.this.soggiacenza3.setText(MainActivity.this.txtsoggiacenza.getText());
          MainActivity.this.txtportata.setText("");
          MainActivity.this.txtsoggiacenza.setText("");
          MainActivity.this.txtportata.requestFocus();
          MainActivity localMainActivity3 = MainActivity.this;
          localMainActivity3.gradino = (1 + localMainActivity3.gradino);
          return;
        case 4:
          MainActivity.this.portata4.setText(MainActivity.this.txtportata.getText());
          MainActivity.this.soggiacenza4.setText(MainActivity.this.txtsoggiacenza.getText());
          MainActivity.this.txtportata.setText("");
          MainActivity.this.txtsoggiacenza.setText("");
          MainActivity.this.txtportata.requestFocus();
          MainActivity localMainActivity2 = MainActivity.this;
          localMainActivity2.gradino = (1 + localMainActivity2.gradino);
          return;
        case 5:
        }
        MainActivity.this.portata5.setText(MainActivity.this.txtportata.getText());
        MainActivity.this.soggiacenza5.setText(MainActivity.this.txtsoggiacenza.getText());
        MainActivity.this.txtportata.setText("");
        MainActivity.this.txtsoggiacenza.setText("");
        MainActivity.this.txtportata.requestFocus();
        MainActivity localMainActivity1 = MainActivity.this;
        localMainActivity1.gradino = (1 + localMainActivity1.gradino);
      }
    });
    this.btncancella.setOnClickListener(new View.OnClickListener()
    {
      public void onClick(View paramAnonymousView)
      {
        switch (MainActivity.this.gradino)
        {
        default:
          return;
        case 2:
          MainActivity.this.portata1.setText("");
          MainActivity.this.soggiacenza1.setText("");
          MainActivity localMainActivity5 = MainActivity.this;
          localMainActivity5.gradino = (-1 + localMainActivity5.gradino);
          return;
        case 3:
          MainActivity.this.portata2.setText("");
          MainActivity.this.soggiacenza2.setText("");
          MainActivity localMainActivity4 = MainActivity.this;
          localMainActivity4.gradino = (-1 + localMainActivity4.gradino);
          return;
        case 4:
          MainActivity.this.portata3.setText("");
          MainActivity.this.soggiacenza3.setText("");
          MainActivity localMainActivity3 = MainActivity.this;
          localMainActivity3.gradino = (-1 + localMainActivity3.gradino);
          return;
        case 5:
          MainActivity.this.portata4.setText("");
          MainActivity.this.soggiacenza4.setText("");
          MainActivity localMainActivity2 = MainActivity.this;
          localMainActivity2.gradino = (-1 + localMainActivity2.gradino);
          return;
        case 6:
        }
        MainActivity.this.portata5.setText("");
        MainActivity.this.soggiacenza5.setText("");
        MainActivity localMainActivity1 = MainActivity.this;
        localMainActivity1.gradino = (-1 + localMainActivity1.gradino);
      }
    });
    this.btngraph.setOnClickListener(new View.OnClickListener()
    {
      public void onClick(View paramAnonymousView)
      {
        Bundle localBundle = new Bundle();
        localBundle.putInt("gradini", MainActivity.this.gradino);
        localBundle.putDouble("portata1", Double.parseDouble(MainActivity.this.portata1.getText().toString()));
        localBundle.putDouble("soggiacenza1", Double.parseDouble(MainActivity.this.soggiacenza1.getText().toString()));
        localBundle.putDouble("portata2", Double.parseDouble(MainActivity.this.portata2.getText().toString()));
        localBundle.putDouble("soggiacenza2", Double.parseDouble(MainActivity.this.soggiacenza2.getText().toString()));
        localBundle.putDouble("portata3", Double.parseDouble(MainActivity.this.portata3.getText().toString()));
        localBundle.putDouble("soggiacenza3", Double.parseDouble(MainActivity.this.soggiacenza3.getText().toString()));
        localBundle.putDouble("portata4", Double.parseDouble(MainActivity.this.portata4.getText().toString()));
        localBundle.putDouble("soggiacenza4", Double.parseDouble(MainActivity.this.soggiacenza4.getText().toString()));
        localBundle.putDouble("portata5", Double.parseDouble(MainActivity.this.portata5.getText().toString()));
        localBundle.putDouble("soggiacenza5", Double.parseDouble(MainActivity.this.soggiacenza5.getText().toString()));
        Intent localIntent = new Intent();
        localIntent.setClass(MainActivity.this, Grafico.class);
        localIntent.putExtras(localBundle);
        MainActivity.this.startActivity(localIntent);
      }
    });
  }

  public boolean onCreateOptionsMenu(Menu paramMenu)
  {
    getMenuInflater().inflate(2131099649, paramMenu);
    return true;
  }
}
-------------------------------------------

come si puo' osservare la differenza e' sostanziale