SlideShare a Scribd company logo
#mceconf #mce-proguard 11 Jan 2014
ProGuard
Optimizer and Obfuscator
in the Android SDK
Eric Lafortune
Developer of ProGuard
Technical director at Saikoa
#mceconf #mce-proguard 11 Jan 2014
ProGuard
Generic
Shrinker
Optimizer
Obfuscator
For Java bytecode
Open source
#mceconf #mce-proguard 11 Jan 2014
ProGuard history
Java applications
Applets
2002
Midlets
2010 2012
Android apps
●
May 2002 First release
●
Sep 2010 Recommended for protecting LVL
●
Dec 2010 Part of Android SDK
●
Jan 2012 Startup Saikoa
#mceconf #mce-proguard 11 Jan 2014
ProGuard
Application
code
Libraries
Runtime
libraries
Shrink Optimize Obfuscate
Processed
code
Runtime
libraries
#mceconf #mce-proguard 11 Jan 2014
ProGuard in Android builds
Application
Java bytecode
ProGuard
Libraries
Java bytecode
Processed
Java bytecode Dex
Dalvik bytecode
Javac
Application
Java source
Libraries
Java bytecode
XML resources
Assets Assets
Compiled
XML resourcesAapt
#mceconf #mce-proguard 11 Jan 2014
Why use ProGuard?
●
Application size
●
Performance
●
Remove logging, debugging, testing code
●
Protection
#mceconf #mce-proguard 11 Jan 2014
Application size
classes.dex size .apk size
Without
ProGuard
With
ProGuard
Reduction
ApiDemos 716 K 482 K 33 % 2.6 M 2.5 M 4 %
GoogleIO
App
3.4 M 905 K 75 % 1.9 M 906 K 53 %
ApiDemos
in Scala*
~6 M 542 K ~90 % ~8 M 2.5 M ~70 %
* [Stéphane Micheloud, http://lampwww.epfl.ch/~michelou/android/library-code-shrinking.html]
#mceconf #mce-proguard 11 Jan 2014
Performance: CaffeineMark
Without ProGuard
Sieve score = 6833
Loop score = 14831
Logic score = 19038
String score = 7694
Float score = 6425
Method score = 4850
Overall score = 8794
With ProGuard
Sieve score = 6666
Loop score = 15473
Logic score = 47840
String score = 7717
Float score = 6488
Method score = 5229
Overall score = 10436
Improvement: 18%
[Acer Iconia Tab A500, nVidia Tegra 2, 1.0 GHz, Android 3.2.1]
#mceconf #mce-proguard 11 Jan 2014
Results
●
Size reduction:
– Code (classes.dex): 20 … 90%
– Application (.apk): 5 ... 70%
●
Performance improvements: 0 … 20%
#mceconf #mce-proguard 11 Jan 2014
How to enable ProGuard?
Ant and Eclipse: project.properties
→ only applied when building release versions
# To enable ProGuard to shrink and obfuscate your code, uncomment this
#proguard.config=
${sdk.dir}/tools/proguard/proguard-android.txt:
proguard-project.txt
# To enable ProGuard to shrink and obfuscate your code, uncomment this
#proguard.config=
${sdk.dir}/tools/proguard/proguard-android.txt:
proguard-project.txt
Tip
#mceconf #mce-proguard 11 Jan 2014
How to enable ProGuard?
Gradle: build.gradle
→ completely flexible
android {
buildTypes {
release {
runProguard true
proguardFile getDefaultProguardFile('proguard-android.txt')
}
}
productFlavors {
some_flavor {
proguardFile 'proguard-project.txt'
}
}
}
android {
buildTypes {
release {
runProguard true
proguardFile getDefaultProguardFile('proguard-android.txt')
}
}
productFlavors {
some_flavor {
proguardFile 'proguard-project.txt'
}
}
}
New
#mceconf #mce-proguard 11 Jan 2014
Notes and warnings
“Closed-world assumption”
→ if debug build works fine,
then ok to ignore in proguard-project.txt:
Warning: com.dropbox.client2.DropboxAPI:
can't find referenced class org.json.simple.JSONArray
Warning: com.dropbox.client2.DropboxAPI:
can't find referenced class org.json.simple.JSONArray
-dontwarn twitter4j.internal.logging.**
-dontwarn com.dropbox.client2.**
-dontwarn twitter4j.internal.logging.**
-dontwarn com.dropbox.client2.**
Warning: twitter4j.internal.logging.Log4JLoggerFactory:
can't find referenced class org.apache.log4j.Logger
Warning: twitter4j.internal.logging.SLF4JLoggerFactory:
can't find referenced class org.slf4j.LoggerFactory
...
Warning: twitter4j.internal.logging.Log4JLoggerFactory:
can't find referenced class org.apache.log4j.Logger
Warning: twitter4j.internal.logging.SLF4JLoggerFactory:
can't find referenced class org.slf4j.LoggerFactory
...
Tip
#mceconf #mce-proguard 11 Jan 2014
Notes and warnings
Straight to the Troubleshooting page:
Warning: there were 12 unresolved references to classes or interfaces.
You may need to add missing library jars or update their versions.
If your code works fine without the missing classes, you can suppress
the warnings with '-dontwarn' options.
(http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedclass)
Warning: there were 12 unresolved references to classes or interfaces.
You may need to add missing library jars or update their versions.
If your code works fine without the missing classes, you can suppress
the warnings with '-dontwarn' options.
(http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedclass)
New
#mceconf #mce-proguard 11 Jan 2014
Shrinking
Also called treeshaking, minimizing, shrouding
#mceconf #mce-proguard 11 Jan 2014
Shrinking
●
Classes, fields, methods
#mceconf #mce-proguard 11 Jan 2014
Entry points
1) Activities, applications, services, fragments,...
→ provided automatically by Android build process
-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.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
…
#mceconf #mce-proguard 11 Jan 2014
Entry points
2) Introspection, e.g. Guice, RoboGuice
→ must be specified in proguard-project.txt:
-keepclassmembers class * {
@javax.inject.** <fields>;
@com.google.inject.** <fields>;
@roboguice.** <fields>;
@roboguice.event.Observes <methods>;
}
-keepclassmembers class * {
@javax.inject.** <fields>;
@com.google.inject.** <fields>;
@roboguice.** <fields>;
@roboguice.event.Observes <methods>;
}
Tip
#mceconf #mce-proguard 11 Jan 2014
Optimization
At the bytecode instruction level:
●
Dead code elimination
●
Constant propagation
●
Method inlining
●
Class merging
●
Remove logging code
●
Peephole optimizations
●
Devirtualization
●
...
#mceconf #mce-proguard 11 Jan 2014
Optimization example
int answer = computeAnswer(1, 2, 3, 7);int answer = computeAnswer(1, 2, 3, 7);
int computeAnswer(int f1, int f2, int f3, int f4) {
if (f2 == 1 && f3 == 1 && f4 == 1) {
return f1;
} else {
return computeAnswer(f1 * f2, f3, f4, 1);
}
}
int computeAnswer(int f1, int f2, int f3, int f4) {
if (f2 == 1 && f3 == 1 && f4 == 1) {
return f1;
} else {
return computeAnswer(f1 * f2, f3, f4, 1);
}
}
#mceconf #mce-proguard 11 Jan 2014
Optimization example
int answer = computeAnswer(1, 2, 3, 7);int answer = computeAnswer(1, 2, 3, 7);
int computeAnswer(int f1, int f2, int f3, int f4) {
if (f2 == 1 && f3 == 1 && f4 == 1) {
return f1;
} else {
return computeAnswer(f1 * f2, f3, f4, 1);
}
}
int computeAnswer(int f1, int f2, int f3, int f4) {
if (f2 == 1 && f3 == 1 && f4 == 1) {
return f1;
} else {
return computeAnswer(f1 * f2, f3, f4, 1);
}
}
int computeAnswer(int f1, int f2, int f3, int f4) {
do {
if (f2 == 1 && f3 == 1 && f4 == 1) {
return f1;
} else {
f1 = f1 * f2; f2 = f3, f3 = f4, f4 = 1;
}
} while (true);
}
int computeAnswer(int f1, int f2, int f3, int f4) {
do {
if (f2 == 1 && f3 == 1 && f4 == 1) {
return f1;
} else {
f1 = f1 * f2; f2 = f3, f3 = f4, f4 = 1;
}
} while (true);
}
#mceconf #mce-proguard 11 Jan 2014
Optimization example
int answer = computeAnswer(1, 2, 3, 7);int answer = computeAnswer(1, 2, 3, 7);
int computeAnswer(int f1, int f2, int f3, int f4) {
if (f2 == 1 && f3 == 1 && f4 == 1) {
return f1;
} else {
return computeAnswer(f1 * f2, f3, f4, 1);
}
}
int computeAnswer(int f1, int f2, int f3, int f4) {
if (f2 == 1 && f3 == 1 && f4 == 1) {
return f1;
} else {
return computeAnswer(f1 * f2, f3, f4, 1);
}
}
int computeAnswer(int f1, int f2, int f3, int f4) {
do {
if (f2 == 1 && f3 == 1 && f4 == 1) {
return f1;
} else {
f1 = f1 * f2; f2 = f3, f3 = f4, f4 = 1;
}
} while (true);
}
int computeAnswer(int f1, int f2, int f3, int f4) {
do {
if (f2 == 1 && f3 == 1 && f4 == 1) {
return f1;
} else {
f1 = f1 * f2; f2 = f3, f3 = f4, f4 = 1;
}
} while (true);
}
#mceconf #mce-proguard 11 Jan 2014
Optimization example
int answer = computeAnswer(1, 2, 3, 7);int answer = computeAnswer(1, 2, 3, 7);
int computeAnswer(int f1, int f2, int f3, int f4) {
if (f2 == 1 && f3 == 1 && f4 == 1) {
return f1;
} else {
return computeAnswer(f1 * f2, f3, f4, 1);
}
}
int computeAnswer(int f1, int f2, int f3, int f4) {
if (f2 == 1 && f3 == 1 && f4 == 1) {
return f1;
} else {
return computeAnswer(f1 * f2, f3, f4, 1);
}
}
int computeAnswer(int f1, int f2, int f3, int f4) {
do {
if (f2 == 1 && f3 == 1 && f4 == 1) {
return f1;
} else {
f1 = f1 * f2; f2 = f3, f3 = f4, f4 = 1;
}
} while (true);
}
int computeAnswer(int f1, int f2, int f3, int f4) {
do {
if (f2 == 1 && f3 == 1 && f4 == 1) {
return f1;
} else {
f1 = f1 * f2; f2 = f3, f3 = f4, f4 = 1;
}
} while (true);
}
int computeAnswer() {
return 42;
}
int computeAnswer() {
return 42;
}
#mceconf #mce-proguard 11 Jan 2014
Optimization example
int answer = computeAnswer(1, 2, 3, 7);int answer = computeAnswer(1, 2, 3, 7);
int computeAnswer(int f1, int f2, int f3, int f4) {
if (f2 == 1 && f3 == 1 && f4 == 1) {
return f1;
} else {
return computeAnswer(f1 * f2, f3, f4, 1);
}
}
int computeAnswer(int f1, int f2, int f3, int f4) {
if (f2 == 1 && f3 == 1 && f4 == 1) {
return f1;
} else {
return computeAnswer(f1 * f2, f3, f4, 1);
}
}
int computeAnswer(int f1, int f2, int f3, int f4) {
do {
if (f2 == 1 && f3 == 1 && f4 == 1) {
return f1;
} else {
f1 = f1 * f2; f2 = f3, f3 = f4, f4 = 1;
}
} while (true);
}
int computeAnswer(int f1, int f2, int f3, int f4) {
do {
if (f2 == 1 && f3 == 1 && f4 == 1) {
return f1;
} else {
f1 = f1 * f2; f2 = f3, f3 = f4, f4 = 1;
}
} while (true);
}
int computeAnswer() {
return 42;
}
int computeAnswer() {
return 42;
}
int answer = 42;int answer = 42;
#mceconf #mce-proguard 11 Jan 2014
Optimization: enum
int answer = getAnswer(MyEnum.GREEN);int answer = getAnswer(MyEnum.GREEN);
int getAnswer(MyEnum e) {
switch (e) {
case RED: return 1;
case GREEN: return 42;
default: return 0;
}
}
int getAnswer(MyEnum e) {
switch (e) {
case RED: return 1;
case GREEN: return 42;
default: return 0;
}
}
enum MyEnum {
RED, GREEN, BLUE
}
enum MyEnum {
RED, GREEN, BLUE
}
New
#mceconf #mce-proguard 11 Jan 2014
Optimization: enum
int answer = getAnswer(MyEnum.GREEN);int answer = getAnswer(MyEnum.GREEN);
int getAnswer(MyEnum e) {
switch (e) {
case RED: return 1;
case GREEN: return 42;
default: return 0;
}
}
int getAnswer(MyEnum e) {
switch (e) {
case RED: return 1;
case GREEN: return 42;
default: return 0;
}
}
enum MyEnum {
RED, GREEN, BLUE
}
enum MyEnum {
RED, GREEN, BLUE
}
class MyEnum {
static final MyEnum RED = new MyEnum(“RED”, 0);
static final MyEnum GREEN = new MyEnum(“GREEN”, 0);
static final MyEnum BLUE = new MyEnum(“BLUE”, 0);
static final MyEnum[] $VALUES =
new MyEnum[] { RED, GREEN, BLUE };
...
}
class MyEnum {
static final MyEnum RED = new MyEnum(“RED”, 0);
static final MyEnum GREEN = new MyEnum(“GREEN”, 0);
static final MyEnum BLUE = new MyEnum(“BLUE”, 0);
static final MyEnum[] $VALUES =
new MyEnum[] { RED, GREEN, BLUE };
...
}
New
#mceconf #mce-proguard 11 Jan 2014
Optimization: enum
int answer = getAnswer(MyEnum.GREEN);int answer = getAnswer(MyEnum.GREEN);
int getAnswer(MyEnum e) {
switch (e) {
case RED: return 1;
case GREEN: return 42;
default: return 0;
}
}
int getAnswer(MyEnum e) {
switch (e) {
case RED: return 1;
case GREEN: return 42;
default: return 0;
}
}
enum MyEnum {
RED, GREEN, BLUE
}
enum MyEnum {
RED, GREEN, BLUE
}
int getAnswer(MyEnum e) {
switch (Internal.$SwitchMap[e.ordinal()]) {
case 1: return 1;
case 2: return 42;
default: return 0;
}
}
int getAnswer(MyEnum e) {
switch (Internal.$SwitchMap[e.ordinal()]) {
case 1: return 1;
case 2: return 42;
default: return 0;
}
}
class MyEnum {
static final MyEnum RED = new MyEnum(“RED”, 0);
static final MyEnum GREEN = new MyEnum(“GREEN”, 0);
static final MyEnum BLUE = new MyEnum(“BLUE”, 0);
static final MyEnum[] $VALUES =
new MyEnum[] { RED, GREEN, BLUE };
...
}
class MyEnum {
static final MyEnum RED = new MyEnum(“RED”, 0);
static final MyEnum GREEN = new MyEnum(“GREEN”, 0);
static final MyEnum BLUE = new MyEnum(“BLUE”, 0);
static final MyEnum[] $VALUES =
new MyEnum[] { RED, GREEN, BLUE };
...
}
class Internal {
static final int[] $SwitchMap
new int[MyEnum.values().length];
static {
$SwitchMap[MyEnum.GREEN.ordinal()] = 1;
$SwitchMap[MyEnum.RED.ordinal()] = 2;
}
}
class Internal {
static final int[] $SwitchMap
new int[MyEnum.values().length];
static {
$SwitchMap[MyEnum.GREEN.ordinal()] = 1;
$SwitchMap[MyEnum.RED.ordinal()] = 2;
}
}
New
#mceconf #mce-proguard 11 Jan 2014
Optimization: enum
int answer = getAnswer(MyEnum.GREEN);int answer = getAnswer(MyEnum.GREEN);
int getAnswer(MyEnum e) {
switch (e) {
case RED: return 1;
case GREEN: return 42;
default: return 0;
}
}
int getAnswer(MyEnum e) {
switch (e) {
case RED: return 1;
case GREEN: return 42;
default: return 0;
}
}
enum MyEnum {
RED, GREEN, BLUE
}
enum MyEnum {
RED, GREEN, BLUE
}
int getAnswer(MyEnum e) {
switch (Internal.$SwitchMap[e.ordinal()]) {
case 1: return 1;
case 2: return 42;
default: return 0;
}
}
int getAnswer(MyEnum e) {
switch (Internal.$SwitchMap[e.ordinal()]) {
case 1: return 1;
case 2: return 42;
default: return 0;
}
}
class MyEnum {
static final MyEnum RED = new MyEnum(“RED”, 0);
static final MyEnum GREEN = new MyEnum(“GREEN”, 0);
static final MyEnum BLUE = new MyEnum(“BLUE”, 0);
static final MyEnum[] $VALUES =
new MyEnum[] { RED, GREEN, BLUE };
...
}
class MyEnum {
static final MyEnum RED = new MyEnum(“RED”, 0);
static final MyEnum GREEN = new MyEnum(“GREEN”, 0);
static final MyEnum BLUE = new MyEnum(“BLUE”, 0);
static final MyEnum[] $VALUES =
new MyEnum[] { RED, GREEN, BLUE };
...
}
class Internal {
static final int[] $SwitchMap
new int[MyEnum.values().length];
static {
$SwitchMap[MyEnum.GREEN.ordinal()] = 1;
$SwitchMap[MyEnum.RED.ordinal()] = 2;
}
}
class Internal {
static final int[] $SwitchMap
new int[MyEnum.values().length];
static {
$SwitchMap[MyEnum.GREEN.ordinal()] = 1;
$SwitchMap[MyEnum.RED.ordinal()] = 2;
}
}
int answer = getAnswer(2);int answer = getAnswer(2);
int getAnswer(int e) {
switch (Internal.$SwitchMap[e]) {
case 1: return 1;
case 2: return 42;
default: return 0;
}
}
int getAnswer(int e) {
switch (Internal.$SwitchMap[e]) {
case 1: return 1;
case 2: return 42;
default: return 0;
}
}
New
class Internal {
static final int[] $SwitchMap =
new int[3];
static {
$SwitchMap[1] = 1;
$SwitchMap[2] = 2;
}
}
class Internal {
static final int[] $SwitchMap =
new int[3];
static {
$SwitchMap[1] = 1;
$SwitchMap[2] = 2;
}
}
#mceconf #mce-proguard 11 Jan 2014
Optimization: enum
int answer = getAnswer(MyEnum.GREEN);int answer = getAnswer(MyEnum.GREEN);
int getAnswer(MyEnum e) {
switch (e) {
case RED: return 1;
case GREEN: return 42;
default: return 0;
}
}
int getAnswer(MyEnum e) {
switch (e) {
case RED: return 1;
case GREEN: return 42;
default: return 0;
}
}
enum MyEnum {
RED, GREEN, BLUE
}
enum MyEnum {
RED, GREEN, BLUE
}
int getAnswer(MyEnum e) {
switch (Internal.$SwitchMap[e.ordinal()]) {
case 1: return 1;
case 2: return 42;
default: return 0;
}
}
int getAnswer(MyEnum e) {
switch (Internal.$SwitchMap[e.ordinal()]) {
case 1: return 1;
case 2: return 42;
default: return 0;
}
}
class MyEnum {
static final MyEnum RED = new MyEnum(“RED”, 0);
static final MyEnum GREEN = new MyEnum(“GREEN”, 0);
static final MyEnum BLUE = new MyEnum(“BLUE”, 0);
static final MyEnum[] $VALUES =
new MyEnum[] { RED, GREEN, BLUE };
...
}
class MyEnum {
static final MyEnum RED = new MyEnum(“RED”, 0);
static final MyEnum GREEN = new MyEnum(“GREEN”, 0);
static final MyEnum BLUE = new MyEnum(“BLUE”, 0);
static final MyEnum[] $VALUES =
new MyEnum[] { RED, GREEN, BLUE };
...
}
class Internal {
static final int[] $SwitchMap
new int[MyEnum.values().length];
static {
$SwitchMap[MyEnum.GREEN.ordinal()] = 1;
$SwitchMap[MyEnum.RED.ordinal()] = 2;
}
}
class Internal {
static final int[] $SwitchMap
new int[MyEnum.values().length];
static {
$SwitchMap[MyEnum.GREEN.ordinal()] = 1;
$SwitchMap[MyEnum.RED.ordinal()] = 2;
}
}
int answer = getAnswer(2);int answer = getAnswer(2);
int getAnswer(int e) {
switch (Internal.$SwitchMap[e]) {
case 1: return 1;
case 2: return 42;
default: return 0;
}
}
int getAnswer(int e) {
switch (Internal.$SwitchMap[e]) {
case 1: return 1;
case 2: return 42;
default: return 0;
}
}
int getAnswer(int e) {
switch (e) {
case 1: return 1;
case 2: return 42;
default: return 0;
}
}
int getAnswer(int e) {
switch (e) {
case 1: return 1;
case 2: return 42;
default: return 0;
}
}
New
class Internal {
static final int[] $SwitchMap =
new int[3];
static {
$SwitchMap[1] = 1;
$SwitchMap[2] = 2;
}
}
class Internal {
static final int[] $SwitchMap =
new int[3];
static {
$SwitchMap[1] = 1;
$SwitchMap[2] = 2;
}
}
#mceconf #mce-proguard 11 Jan 2014
Optimization: enum
int answer = getAnswer(MyEnum.GREEN);int answer = getAnswer(MyEnum.GREEN);
int getAnswer(MyEnum e) {
switch (e) {
case RED: return 1;
case GREEN: return 42;
default: return 0;
}
}
int getAnswer(MyEnum e) {
switch (e) {
case RED: return 1;
case GREEN: return 42;
default: return 0;
}
}
enum MyEnum {
RED, GREEN, BLUE
}
enum MyEnum {
RED, GREEN, BLUE
}
int getAnswer(MyEnum e) {
switch (Internal.$SwitchMap[e.ordinal()]) {
case 1: return 1;
case 2: return 42;
default: return 0;
}
}
int getAnswer(MyEnum e) {
switch (Internal.$SwitchMap[e.ordinal()]) {
case 1: return 1;
case 2: return 42;
default: return 0;
}
}
class MyEnum {
static final MyEnum RED = new MyEnum(“RED”, 0);
static final MyEnum GREEN = new MyEnum(“GREEN”, 0);
static final MyEnum BLUE = new MyEnum(“BLUE”, 0);
static final MyEnum[] $VALUES =
new MyEnum[] { RED, GREEN, BLUE };
...
}
class MyEnum {
static final MyEnum RED = new MyEnum(“RED”, 0);
static final MyEnum GREEN = new MyEnum(“GREEN”, 0);
static final MyEnum BLUE = new MyEnum(“BLUE”, 0);
static final MyEnum[] $VALUES =
new MyEnum[] { RED, GREEN, BLUE };
...
}
class Internal {
static final int[] $SwitchMap
new int[MyEnum.values().length];
static {
$SwitchMap[MyEnum.GREEN.ordinal()] = 1;
$SwitchMap[MyEnum.RED.ordinal()] = 2;
}
}
class Internal {
static final int[] $SwitchMap
new int[MyEnum.values().length];
static {
$SwitchMap[MyEnum.GREEN.ordinal()] = 1;
$SwitchMap[MyEnum.RED.ordinal()] = 2;
}
}
int answer = getAnswer(2);int answer = getAnswer(2);
int getAnswer(int e) {
switch (Internal.$SwitchMap[e]) {
case 1: return 1;
case 2: return 42;
default: return 0;
}
}
int getAnswer(int e) {
switch (Internal.$SwitchMap[e]) {
case 1: return 1;
case 2: return 42;
default: return 0;
}
}
int getAnswer(int e) {
switch (e) {
case 1: return 1;
case 2: return 42;
default: return 0;
}
}
int getAnswer(int e) {
switch (e) {
case 1: return 1;
case 2: return 42;
default: return 0;
}
}
int answer = 42;int answer = 42;
New
class Internal {
static final int[] $SwitchMap =
new int[3];
static {
$SwitchMap[1] = 1;
$SwitchMap[2] = 2;
}
}
class Internal {
static final int[] $SwitchMap =
new int[3];
static {
$SwitchMap[1] = 1;
$SwitchMap[2] = 2;
}
}
#mceconf #mce-proguard 11 Jan 2014
How to enable optimization?
Ant and Eclipse: project.properties
Tip
# To enable ProGuard to shrink and obfuscate your code, uncomment this
proguard.config=
${sdk.dir}/tools/proguard/proguard-android-optimize.txt:
proguard-project.txt
# To enable ProGuard to shrink and obfuscate your code, uncomment this
proguard.config=
${sdk.dir}/tools/proguard/proguard-android-optimize.txt:
proguard-project.txt
#mceconf #mce-proguard 11 Jan 2014
How to enable optimization?
Gradle: build.gradle
android {
buildTypes {
release {
runProguard true
proguardFile getDefaultProguardFile('proguard-android-optimize.txt')
}
}
productFlavors {
some_flavor {
proguardFile 'proguard-project.txt'
}
}
}
android {
buildTypes {
release {
runProguard true
proguardFile getDefaultProguardFile('proguard-android-optimize.txt')
}
}
productFlavors {
some_flavor {
proguardFile 'proguard-project.txt'
}
}
}
New
#mceconf #mce-proguard 11 Jan 2014
Remove logging code
Specify assumptions in proguard-project.txt:
-assumenosideeffects class android.util.Log {
public static boolean isLoggable(java.lang.String, int);
public static int v(...);
public static int i(...);
public static int w(...);
public static int d(...);
public static int e(...);
public static java.lang.String getStackTraceString
(java.lang.Throwable);
}
-assumenosideeffects class android.util.Log {
public static boolean isLoggable(java.lang.String, int);
public static int v(...);
public static int i(...);
public static int w(...);
public static int d(...);
public static int e(...);
public static java.lang.String getStackTraceString
(java.lang.Throwable);
}
Tip
#mceconf #mce-proguard 11 Jan 2014
Obfuscation
Traditional name obfuscation:
●
Rename identifiers:
class/field/method names
●
Remove debug information:
line numbers, local variable names,...
#mceconf #mce-proguard 11 Jan 2014
Obfuscation example
public class MyComputationClass {
private MySettings settings;
private MyAlgorithm algorithm;
private int answer;
public int computeAnswer(int input) {
…
return answer;
}
}
public class MyComputationClass {
private MySettings settings;
private MyAlgorithm algorithm;
private int answer;
public int computeAnswer(int input) {
…
return answer;
}
}
#mceconf #mce-proguard 11 Jan 2014
Obfuscation example
public class MyComputationClass {
private MySettings settings;
private MyAlgorithm algorithm;
private int answer;
public int computeAnswer(int input) {
…
return answer;
}
}
public class MyComputationClass {
private MySettings settings;
private MyAlgorithm algorithm;
private int answer;
public int computeAnswer(int input) {
…
return answer;
}
}
public class a {
private b a;
private c b;
private int c;
public int a(int a) {
…
return c;
}
}
public class a {
private b a;
private c b;
private int c;
public int a(int a) {
…
return c;
}
}
#mceconf #mce-proguard 11 Jan 2014
Complementary steps
Optimization Obfuscation
Irreversibly remove information
#mceconf #mce-proguard 11 Jan 2014
What about ART?
The new (experimental) Android RunTime
Application
Java bytecode
ProGuard
Libraries
Java bytecode
Processed
Java bytecode Dex
Dalvik bytecode
Dex2oat
Native code
Development
Device
#mceconf #mce-proguard 11 Jan 2014
More application protection?
public class MyVerificationClass {
public int checkSignatures() {
…
return activity
.getPackageManager()
.checkSignatures(“mypackage1”, “mypackage2”);
}
}
public class MyVerificationClass {
public int checkSignatures() {
…
return activity
.getPackageManager()
.checkSignatures(“mypackage1”, “mypackage2”);
}
}
#mceconf #mce-proguard 11 Jan 2014
More application protection?
public class MyVerificationClass {
public int checkSignatures() {
…
return activity
.getPackageManager()
.checkSignatures(“mypackage1”, “mypackage2”);
}
}
public class MyVerificationClass {
public int checkSignatures() {
…
return activity
.getPackageManager()
.checkSignatures(“mypackage1”, “mypackage2”);
}
}
public class a {
public int a() {
…
return a
.getPackageManager()
.checkSignatures(“mypackage1”, “mypackage2”);
}
}
public class a {
public int a() {
…
return a
.getPackageManager()
.checkSignatures(“mypackage1”, “mypackage2”);
}
}
#mceconf #mce-proguard 11 Jan 2014
More application protection
Nothing is unbreakable, but you can raise the bar:
●
ProGuard
●
String encryption
●
Reflection
●
Dynamic class loading
●
Native code
●
Data encryption
●
… DexGuard
#mceconf #mce-proguard 11 Jan 2014
ProGuard - DexGuard
Open source
Generic
Shrinker
Optimizer
Obfuscator
For Java bytecode
Closed source
Specialized
Shrinker
Optimizer
Obfuscator
Protector
For Android
Compatible
#mceconf #mce-proguard 11 Jan 2014
ProGuard guide – Android SDK
developer.android.comdeveloper.android.com
#mceconf #mce-proguard 11 Jan 2014
ProGuard website
proguard.sourceforge.netproguard.sourceforge.net
#mceconf #mce-proguard 11 Jan 2014
ProGuard manualTip
proguard.sourceforge.netproguard.sourceforge.net
#mceconf #mce-proguard 11 Jan 2014
Saikoa website
www.saikoa.comwww.saikoa.com
#mceconf #mce-proguard 11 Jan 2014
Questions?
Open source
Shrinking
Optimization
Obfuscation
Java bytecode
ProGuard
Saikoa
DexGuard
Dalvik bytecode
Protection

