Top Banner
ProGuard and DexGuard for Optimization and Protection Eric Lafortune Creator of ProGuard and DexGuard Technical director at Saikoa
45

Eric Lafortune - ProGuard and DexGuard for optimization and protection

Jan 20, 2017

Download

Software

GuardSquare
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Eric Lafortune - ProGuard and DexGuard for optimization and protection

ProGuardand DexGuard

for Optimizationand Protection

Eric LafortuneCreator of ProGuard and DexGuard

Technical director at Saikoa

Page 2: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Topics

ProGuard

– Techniques– Results

More application protection

– Goals– Attackers– Types of attacks– Protection

Page 3: Eric Lafortune - ProGuard and DexGuard for optimization and protection

ProGuard

Applicationcode

Shrink

Libraries

Androidruntime

Optimize Obfuscate Processedcode

Androidruntime

Page 4: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Results

● Size reduction:

– Code (classes.dex): 20 … 90%– Application (.apk): 5 ... 70%

● Performance improvements: 0 … 20%

Page 5: Eric Lafortune - ProGuard and DexGuard for optimization and protection

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

Page 6: Eric Lafortune - ProGuard and DexGuard for optimization and protection

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

Page 7: Eric Lafortune - ProGuard and DexGuard for optimization and protection

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.JSONArrayWarning: 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.LoggerWarning: 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.LoggerWarning: twitter4j.internal.logging.SLF4JLoggerFactory: can't find referenced class org.slf4j.LoggerFactory...

Tip

Page 8: Eric Lafortune - ProGuard and DexGuard for optimization and protection

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

Page 9: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Shrinking

● Classes, fields, methods

Page 10: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Entry points

1) Activities, applications, services, fragments,...

→ provided automatically by Android build process

2) Introspection

→ must be specified in proguard-project.txt:

-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…

Page 11: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Optimization

At the bytecode instruction level:

● Dead code elimination

● Constant propagation

● Method inlining

● Class merging

● Remove logging code

● Peephole optimizations

● Devirtualization

● ...

Page 12: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Optimization exampleint 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

Page 13: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Optimization exampleint 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 }; ...}

New

Page 14: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Optimization exampleint 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 }; ...}

New

class Internal { static final int[] $SwitchMap = new int[MyEnum.values().length];

static { $SwitchMap[MyEnum.RED.ordinal()] = 1; $SwitchMap[MyEnum.GREEN.ordinal()] = 2; }}

class Internal { static final int[] $SwitchMap = new int[MyEnum.values().length];

static { $SwitchMap[MyEnum.RED.ordinal()] = 1; $SwitchMap[MyEnum.GREEN.ordinal()] = 2; }}

Page 15: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Optimization exampleint 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 }; ...}

New

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; }}

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; }}

Page 16: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Optimization exampleint 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 }; ...}

New

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; }}

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; }}

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; }}

Page 17: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Optimization exampleint 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 }; ...}

New

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; }}

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; }}

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;

Page 18: Eric Lafortune - ProGuard and DexGuard for optimization and protection

How to enable optimization?

Ant and Eclipse: project.properties

# To enable ProGuard to shrink and obfuscate your code, uncomment thisproguard.config= ${sdk.dir}/tools/proguard/proguard-android-optimize.txt: proguard-project.txt

# To enable ProGuard to shrink and obfuscate your code, uncomment thisproguard.config= ${sdk.dir}/tools/proguard/proguard-android-optimize.txt: proguard-project.txt

Tip

Page 19: Eric Lafortune - ProGuard and DexGuard for optimization and protection

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

Page 20: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Obfuscation

Traditional name obfuscation:

● Rename identifiers:class/field/method names

● Remove debug information: line numbers, local variable names,...

Page 21: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Obfuscation examplepublic 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; }}

Page 22: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Obfuscation examplepublic 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; }}

Page 23: Eric Lafortune - ProGuard and DexGuard for optimization and protection

ProGuard documentation

developer.android.comdeveloper.android.com

proguard.sourceforge.netproguard.sourceforge.net

Page 24: Eric Lafortune - ProGuard and DexGuard for optimization and protection

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”); }}

Page 25: Eric Lafortune - ProGuard and DexGuard for optimization and protection

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”); }}

Page 26: Eric Lafortune - ProGuard and DexGuard for optimization and protection

What to protect?

● Application

● Algorithms

● Communication

● Assets

● Keys