More Related Content

What's hot

20130530-PEGjs
20130530-PEGjs20130530-PEGjs
20130530-PEGjs
zuqqhi 2
 
Qe Reference
Qe ReferenceQe Reference
Qe Reference
Susan Gold
 
Mutation Testing at BzhJUG
Mutation Testing at BzhJUGMutation Testing at BzhJUG
Mutation Testing at BzhJUG
STAMP Project
 
Navigating the xDD Alphabet Soup
Navigating the xDD Alphabet SoupNavigating the xDD Alphabet Soup
Navigating the xDD Alphabet Soup
Dror Helper
 
Scientific calcultor-Java
Scientific calcultor-JavaScientific calcultor-Java
Scientific calcultor-Java
Shaibal Ahmed
 
Computer Programming- Lecture 4
Computer Programming- Lecture 4Computer Programming- Lecture 4
Computer Programming- Lecture 4
Dr. Md. Shohel Sayeed
 
Simulado java se 7 programmer
Simulado java se 7 programmerSimulado java se 7 programmer
Simulado java se 7 programmer
Miguel Vilaca
 
C++ game development with oxygine
C++ game development with oxygineC++ game development with oxygine
C++ game development with oxygine
corehard_by
 
Lecture 12: Classes and Files
Lecture 12: Classes and FilesLecture 12: Classes and Files
Lecture 12: Classes and Files
Dr. Md. Shohel Sayeed
 
E:\Plp 2009 2\Plp 9
E:\Plp 2009 2\Plp 9E:\Plp 2009 2\Plp 9
E:\Plp 2009 2\Plp 9
Ismar Silveira
 
Kpi driven-java-development-fn conf
Kpi driven-java-development-fn confKpi driven-java-development-fn conf
Kpi driven-java-development-fn conf
Anirban Bhattacharjee
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
Arturo Herrero
 
The Ring programming language version 1.2 book - Part 59 of 84
The Ring programming language version 1.2 book - Part 59 of 84The Ring programming language version 1.2 book - Part 59 of 84
The Ring programming language version 1.2 book - Part 59 of 84
Mahmoud Samir Fayed
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing Speed
Pascal-Louis Perez
 
TDD Hands-on
TDD Hands-onTDD Hands-on
TDD Hands-on
Shuji Watanabe
 
Test-driven JavaScript Development - OPITZ CONSULTING - Tobias Bosch - Stefa...
Test-driven JavaScript Development - OPITZ CONSULTING -  Tobias Bosch - Stefa...Test-driven JavaScript Development - OPITZ CONSULTING -  Tobias Bosch - Stefa...
Test-driven JavaScript Development - OPITZ CONSULTING - Tobias Bosch - Stefa...
OPITZ CONSULTING Deutschland
 