Code

Resources

Assets

Signatures

Page 27: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Attackers

Page 28: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Attackers

Page 29: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Time

Page 30: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Choice

Page 31: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Static analysis

● Disassemblers: dexdump, baksmali

● Decompilers: dex2jar + jad, JD-GUI, JEB,...

● Resources: aapt, apktool,...

Page 32: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Dynamic analysis

● Debuggers: adb,...

● Subverted runtime

● Cracking tools

Page 33: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Server-side code

Client-sideapplication

Server-sideapplication

?

Page 34: Eric Lafortune - ProGuard and DexGuard for optimization and protection

String encryption

Be creative!

String KEY = “Secret key”;String KEY = “Secret key”;

String KEY = new String(Base64.decode(“U2VjcmV0IGtleQo=”));String KEY = new String(Base64.decode(“U2VjcmV0IGtleQo=”));

Page 35: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Reflection

java.lang.reflect

System.out.println(“Hello world!”);System.out.println(“Hello world!”);

Class clazz = Class.forName(“java.io.PrintStream”);

Method method = clazz.getMethod(“println”, new Class[] { String.class });

method.invoke(nul, new Object[] { “Hello world!” });

Class clazz = Class.forName(“java.io.PrintStream”);

Method method = clazz.getMethod(“println”, new Class[] { String.class });

method.invoke(nul, new Object[] { “Hello world!” });

Page 36: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Dynamic class loading

http://android-developers.blogspot.be/2011/07/custom-class-loading-in-dalvik.html

classes.dex

extra.dex

classes.dex

Page 37: Eric Lafortune - ProGuard and DexGuard for optimization and protection

classes.dex

libutil.solibutil.so

Native code

Java Native Interface

libutil.so

classes.dex

Page 38: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Data encryption

● Standard cryptography APIs

● SQLCipher

Cipher cipher = Cipher.getInstance(“AES/CFB/NoPadding”);cipher.init(Cipher.ENCRYPT_MODE, key, initializationVector);

byte[] decrypted = cipher.doFinal(encrypted);

Cipher cipher = Cipher.getInstance(“AES/CFB/NoPadding”);cipher.init(Cipher.ENCRYPT_MODE, key, initializationVector);

byte[] decrypted = cipher.doFinal(encrypted);

Page 39: Eric Lafortune - ProGuard and DexGuard for optimization and protection

White-box cryptography

Research: www.whiteboxcrypto.com

Real examples: DES, AES

final int KEY = 42;

int decryptValue(int encryptedValue) { return encryptedValue * KEY;}

final int KEY = 42;

int decryptValue(int encryptedValue) { return encryptedValue * KEY;}

int decryptValue(int encryptedValue) { encryptedValue += 5; encryptedValue *= 21; encryptedValue -= 105; encryptedValue += encryptedValue; return encryptedValue;}

int decryptValue(int encryptedValue) { encryptedValue += 5; encryptedValue *= 21; encryptedValue -= 105; encryptedValue += encryptedValue; return encryptedValue;}

Page 40: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Application checks

● Check application certificate:

● Check debug flag:

boolean debug = (activity.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;

boolean debug = (activity.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;

byte[] certificateData = activity .getPackageManager() .getPackageInfo(activity.getPackageName(), PackageManager.GET_SIGNATURES) .signatures[0] .toByteArray();

byte[] certificateData = activity .getPackageManager() .getPackageInfo(activity.getPackageName(), PackageManager.GET_SIGNATURES) .signatures[0] .toByteArray();

Page 41: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Environment checks

● Emulator detection

● Root detection

Page 42: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Conclusion

Nothing is unbreakable, but you can raise the bar:

● ProGuard

● String encryption

● Reflection

● Dynamic class loading

● Native code

● Data encryption

● Application checks

● Environment checks

● … DexGuard

Page 43: Eric Lafortune - ProGuard and DexGuard for optimization and protection

DexGuard

● Specialized for Android

● Code and data

● Layers of protection

● Recommended techniques

● Low-level techniques

● Transparent

Tip

Code

Resources

Assets

Signatures

Page 44: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Saikoa website

www.saikoa.comwww.saikoa.com

Page 45: Eric Lafortune - ProGuard and DexGuard for optimization and protection

Questions?

Open source

ShrinkingOptimizationObfuscation

Java bytecode

ProGuard

Saikoa

DexGuard

Dalvik bytecode

Protection