Improving Android Performance at Droidcon UK 2014
Improving Android Performance at Droidcon UK 2014Improving Android Performance at Droidcon UK 2014
Improving Android Performance at Droidcon UK 2014
Raimon Ràfols
 
Some stuff about C++ and development
Some stuff about C++ and developmentSome stuff about C++ and development
Some stuff about C++ and development
Jon Jagger
 
Introduction to Erlang
Introduction to ErlangIntroduction to Erlang
Introduction to Erlang
Gabriele Lana
 
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
corehard_by
 

What's hot (20)

20130530-PEGjs
20130530-PEGjs20130530-PEGjs
20130530-PEGjs
 
Qe Reference
Qe ReferenceQe Reference
Qe Reference
 
Mutation Testing at BzhJUG
Mutation Testing at BzhJUGMutation Testing at BzhJUG
Mutation Testing at BzhJUG
 
Navigating the xDD Alphabet Soup
Navigating the xDD Alphabet SoupNavigating the xDD Alphabet Soup
Navigating the xDD Alphabet Soup
 
Scientific calcultor-Java
Scientific calcultor-JavaScientific calcultor-Java
Scientific calcultor-Java
 
Computer Programming- Lecture 4
Computer Programming- Lecture 4Computer Programming- Lecture 4
Computer Programming- Lecture 4
 
Simulado java se 7 programmer
Simulado java se 7 programmerSimulado java se 7 programmer
Simulado java se 7 programmer
 
C++ game development with oxygine
C++ game development with oxygineC++ game development with oxygine
C++ game development with oxygine
 
Lecture 12: Classes and Files
Lecture 12: Classes and FilesLecture 12: Classes and Files
Lecture 12: Classes and Files
 
E:\Plp 2009 2\Plp 9
E:\Plp 2009 2\Plp 9E:\Plp 2009 2\Plp 9
E:\Plp 2009 2\Plp 9
 
Kpi driven-java-development-fn conf
Kpi driven-java-development-fn confKpi driven-java-development-fn conf
Kpi driven-java-development-fn conf
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 
The Ring programming language version 1.2 book - Part 59 of 84
The Ring programming language version 1.2 book - Part 59 of 84The Ring programming language version 1.2 book - Part 59 of 84
The Ring programming language version 1.2 book - Part 59 of 84
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing Speed
 
TDD Hands-on
TDD Hands-onTDD Hands-on
TDD Hands-on
 
Test-driven JavaScript Development - OPITZ CONSULTING - Tobias Bosch - Stefa...
Test-driven JavaScript Development - OPITZ CONSULTING -  Tobias Bosch - Stefa...Test-driven JavaScript Development - OPITZ CONSULTING -  Tobias Bosch - Stefa...
Test-driven JavaScript Development - OPITZ CONSULTING - Tobias Bosch - Stefa...
 
Improving Android Performance at Droidcon UK 2014
Improving Android Performance at Droidcon UK 2014Improving Android Performance at Droidcon UK 2014
Improving Android Performance at Droidcon UK 2014
 
Some stuff about C++ and development
Some stuff about C++ and developmentSome stuff about C++ and development
Some stuff about C++ and development
 
Introduction to Erlang
Introduction to ErlangIntroduction to Erlang
Introduction to Erlang
 
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
 

Viewers also liked

Segurança no Desenvolvimento de App`s
Segurança no Desenvolvimento de App`sSegurança no Desenvolvimento de App`s
Segurança no Desenvolvimento de App`s
Onyo
 
Linkedin.com DomXss 04-08-2014
Linkedin.com DomXss 04-08-2014Linkedin.com DomXss 04-08-2014
Linkedin.com DomXss 04-08-2014
Giorgio Fedon
 
iOS Masque Attack
iOS Masque AttackiOS Masque Attack
iOS Masque Attack
Minded Security
 
Concrete5 Multiple Reflected XSS Advisory
Concrete5 Multiple Reflected XSS AdvisoryConcrete5 Multiple Reflected XSS Advisory
Concrete5 Multiple Reflected XSS Advisory
Minded Security
 
Concrete5 Sendmail RCE Advisory
Concrete5 Sendmail RCE AdvisoryConcrete5 Sendmail RCE Advisory
Concrete5 Sendmail RCE Advisory
Minded Security
 
Comparing DOM XSS Tools On Real World Bug
Comparing DOM XSS Tools On Real World BugComparing DOM XSS Tools On Real World Bug
Comparing DOM XSS Tools On Real World Bug
Stefano Di Paola
 
Mobile application security – effective methodology, efficient testing! hem...
Mobile application security – effective methodology, efficient testing!   hem...Mobile application security – effective methodology, efficient testing!   hem...
Mobile application security – effective methodology, efficient testing! hem...
owaspindia
 
Mobile Banking Security: Challenges, Solutions
Mobile Banking Security: Challenges, SolutionsMobile Banking Security: Challenges, Solutions
Mobile Banking Security: Challenges, Solutions
Cognizant
 
Advanced JS Deobfuscation
Advanced JS DeobfuscationAdvanced JS Deobfuscation
Advanced JS Deobfuscation
Minded Security
 
Security Testing Mobile Applications
Security Testing Mobile ApplicationsSecurity Testing Mobile Applications
Security Testing Mobile Applications
Denim Group
 
Reverse Engineering iOS apps
Reverse Engineering iOS appsReverse Engineering iOS apps
Reverse Engineering iOS apps
Max Bazaliy
 
The old is new, again. CVE-2011-2461 is back!
The old is new, again. CVE-2011-2461 is back!The old is new, again. CVE-2011-2461 is back!
The old is new, again. CVE-2011-2461 is back!
Luca Carettoni
 
Cybersecurity - Mobile Application Security
Cybersecurity - Mobile Application SecurityCybersecurity - Mobile Application Security
Cybersecurity - Mobile Application Security
Eryk Budi Pratama
 
I Want More Ninja – iOS Security Testing
I Want More Ninja – iOS Security TestingI Want More Ninja – iOS Security Testing
I Want More Ninja – iOS Security Testing
Jason Haddix
 
The curious case of mobile app security.pptx
The curious case of mobile app security.pptxThe curious case of mobile app security.pptx
The curious case of mobile app security.pptx
Ankit Giri
 
AppSec EU 2016: Automated Mobile Application Security Assessment with MobSF
AppSec EU 2016: Automated Mobile Application Security Assessment with MobSFAppSec EU 2016: Automated Mobile Application Security Assessment with MobSF
AppSec EU 2016: Automated Mobile Application Security Assessment with MobSF
Ajin Abraham
 
Mobile Application Security Testing, Testing for Mobility App | www.idexcel.com
Mobile Application Security Testing, Testing for Mobility App | www.idexcel.comMobile Application Security Testing, Testing for Mobility App | www.idexcel.com
Mobile Application Security Testing, Testing for Mobility App | www.idexcel.com
Idexcel Technologies
 
Pentesting iOS Applications
Pentesting iOS ApplicationsPentesting iOS Applications
Pentesting iOS Applications
jasonhaddix
 
Mobile Application Security
Mobile Application SecurityMobile Application Security
Mobile Application Security
cclark_isec
 
Automated Security Analysis of Android & iOS Applications with Mobile Securit...
Automated Security Analysis of Android & iOS Applications with Mobile Securit...Automated Security Analysis of Android & iOS Applications with Mobile Securit...
Automated Security Analysis of Android & iOS Applications with Mobile Securit...
Ajin Abraham
 

Viewers also liked (20)

Segurança no Desenvolvimento de App`s
Segurança no Desenvolvimento de App`sSegurança no Desenvolvimento de App`s
Segurança no Desenvolvimento de App`s
 
Linkedin.com DomXss 04-08-2014
Linkedin.com DomXss 04-08-2014Linkedin.com DomXss 04-08-2014
Linkedin.com DomXss 04-08-2014
 
iOS Masque Attack
iOS Masque AttackiOS Masque Attack
iOS Masque Attack
 
Concrete5 Multiple Reflected XSS Advisory
Concrete5 Multiple Reflected XSS AdvisoryConcrete5 Multiple Reflected XSS Advisory
Concrete5 Multiple Reflected XSS Advisory
 
Concrete5 Sendmail RCE Advisory
Concrete5 Sendmail RCE AdvisoryConcrete5 Sendmail RCE Advisory
Concrete5 Sendmail RCE Advisory
 
Comparing DOM XSS Tools On Real World Bug
Comparing DOM XSS Tools On Real World BugComparing DOM XSS Tools On Real World Bug
Comparing DOM XSS Tools On Real World Bug
 
Mobile application security – effective methodology, efficient testing! hem...
Mobile application security – effective methodology, efficient testing!   hem...Mobile application security – effective methodology, efficient testing!   hem...
Mobile application security – effective methodology, efficient testing! hem...
 
Mobile Banking Security: Challenges, Solutions
Mobile Banking Security: Challenges, SolutionsMobile Banking Security: Challenges, Solutions
Mobile Banking Security: Challenges, Solutions
 
Advanced JS Deobfuscation
Advanced JS DeobfuscationAdvanced JS Deobfuscation
Advanced JS Deobfuscation
 
Security Testing Mobile Applications
Security Testing Mobile ApplicationsSecurity Testing Mobile Applications
Security Testing Mobile Applications
 
Reverse Engineering iOS apps
Reverse Engineering iOS appsReverse Engineering iOS apps
Reverse Engineering iOS apps
 
The old is new, again. CVE-2011-2461 is back!
The old is new, again. CVE-2011-2461 is back!The old is new, again. CVE-2011-2461 is back!
The old is new, again. CVE-2011-2461 is back!
 
Cybersecurity - Mobile Application Security
Cybersecurity - Mobile Application SecurityCybersecurity - Mobile Application Security
Cybersecurity - Mobile Application Security
 
I Want More Ninja – iOS Security Testing
I Want More Ninja – iOS Security TestingI Want More Ninja – iOS Security Testing
I Want More Ninja – iOS Security Testing
 
The curious case of mobile app security.pptx
The curious case of mobile app security.pptxThe curious case of mobile app security.pptx
The curious case of mobile app security.pptx
 
AppSec EU 2016: Automated Mobile Application Security Assessment with MobSF
AppSec EU 2016: Automated Mobile Application Security Assessment with MobSFAppSec EU 2016: Automated Mobile Application Security Assessment with MobSF
AppSec EU 2016: Automated Mobile Application Security Assessment with MobSF
 
Mobile Application Security Testing, Testing for Mobility App | www.idexcel.com
Mobile Application Security Testing, Testing for Mobility App | www.idexcel.comMobile Application Security Testing, Testing for Mobility App | www.idexcel.com
Mobile Application Security Testing, Testing for Mobility App | www.idexcel.com
 
Pentesting iOS Applications
Pentesting iOS ApplicationsPentesting iOS Applications
Pentesting iOS Applications
 
Mobile Application Security
Mobile Application SecurityMobile Application Security
Mobile Application Security
 
Automated Security Analysis of Android & iOS Applications with Mobile Securit...
Automated Security Analysis of Android & iOS Applications with Mobile Securit...Automated Security Analysis of Android & iOS Applications with Mobile Securit...
Automated Security Analysis of Android & iOS Applications with Mobile Securit...
 

Similar to Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK

Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK
Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDKEric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK
Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK
GuardSquare
 
Droidcon2013 pro guard, optimizer and obfuscator in the android sdk_eric lafo...
Droidcon2013 pro guard, optimizer and obfuscator in the android sdk_eric lafo...Droidcon2013 pro guard, optimizer and obfuscator in the android sdk_eric lafo...
Droidcon2013 pro guard, optimizer and obfuscator in the android sdk_eric lafo...
Droidcon Berlin
 
Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015
Lin Yo-An
 
DeVry GSP 115 All Assignments latest
DeVry GSP 115 All Assignments latestDeVry GSP 115 All Assignments latest
DeVry GSP 115 All Assignments latest
Atifkhilji
 
Assignment #2.classpathAssignment #2.project Assig.docx
Assignment #2.classpathAssignment #2.project  Assig.docxAssignment #2.classpathAssignment #2.project  Assig.docx
Assignment #2.classpathAssignment #2.project Assig.docx
fredharris32
 
FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6
FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6
FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6
FrontDays
 
C++ Question on References and Function Overloading
C++ Question on References and Function OverloadingC++ Question on References and Function Overloading
C++ Question on References and Function Overloading
mohamed sikander
 
The following is the (incomplete) header file for the class Fracti.pdf
The following is the (incomplete) header file for the class Fracti.pdfThe following is the (incomplete) header file for the class Fracti.pdf
The following is the (incomplete) header file for the class Fracti.pdf
4babies2010
 
Pruning your code
Pruning your codePruning your code
Pruning your code
Frikkie van Biljon
 
Kinect v2 Introduction and Tutorial
Kinect v2 Introduction and TutorialKinect v2 Introduction and Tutorial
Kinect v2 Introduction and Tutorial
Tsukasa Sugiura
 
Compiler Optimization Presentation
Compiler Optimization PresentationCompiler Optimization Presentation
Compiler Optimization Presentation
19magnet
 
"Развитие ветки PHP-7"
"Развитие ветки PHP-7""Развитие ветки PHP-7"
"Развитие ветки PHP-7"
Badoo Development
 
How to practice functional programming in react
How to practice functional programming in reactHow to practice functional programming in react
How to practice functional programming in react
Netta Bondy
 
Facts about multithreading that'll keep you up at night - Guy Bar on, Vonage
Facts about multithreading that'll keep you up at night - Guy Bar on, VonageFacts about multithreading that'll keep you up at night - Guy Bar on, Vonage
Facts about multithreading that'll keep you up at night - Guy Bar on, Vonage
Codemotion Tel Aviv
 
2.1 ### uVision Project, (C) Keil Software .docx
2.1   ### uVision Project, (C) Keil Software    .docx2.1   ### uVision Project, (C) Keil Software    .docx
2.1 ### uVision Project, (C) Keil Software .docx
tarifarmarie
 
Nagios Conference 2012 - Dave Josephsen - Stop Being Lazy
Nagios Conference 2012 - Dave Josephsen - Stop Being LazyNagios Conference 2012 - Dave Josephsen - Stop Being Lazy
Nagios Conference 2012 - Dave Josephsen - Stop Being Lazy
Nagios
 
Refactoring
RefactoringRefactoring
Refactoring
Amir Barylko
 
DeVry GSP 115 Week 3 Assignment latest
DeVry GSP 115 Week 3 Assignment latestDeVry GSP 115 Week 3 Assignment latest
DeVry GSP 115 Week 3 Assignment latest
Atifkhilji
 
C++ aptitude
C++ aptitudeC++ aptitude
C++ aptitude
chetan_p211
 
Beyond unit tests: Testing for Spark/Hadoop Workflows with Shankar Manian Ana...
Beyond unit tests: Testing for Spark/Hadoop Workflows with Shankar Manian Ana...Beyond unit tests: Testing for Spark/Hadoop Workflows with Shankar Manian Ana...
Beyond unit tests: Testing for Spark/Hadoop Workflows with Shankar Manian Ana...
Spark Summit
 

Similar to Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK (20)

Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK
Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDKEric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK
Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK
 
Droidcon2013 pro guard, optimizer and obfuscator in the android sdk_eric lafo...
Droidcon2013 pro guard, optimizer and obfuscator in the android sdk_eric lafo...Droidcon2013 pro guard, optimizer and obfuscator in the android sdk_eric lafo...
Droidcon2013 pro guard, optimizer and obfuscator in the android sdk_eric lafo...
 
Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015Code Generation in PHP - PHPConf 2015
Code Generation in PHP - PHPConf 2015
 
DeVry GSP 115 All Assignments latest
DeVry GSP 115 All Assignments latestDeVry GSP 115 All Assignments latest
DeVry GSP 115 All Assignments latest
 
Assignment #2.classpathAssignment #2.project Assig.docx
Assignment #2.classpathAssignment #2.project  Assig.docxAssignment #2.classpathAssignment #2.project  Assig.docx
Assignment #2.classpathAssignment #2.project Assig.docx
 
FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6
FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6
FrontDays #3. Иван Федяев, Эволюция JavaScript. Обзор нововведений ECMAScript 6
 
C++ Question on References and Function Overloading
C++ Question on References and Function OverloadingC++ Question on References and Function Overloading
C++ Question on References and Function Overloading
 
The following is the (incomplete) header file for the class Fracti.pdf
The following is the (incomplete) header file for the class Fracti.pdfThe following is the (incomplete) header file for the class Fracti.pdf
The following is the (incomplete) header file for the class Fracti.pdf
 
Pruning your code
Pruning your codePruning your code
Pruning your code
 
Kinect v2 Introduction and Tutorial
Kinect v2 Introduction and TutorialKinect v2 Introduction and Tutorial
Kinect v2 Introduction and Tutorial
 
Compiler Optimization Presentation
Compiler Optimization PresentationCompiler Optimization Presentation
Compiler Optimization Presentation
 
"Развитие ветки PHP-7"
"Развитие ветки PHP-7""Развитие ветки PHP-7"
"Развитие ветки PHP-7"
 
How to practice functional programming in react
How to practice functional programming in reactHow to practice functional programming in react
How to practice functional programming in react
 
Facts about multithreading that'll keep you up at night - Guy Bar on, Vonage
Facts about multithreading that'll keep you up at night - Guy Bar on, VonageFacts about multithreading that'll keep you up at night - Guy Bar on, Vonage
Facts about multithreading that'll keep you up at night - Guy Bar on, Vonage
 
2.1 ### uVision Project, (C) Keil Software .docx
2.1   ### uVision Project, (C) Keil Software    .docx2.1   ### uVision Project, (C) Keil Software    .docx
2.1 ### uVision Project, (C) Keil Software .docx
 
Nagios Conference 2012 - Dave Josephsen - Stop Being Lazy
Nagios Conference 2012 - Dave Josephsen - Stop Being LazyNagios Conference 2012 - Dave Josephsen - Stop Being Lazy
Nagios Conference 2012 - Dave Josephsen - Stop Being Lazy
 
Refactoring
RefactoringRefactoring
Refactoring
 
DeVry GSP 115 Week 3 Assignment latest
DeVry GSP 115 Week 3 Assignment latestDeVry GSP 115 Week 3 Assignment latest
DeVry GSP 115 Week 3 Assignment latest
 
C++ aptitude
C++ aptitudeC++ aptitude
C++ aptitude
 
Beyond unit tests: Testing for Spark/Hadoop Workflows with Shankar Manian Ana...
Beyond unit tests: Testing for Spark/Hadoop Workflows with Shankar Manian Ana...Beyond unit tests: Testing for Spark/Hadoop Workflows with Shankar Manian Ana...
Beyond unit tests: Testing for Spark/Hadoop Workflows with Shankar Manian Ana...
 

Recently uploaded

Lecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptxLecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptx
TaghreedAltamimi
 
Transform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR SolutionsTransform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR Solutions
TheSMSPoint
 
Odoo ERP Vs. Traditional ERP Systems – A Comparative Analysis
Odoo ERP Vs. Traditional ERP Systems – A Comparative AnalysisOdoo ERP Vs. Traditional ERP Systems – A Comparative Analysis
Odoo ERP Vs. Traditional ERP Systems – A Comparative Analysis
Envertis Software Solutions
 
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit ParisNeo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Łukasz Chruściel
 
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdfTop Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
VALiNTRY360
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Crescat
 
How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?
ToXSL Technologies
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
Green Software Development
 
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s EcosystemUI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
Peter Muessig
 
GreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-JurisicGreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-Jurisic
Green Software Development
 
socradar-q1-2024-aviation-industry-report.pdf
socradar-q1-2024-aviation-industry-report.pdfsocradar-q1-2024-aviation-industry-report.pdf
socradar-q1-2024-aviation-industry-report.pdf
SOCRadar
 
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
XfilesPro
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
Green Software Development
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Julian Hyde
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
Shane Coughlan
 
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian CompaniesE-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
Quickdice ERP
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
Deuglo Infosystem Pvt Ltd
 
SQL Accounting Software Brochure Malaysia
SQL Accounting Software Brochure MalaysiaSQL Accounting Software Brochure Malaysia
SQL Accounting Software Brochure Malaysia
GohKiangHock
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
Grant Fritchey
 

Recently uploaded (20)

Lecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptxLecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptx
 
Transform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR SolutionsTransform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR Solutions
 
Odoo ERP Vs. Traditional ERP Systems – A Comparative Analysis
Odoo ERP Vs. Traditional ERP Systems – A Comparative AnalysisOdoo ERP Vs. Traditional ERP Systems – A Comparative Analysis
Odoo ERP Vs. Traditional ERP Systems – A Comparative Analysis
 
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit ParisNeo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
 
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdfTop Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
 
How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
 
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s EcosystemUI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
 
GreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-JurisicGreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-Jurisic
 
socradar-q1-2024-aviation-industry-report.pdf
socradar-q1-2024-aviation-industry-report.pdfsocradar-q1-2024-aviation-industry-report.pdf
socradar-q1-2024-aviation-industry-report.pdf
 
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
Everything You Need to Know About X-Sign: The eSign Functionality of XfilesPr...
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
 
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian CompaniesE-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
 
SQL Accounting Software Brochure Malaysia
SQL Accounting Software Brochure MalaysiaSQL Accounting Software Brochure Malaysia
SQL Accounting Software Brochure Malaysia
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
 

Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK

  • 1. #mceconf #mce-proguard 11 Jan 2014 ProGuard Optimizer and Obfuscator in the Android SDK Eric Lafortune Developer of ProGuard Technical director at Saikoa
  • 2. #mceconf #mce-proguard 11 Jan 2014 ProGuard Generic Shrinker Optimizer Obfuscator For Java bytecode Open source
  • 3. #mceconf #mce-proguard 11 Jan 2014 ProGuard history Java applications Applets 2002 Midlets 2010 2012 Android apps ● May 2002 First release ● Sep 2010 Recommended for protecting LVL ● Dec 2010 Part of Android SDK ● Jan 2012 Startup Saikoa
  • 4. #mceconf #mce-proguard 11 Jan 2014 ProGuard Application code Libraries Runtime libraries Shrink Optimize Obfuscate Processed code Runtime libraries
  • 5. #mceconf #mce-proguard 11 Jan 2014 ProGuard in Android builds Application Java bytecode ProGuard Libraries Java bytecode Processed Java bytecode Dex Dalvik bytecode Javac Application Java source Libraries Java bytecode XML resources Assets Assets Compiled XML resourcesAapt
  • 6. #mceconf #mce-proguard 11 Jan 2014 Why use ProGuard? ● Application size ● Performance ● Remove logging, debugging, testing code ● Protection
  • 7. #mceconf #mce-proguard 11 Jan 2014 Application size classes.dex size .apk size Without ProGuard With ProGuard Reduction ApiDemos 716 K 482 K 33 % 2.6 M 2.5 M 4 % GoogleIO App 3.4 M 905 K 75 % 1.9 M 906 K 53 % ApiDemos in Scala* ~6 M 542 K ~90 % ~8 M 2.5 M ~70 % * [Stéphane Micheloud, http://lampwww.epfl.ch/~michelou/android/library-code-shrinking.html]
  • 8. #mceconf #mce-proguard 11 Jan 2014 Performance: CaffeineMark Without ProGuard Sieve score = 6833 Loop score = 14831 Logic score = 19038 String score = 7694 Float score = 6425 Method score = 4850 Overall score = 8794 With ProGuard Sieve score = 6666 Loop score = 15473 Logic score = 47840 String score = 7717 Float score = 6488 Method score = 5229 Overall score = 10436 Improvement: 18% [Acer Iconia Tab A500, nVidia Tegra 2, 1.0 GHz, Android 3.2.1]
  • 9. #mceconf #mce-proguard 11 Jan 2014 Results ● Size reduction: – Code (classes.dex): 20 … 90% – Application (.apk): 5 ... 70% ● Performance improvements: 0 … 20%
  • 10. #mceconf #mce-proguard 11 Jan 2014 How to enable ProGuard? Ant and Eclipse: project.properties → only applied when building release versions # To enable ProGuard to shrink and obfuscate your code, uncomment this #proguard.config= ${sdk.dir}/tools/proguard/proguard-android.txt: proguard-project.txt # To enable ProGuard to shrink and obfuscate your code, uncomment this #proguard.config= ${sdk.dir}/tools/proguard/proguard-android.txt: proguard-project.txt Tip
  • 11. #mceconf #mce-proguard 11 Jan 2014 How to enable ProGuard? Gradle: build.gradle → completely flexible android { buildTypes { release { runProguard true proguardFile getDefaultProguardFile('proguard-android.txt') } } productFlavors { some_flavor { proguardFile 'proguard-project.txt' } } } android { buildTypes { release { runProguard true proguardFile getDefaultProguardFile('proguard-android.txt') } } productFlavors { some_flavor { proguardFile 'proguard-project.txt' } } } New
  • 12. #mceconf #mce-proguard 11 Jan 2014 Notes and warnings “Closed-world assumption” → if debug build works fine, then ok to ignore in proguard-project.txt: Warning: com.dropbox.client2.DropboxAPI: can't find referenced class org.json.simple.JSONArray Warning: com.dropbox.client2.DropboxAPI: can't find referenced class org.json.simple.JSONArray -dontwarn twitter4j.internal.logging.** -dontwarn com.dropbox.client2.** -dontwarn twitter4j.internal.logging.** -dontwarn com.dropbox.client2.** Warning: twitter4j.internal.logging.Log4JLoggerFactory: can't find referenced class org.apache.log4j.Logger Warning: twitter4j.internal.logging.SLF4JLoggerFactory: can't find referenced class org.slf4j.LoggerFactory ... Warning: twitter4j.internal.logging.Log4JLoggerFactory: can't find referenced class org.apache.log4j.Logger Warning: twitter4j.internal.logging.SLF4JLoggerFactory: can't find referenced class org.slf4j.LoggerFactory ... Tip
  • 13. #mceconf #mce-proguard 11 Jan 2014 Notes and warnings Straight to the Troubleshooting page: Warning: there were 12 unresolved references to classes or interfaces. You may need to add missing library jars or update their versions. If your code works fine without the missing classes, you can suppress the warnings with '-dontwarn' options. (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedclass) Warning: there were 12 unresolved references to classes or interfaces. You may need to add missing library jars or update their versions. If your code works fine without the missing classes, you can suppress the warnings with '-dontwarn' options. (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedclass) New
  • 14. #mceconf #mce-proguard 11 Jan 2014 Shrinking Also called treeshaking, minimizing, shrouding
  • 15. #mceconf #mce-proguard 11 Jan 2014 Shrinking ● Classes, fields, methods
  • 16. #mceconf #mce-proguard 11 Jan 2014 Entry points 1) Activities, applications, services, fragments,... → provided automatically by Android build process -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.app.Activity -keep public class * extends android.app.Application -keep public class * extends android.app.Service …
  • 17. #mceconf #mce-proguard 11 Jan 2014 Entry points 2) Introspection, e.g. Guice, RoboGuice → must be specified in proguard-project.txt: -keepclassmembers class * { @javax.inject.** <fields>; @com.google.inject.** <fields>; @roboguice.** <fields>; @roboguice.event.Observes <methods>; } -keepclassmembers class * { @javax.inject.** <fields>; @com.google.inject.** <fields>; @roboguice.** <fields>; @roboguice.event.Observes <methods>; } Tip
  • 18. #mceconf #mce-proguard 11 Jan 2014 Optimization At the bytecode instruction level: ● Dead code elimination ● Constant propagation ● Method inlining ● Class merging ● Remove logging code ● Peephole optimizations ● Devirtualization ● ...
  • 19. #mceconf #mce-proguard 11 Jan 2014 Optimization example int answer = computeAnswer(1, 2, 3, 7);int answer = computeAnswer(1, 2, 3, 7); int computeAnswer(int f1, int f2, int f3, int f4) { if (f2 == 1 && f3 == 1 && f4 == 1) { return f1; } else { return computeAnswer(f1 * f2, f3, f4, 1); } } int computeAnswer(int f1, int f2, int f3, int f4) { if (f2 == 1 && f3 == 1 && f4 == 1) { return f1; } else { return computeAnswer(f1 * f2, f3, f4, 1); } }
  • 20. #mceconf #mce-proguard 11 Jan 2014 Optimization example int answer = computeAnswer(1, 2, 3, 7);int answer = computeAnswer(1, 2, 3, 7); int computeAnswer(int f1, int f2, int f3, int f4) { if (f2 == 1 && f3 == 1 && f4 == 1) { return f1; } else { return computeAnswer(f1 * f2, f3, f4, 1); } } int computeAnswer(int f1, int f2, int f3, int f4) { if (f2 == 1 && f3 == 1 && f4 == 1) { return f1; } else { return computeAnswer(f1 * f2, f3, f4, 1); } } int computeAnswer(int f1, int f2, int f3, int f4) { do { if (f2 == 1 && f3 == 1 && f4 == 1) { return f1; } else { f1 = f1 * f2; f2 = f3, f3 = f4, f4 = 1; } } while (true); } int computeAnswer(int f1, int f2, int f3, int f4) { do { if (f2 == 1 && f3 == 1 && f4 == 1) { return f1; } else { f1 = f1 * f2; f2 = f3, f3 = f4, f4 = 1; } } while (true); }
  • 21. #mceconf #mce-proguard 11 Jan 2014 Optimization example int answer = computeAnswer(1, 2, 3, 7);int answer = computeAnswer(1, 2, 3, 7); int computeAnswer(int f1, int f2, int f3, int f4) { if (f2 == 1 && f3 == 1 && f4 == 1) { return f1; } else { return computeAnswer(f1 * f2, f3, f4, 1); } } int computeAnswer(int f1, int f2, int f3, int f4) { if (f2 == 1 && f3 == 1 && f4 == 1) { return f1; } else { return computeAnswer(f1 * f2, f3, f4, 1); } } int computeAnswer(int f1, int f2, int f3, int f4) { do { if (f2 == 1 && f3 == 1 && f4 == 1) { return f1; } else { f1 = f1 * f2; f2 = f3, f3 = f4, f4 = 1; } } while (true); } int computeAnswer(int f1, int f2, int f3, int f4) { do { if (f2 == 1 && f3 == 1 && f4 == 1) { return f1; } else { f1 = f1 * f2; f2 = f3, f3 = f4, f4 = 1; } } while (true); }
  • 22. #mceconf #mce-proguard 11 Jan 2014 Optimization example int answer = computeAnswer(1, 2, 3, 7);int answer = computeAnswer(1, 2, 3, 7); int computeAnswer(int f1, int f2, int f3, int f4) { if (f2 == 1 && f3 == 1 && f4 == 1) { return f1; } else { return computeAnswer(f1 * f2, f3, f4, 1); } } int computeAnswer(int f1, int f2, int f3, int f4) { if (f2 == 1 && f3 == 1 && f4 == 1) { return f1; } else { return computeAnswer(f1 * f2, f3, f4, 1); } } int computeAnswer(int f1, int f2, int f3, int f4) { do { if (f2 == 1 && f3 == 1 && f4 == 1) { return f1; } else { f1 = f1 * f2; f2 = f3, f3 = f4, f4 = 1; } } while (true); } int computeAnswer(int f1, int f2, int f3, int f4) { do { if (f2 == 1 && f3 == 1 && f4 == 1) { return f1; } else { f1 = f1 * f2; f2 = f3, f3 = f4, f4 = 1; } } while (true); } int computeAnswer() { return 42; } int computeAnswer() { return 42; }
  • 23. #mceconf #mce-proguard 11 Jan 2014 Optimization example int answer = computeAnswer(1, 2, 3, 7);int answer = computeAnswer(1, 2, 3, 7); int computeAnswer(int f1, int f2, int f3, int f4) { if (f2 == 1 && f3 == 1 && f4 == 1) { return f1; } else { return computeAnswer(f1 * f2, f3, f4, 1); } } int computeAnswer(int f1, int f2, int f3, int f4) { if (f2 == 1 && f3 == 1 && f4 == 1) { return f1; } else { return computeAnswer(f1 * f2, f3, f4, 1); } } int computeAnswer(int f1, int f2, int f3, int f4) { do { if (f2 == 1 && f3 == 1 && f4 == 1) { return f1; } else { f1 = f1 * f2; f2 = f3, f3 = f4, f4 = 1; } } while (true); } int computeAnswer(int f1, int f2, int f3, int f4) { do { if (f2 == 1 && f3 == 1 && f4 == 1) { return f1; } else { f1 = f1 * f2; f2 = f3, f3 = f4, f4 = 1; } } while (true); } int computeAnswer() { return 42; } int computeAnswer() { return 42; } int answer = 42;int answer = 42;
  • 24. #mceconf #mce-proguard 11 Jan 2014 Optimization: enum int answer = getAnswer(MyEnum.GREEN);int answer = getAnswer(MyEnum.GREEN); int getAnswer(MyEnum e) { switch (e) { case RED: return 1; case GREEN: return 42; default: return 0; } } int getAnswer(MyEnum e) { switch (e) { case RED: return 1; case GREEN: return 42; default: return 0; } } enum MyEnum { RED, GREEN, BLUE } enum MyEnum { RED, GREEN, BLUE } New
  • 25. #mceconf #mce-proguard 11 Jan 2014 Optimization: enum int answer = getAnswer(MyEnum.GREEN);int answer = getAnswer(MyEnum.GREEN); int getAnswer(MyEnum e) { switch (e) { case RED: return 1; case GREEN: return 42; default: return 0; } } int getAnswer(MyEnum e) { switch (e) { case RED: return 1; case GREEN: return 42; default: return 0; } } enum MyEnum { RED, GREEN, BLUE } enum MyEnum { RED, GREEN, BLUE } class MyEnum { static final MyEnum RED = new MyEnum(“RED”, 0); static final MyEnum GREEN = new MyEnum(“GREEN”, 0); static final MyEnum BLUE = new MyEnum(“BLUE”, 0); static final MyEnum[] $VALUES = new MyEnum[] { RED, GREEN, BLUE }; ... } class MyEnum { static final MyEnum RED = new MyEnum(“RED”, 0); static final MyEnum GREEN = new MyEnum(“GREEN”, 0); static final MyEnum BLUE = new MyEnum(“BLUE”, 0); static final MyEnum[] $VALUES = new MyEnum[] { RED, GREEN, BLUE }; ... } New
  • 26. #mceconf #mce-proguard 11 Jan 2014 Optimization: enum int answer = getAnswer(MyEnum.GREEN);int answer = getAnswer(MyEnum.GREEN); int getAnswer(MyEnum e) { switch (e) { case RED: return 1; case GREEN: return 42; default: return 0; } } int getAnswer(MyEnum e) { switch (e) { case RED: return 1; case GREEN: return 42; default: return 0; } } enum MyEnum { RED, GREEN, BLUE } enum MyEnum { RED, GREEN, BLUE } int getAnswer(MyEnum e) { switch (Internal.$SwitchMap[e.ordinal()]) { case 1: return 1; case 2: return 42; default: return 0; } } int getAnswer(MyEnum e) { switch (Internal.$SwitchMap[e.ordinal()]) { case 1: return 1; case 2: return 42; default: return 0; } } class MyEnum { static final MyEnum RED = new MyEnum(“RED”, 0); static final MyEnum GREEN = new MyEnum(“GREEN”, 0); static final MyEnum BLUE = new MyEnum(“BLUE”, 0); static final MyEnum[] $VALUES = new MyEnum[] { RED, GREEN, BLUE }; ... } class MyEnum { static final MyEnum RED = new MyEnum(“RED”, 0); static final MyEnum GREEN = new MyEnum(“GREEN”, 0); static final MyEnum BLUE = new MyEnum(“BLUE”, 0); static final MyEnum[] $VALUES = new MyEnum[] { RED, GREEN, BLUE }; ... } class Internal { static final int[] $SwitchMap new int[MyEnum.values().length]; static { $SwitchMap[MyEnum.GREEN.ordinal()] = 1; $SwitchMap[MyEnum.RED.ordinal()] = 2; } } class Internal { static final int[] $SwitchMap new int[MyEnum.values().length]; static { $SwitchMap[MyEnum.GREEN.ordinal()] = 1; $SwitchMap[MyEnum.RED.ordinal()] = 2; } } New
  • 27. #mceconf #mce-proguard 11 Jan 2014 Optimization: enum int answer = getAnswer(MyEnum.GREEN);int answer = getAnswer(MyEnum.GREEN); int getAnswer(MyEnum e) { switch (e) { case RED: return 1; case GREEN: return 42; default: return 0; } } int getAnswer(MyEnum e) { switch (e) { case RED: return 1; case GREEN: return 42; default: return 0; } } enum MyEnum { RED, GREEN, BLUE } enum MyEnum { RED, GREEN, BLUE } int getAnswer(MyEnum e) { switch (Internal.$SwitchMap[e.ordinal()]) { case 1: return 1; case 2: return 42; default: return 0; } } int getAnswer(MyEnum e) { switch (Internal.$SwitchMap[e.ordinal()]) { case 1: return 1; case 2: return 42; default: return 0; } } class MyEnum { static final MyEnum RED = new MyEnum(“RED”, 0); static final MyEnum GREEN = new MyEnum(“GREEN”, 0); static final MyEnum BLUE = new MyEnum(“BLUE”, 0); static final MyEnum[] $VALUES = new MyEnum[] { RED, GREEN, BLUE }; ... } class MyEnum { static final MyEnum RED = new MyEnum(“RED”, 0); static final MyEnum GREEN = new MyEnum(“GREEN”, 0); static final MyEnum BLUE = new MyEnum(“BLUE”, 0); static final MyEnum[] $VALUES = new MyEnum[] { RED, GREEN, BLUE }; ... } class Internal { static final int[] $SwitchMap new int[MyEnum.values().length]; static { $SwitchMap[MyEnum.GREEN.ordinal()] = 1; $SwitchMap[MyEnum.RED.ordinal()] = 2; } } class Internal { static final int[] $SwitchMap new int[MyEnum.values().length]; static { $SwitchMap[MyEnum.GREEN.ordinal()] = 1; $SwitchMap[MyEnum.RED.ordinal()] = 2; } } int answer = getAnswer(2);int answer = getAnswer(2); int getAnswer(int e) { switch (Internal.$SwitchMap[e]) { case 1: return 1; case 2: return 42; default: return 0; } } int getAnswer(int e) { switch (Internal.$SwitchMap[e]) { case 1: return 1; case 2: return 42; default: return 0; } } New class Internal { static final int[] $SwitchMap = new int[3]; static { $SwitchMap[1] = 1; $SwitchMap[2] = 2; } } class Internal { static final int[] $SwitchMap = new int[3]; static { $SwitchMap[1] = 1; $SwitchMap[2] = 2; } }
  • 28. #mceconf #mce-proguard 11 Jan 2014 Optimization: enum int answer = getAnswer(MyEnum.GREEN);int answer = getAnswer(MyEnum.GREEN); int getAnswer(MyEnum e) { switch (e) { case RED: return 1; case GREEN: return 42; default: return 0; } } int getAnswer(MyEnum e) { switch (e) { case RED: return 1; case GREEN: return 42; default: return 0; } } enum MyEnum { RED, GREEN, BLUE } enum MyEnum { RED, GREEN, BLUE } int getAnswer(MyEnum e) { switch (Internal.$SwitchMap[e.ordinal()]) { case 1: return 1; case 2: return 42; default: return 0; } } int getAnswer(MyEnum e) { switch (Internal.$SwitchMap[e.ordinal()]) { case 1: return 1; case 2: return 42; default: return 0; } } class MyEnum { static final MyEnum RED = new MyEnum(“RED”, 0); static final MyEnum GREEN = new MyEnum(“GREEN”, 0); static final MyEnum BLUE = new MyEnum(“BLUE”, 0); static final MyEnum[] $VALUES = new MyEnum[] { RED, GREEN, BLUE }; ... } class MyEnum { static final MyEnum RED = new MyEnum(“RED”, 0); static final MyEnum GREEN = new MyEnum(“GREEN”, 0); static final MyEnum BLUE = new MyEnum(“BLUE”, 0); static final MyEnum[] $VALUES = new MyEnum[] { RED, GREEN, BLUE }; ... } class Internal { static final int[] $SwitchMap new int[MyEnum.values().length]; static { $SwitchMap[MyEnum.GREEN.ordinal()] = 1; $SwitchMap[MyEnum.RED.ordinal()] = 2; } } class Internal { static final int[] $SwitchMap new int[MyEnum.values().length]; static { $SwitchMap[MyEnum.GREEN.ordinal()] = 1; $SwitchMap[MyEnum.RED.ordinal()] = 2; } } int answer = getAnswer(2);int answer = getAnswer(2); int getAnswer(int e) { switch (Internal.$SwitchMap[e]) { case 1: return 1; case 2: return 42; default: return 0; } } int getAnswer(int e) { switch (Internal.$SwitchMap[e]) { case 1: return 1; case 2: return 42; default: return 0; } } int getAnswer(int e) { switch (e) { case 1: return 1; case 2: return 42; default: return 0; } } int getAnswer(int e) { switch (e) { case 1: return 1; case 2: return 42; default: return 0; } } New class Internal { static final int[] $SwitchMap = new int[3]; static { $SwitchMap[1] = 1; $SwitchMap[2] = 2; } } class Internal { static final int[] $SwitchMap = new int[3]; static { $SwitchMap[1] = 1; $SwitchMap[2] = 2; } }
  • 29. #mceconf #mce-proguard 11 Jan 2014 Optimization: enum int answer = getAnswer(MyEnum.GREEN);int answer = getAnswer(MyEnum.GREEN); int getAnswer(MyEnum e) { switch (e) { case RED: return 1; case GREEN: return 42; default: return 0; } } int getAnswer(MyEnum e) { switch (e) { case RED: return 1; case GREEN: return 42; default: return 0; } } enum MyEnum { RED, GREEN, BLUE } enum MyEnum { RED, GREEN, BLUE } int getAnswer(MyEnum e) { switch (Internal.$SwitchMap[e.ordinal()]) { case 1: return 1; case 2: return 42; default: return 0; } } int getAnswer(MyEnum e) { switch (Internal.$SwitchMap[e.ordinal()]) { case 1: return 1; case 2: return 42; default: return 0; } } class MyEnum { static final MyEnum RED = new MyEnum(“RED”, 0); static final MyEnum GREEN = new MyEnum(“GREEN”, 0); static final MyEnum BLUE = new MyEnum(“BLUE”, 0); static final MyEnum[] $VALUES = new MyEnum[] { RED, GREEN, BLUE }; ... } class MyEnum { static final MyEnum RED = new MyEnum(“RED”, 0); static final MyEnum GREEN = new MyEnum(“GREEN”, 0); static final MyEnum BLUE = new MyEnum(“BLUE”, 0); static final MyEnum[] $VALUES = new MyEnum[] { RED, GREEN, BLUE }; ... } class Internal { static final int[] $SwitchMap new int[MyEnum.values().length]; static { $SwitchMap[MyEnum.GREEN.ordinal()] = 1; $SwitchMap[MyEnum.RED.ordinal()] = 2; } } class Internal { static final int[] $SwitchMap new int[MyEnum.values().length]; static { $SwitchMap[MyEnum.GREEN.ordinal()] = 1; $SwitchMap[MyEnum.RED.ordinal()] = 2; } } int answer = getAnswer(2);int answer = getAnswer(2); int getAnswer(int e) { switch (Internal.$SwitchMap[e]) { case 1: return 1; case 2: return 42; default: return 0; } } int getAnswer(int e) { switch (Internal.$SwitchMap[e]) { case 1: return 1; case 2: return 42; default: return 0; } } int getAnswer(int e) { switch (e) { case 1: return 1; case 2: return 42; default: return 0; } } int getAnswer(int e) { switch (e) { case 1: return 1; case 2: return 42; default: return 0; } } int answer = 42;int answer = 42; New class Internal { static final int[] $SwitchMap = new int[3]; static { $SwitchMap[1] = 1; $SwitchMap[2] = 2; } } class Internal { static final int[] $SwitchMap = new int[3]; static { $SwitchMap[1] = 1; $SwitchMap[2] = 2; } }
  • 30. #mceconf #mce-proguard 11 Jan 2014 How to enable optimization? Ant and Eclipse: project.properties Tip # To enable ProGuard to shrink and obfuscate your code, uncomment this proguard.config= ${sdk.dir}/tools/proguard/proguard-android-optimize.txt: proguard-project.txt # To enable ProGuard to shrink and obfuscate your code, uncomment this proguard.config= ${sdk.dir}/tools/proguard/proguard-android-optimize.txt: proguard-project.txt
  • 31. #mceconf #mce-proguard 11 Jan 2014 How to enable optimization? Gradle: build.gradle android { buildTypes { release { runProguard true proguardFile getDefaultProguardFile('proguard-android-optimize.txt') } } productFlavors { some_flavor { proguardFile 'proguard-project.txt' } } } android { buildTypes { release { runProguard true proguardFile getDefaultProguardFile('proguard-android-optimize.txt') } } productFlavors { some_flavor { proguardFile 'proguard-project.txt' } } } New
  • 32. #mceconf #mce-proguard 11 Jan 2014 Remove logging code Specify assumptions in proguard-project.txt: -assumenosideeffects class android.util.Log { public static boolean isLoggable(java.lang.String, int); public static int v(...); public static int i(...); public static int w(...); public static int d(...); public static int e(...); public static java.lang.String getStackTraceString (java.lang.Throwable); } -assumenosideeffects class android.util.Log { public static boolean isLoggable(java.lang.String, int); public static int v(...); public static int i(...); public static int w(...); public static int d(...); public static int e(...); public static java.lang.String getStackTraceString (java.lang.Throwable); } Tip
  • 33. #mceconf #mce-proguard 11 Jan 2014 Obfuscation Traditional name obfuscation: ● Rename identifiers: class/field/method names ● Remove debug information: line numbers, local variable names,...
  • 34. #mceconf #mce-proguard 11 Jan 2014 Obfuscation example public class MyComputationClass { private MySettings settings; private MyAlgorithm algorithm; private int answer; public int computeAnswer(int input) { … return answer; } } public class MyComputationClass { private MySettings settings; private MyAlgorithm algorithm; private int answer; public int computeAnswer(int input) { … return answer; } }
  • 35. #mceconf #mce-proguard 11 Jan 2014 Obfuscation example public class MyComputationClass { private MySettings settings; private MyAlgorithm algorithm; private int answer; public int computeAnswer(int input) { … return answer; } } public class MyComputationClass { private MySettings settings; private MyAlgorithm algorithm; private int answer; public int computeAnswer(int input) { … return answer; } } public class a { private b a; private c b; private int c; public int a(int a) { … return c; } } public class a { private b a; private c b; private int c; public int a(int a) { … return c; } }
  • 36. #mceconf #mce-proguard 11 Jan 2014 Complementary steps Optimization Obfuscation Irreversibly remove information
  • 37. #mceconf #mce-proguard 11 Jan 2014 What about ART? The new (experimental) Android RunTime Application Java bytecode ProGuard Libraries Java bytecode Processed Java bytecode Dex Dalvik bytecode Dex2oat Native code Development Device
  • 38. #mceconf #mce-proguard 11 Jan 2014 More application protection? public class MyVerificationClass { public int checkSignatures() { … return activity .getPackageManager() .checkSignatures(“mypackage1”, “mypackage2”); } } public class MyVerificationClass { public int checkSignatures() { … return activity .getPackageManager() .checkSignatures(“mypackage1”, “mypackage2”); } }
  • 39. #mceconf #mce-proguard 11 Jan 2014 More application protection? public class MyVerificationClass { public int checkSignatures() { … return activity .getPackageManager() .checkSignatures(“mypackage1”, “mypackage2”); } } public class MyVerificationClass { public int checkSignatures() { … return activity .getPackageManager() .checkSignatures(“mypackage1”, “mypackage2”); } } public class a { public int a() { … return a .getPackageManager() .checkSignatures(“mypackage1”, “mypackage2”); } } public class a { public int a() { … return a .getPackageManager() .checkSignatures(“mypackage1”, “mypackage2”); } }
  • 40. #mceconf #mce-proguard 11 Jan 2014 More application protection Nothing is unbreakable, but you can raise the bar: ● ProGuard ● String encryption ● Reflection ● Dynamic class loading ● Native code ● Data encryption ● … DexGuard
  • 41. #mceconf #mce-proguard 11 Jan 2014 ProGuard - DexGuard Open source Generic Shrinker Optimizer Obfuscator For Java bytecode Closed source Specialized Shrinker Optimizer Obfuscator Protector For Android Compatible
  • 42. #mceconf #mce-proguard 11 Jan 2014 ProGuard guide – Android SDK developer.android.comdeveloper.android.com
  • 43. #mceconf #mce-proguard 11 Jan 2014 ProGuard website proguard.sourceforge.netproguard.sourceforge.net
  • 44. #mceconf #mce-proguard 11 Jan 2014 ProGuard manualTip proguard.sourceforge.netproguard.sourceforge.net
  • 45. #mceconf #mce-proguard 11 Jan 2014 Saikoa website www.saikoa.comwww.saikoa.com
  • 46. #mceconf #mce-proguard 11 Jan 2014 Questions? Open source Shrinking Optimization Obfuscation Java bytecode ProGuard Saikoa DexGuard Dalvik bytecode Protection