SlideShare a Scribd company logo
1 of 31
Download to read offline
23 June 2016
ProGuard
DexGuard
Tips and Tricks
Thomas Neidhart
Developer @ GuardSquare
23 June 2016
ProGuard Overview
Shrinking
(-dontshrink)
Optimization
(-dontoptimize)
Obfuscation
(-dontobfuscate)
23 June 2016
ProGuard in Android builds
Application
Java bytec.
ProGuard
Processed
Java bytec.
Zip
align
Application
Java source
Libraries
Java bytec.
XML res.
Assets
Aapt
Javac
Libraries
Java bytec.
Dalvik
bytecode
Assets
Compiled
XML res.
Signatures
Assets
Compiled
XML res.
Dalvik
bytecode
Signatures
Assets
Compiled
XML res.
Dalvik
bytecode
Dex
Jar
signer
Application
Native src
Native
libraries
Native
libraries
Native
libraries
Gcc
23 June 2016
android {
buildTypes {
debug {
minifyEnabled false
}
release {
minifyEnabled true
proguardFile getDefaultProguardFile('proguard-android.txt')
// To enable optimization, use the following instead:
// proguardFile getDefaultProguardFile('proguard-android-optimize.txt')
proguardFile 'proguard-project.txt'
}
}
}
Build configuration
Gradle: build.gradle
23 June 2016
Build configuration
Used configurations:
● Specified proguardFiles in build.gradle
● consumerProguardFiles from libraries
(automatically added by Android plugin)
● Proguard rules generated by aapt, located in
build/intermediates/proguard-rules/<build-
type>/aapt_rules.txt
Tip
23 June 2016
Configuration Debugging
Help for figuring out whats going on:
● Use '-printconfiguration config.pro'
● Use '-whyareyoukeeping class xxx.yyy ...'
Tip
com.example.HelloWorldActivity
  is kept by a directive in the configuration.
com.example.HelloWorldActivity: java.lang.String TAG
  is not being kept.
com.example.HelloWorldActivity: HelloWorldActivity() (18:18)
  is kept by a directive in the configuration.
com.example.HelloWorldActivity: void onCreate(android.os.Bundle) 
(25:39)
  implements       android.app.Activity: void 
onCreate(android.os.Bundle)
  is a library method.
23 June 2016
Keep rules
Keep From being removed or renamed From being renamed
Classes and class members -keep -keepnames
Class members only -keepclassmembers -keepclassmembernames
Classes and class members, if
class members present
-keepclasseswithmembers -keepclasseswithmembernames
Hints:
● '-keep class xxx.yyy' will only keep the class itself
(+ default ctor), not its members
● Avoid '-keep class xxx.yyy { *; }' rules,
prefer '-keep class xxx.yyy { public protected *; }'
23 June 2016
Pattern matching
Pattern types:
● Inclusion patterns: com.example.**
● Exclusion patterns: !com.example.foo.*
Pattern analysis:
● Patterns are analyzed in sequential order
● Exclusion patterns must come first
Tip
23 June 2016
Pattern example
Keep everything in the package com.example and its
subpackages, except for package com.example.internal:
This won't work:
Tip
­keep class !com.example.internal.**,
             com.example.** {
  *;
}
­keep class !com.example.internal.**,
             com.example.** {
  *;
}
­keep class !com.example.internal.** { *; }
­keep class com.example.** { *; }
­keep class !com.example.internal.** { *; }
­keep class com.example.** { *; }
23 June 2016
Notes and warnings
“Closed-world assumption”
● Might lead to problems during optimization
● Better to resolve than to hide
● Warnings and Notes are handled separately (-dontnote)
Tip
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
...
­dontwarn twitter4j.internal.logging.**
# last resort
­ignorewarnings
­dontwarn twitter4j.internal.logging.**
# last resort
­ignorewarnings
23 June 2016
Shrinking
Attributes:
Default config only keeps *Annotation*
Other useful / necessary attributes to keep:
● Signature
● InnerClasses
● LineNumberTable
● SourceFile (together with -renamesourcefileattribute '')
Tip
23 June 2016
Optimization
Various techniques:
● Method inlining
● Constant propagation
● Class merging
● Dead code elimination
● Code removal
● Peephole optimizations
● Variable allocations
● Field/Parameter/Exception removal
● ...
23 June 2016
Optimization limitations
Extracted from user guide:
Warning: 3rd party libraries might be obfuscated in a way that breaks these
assumptions.
Mitigations:
● -dontoptimize
●
System property: -Doptimize.conservatively
For best results, ProGuard's optimization algorithms assume that the processed code never intentionally
throws NullPointerExceptions or ArrayIndexOutOfBoundsExceptions, or even OutOfMemoryErrors
or StackOverflowErrors, in order to achieve something useful. For instance, it may remove a method call
myObject.myMethod() if that call wouldn't have any effect. It ignores the possibility that myObject might be
null, causing a NullPointerException. In some way this is a good thing: optimized code may throw fewer
exceptions. Should this entire assumption be false, you'll have to switch off optimization using the
-dontoptimize option.
Tip
23 June 2016
Optimization Methods
Optimization Technique Flags Safe? Impact
Method inlining method/inlining/* Yes
Peephole optimizations code/simplification/* Yes
Unreachable Code removal code/removal/simple Yes
Code removal code/removal/advanced Yes (ex. Obfuscated
libs)
Needed for logging removal, generally
safe, but depends on configuration.
Enum unboxing class/unboxing/enum Mostly yes Might lead to problems, especially when
using EnumMap / EnumSet
Variable allocation code/allocation/variable For Applications. Dx might crash when
-keepparameternames is used (or
LocalVariableTable is kept).
Method de-synchronization method/marking/synchronized Yes Effect might not be noticable, Slow
optimization
Constant propagation field/propagation/value
method/propagation/*
Yes
Class merging class/merging/* Mostly yes Might cause issues in rare cases.
Field removal field/removal/writeonly Yes
Tip
23 June 2016
Logging Removal
Java Source:
Smali:
Log.d(TAG, "Hello world " + this.getClass().getName() + "!");
  .line 31
    invoke­virtual { p0, v5 }, Lcom/example/HelloWorldActivity;­>setContentView(Landroid/view/View;)V
  .line 33
    const­string v0, "Activity"
    new­instance v1, Ljava/lang/StringBuilder;
    invoke­direct { v1 }, Ljava/lang/StringBuilder;­><init>()V
    const­string v2, "Hello world "
    invoke­virtual { v1, v2 }, Ljava/lang/StringBuilder;­>append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    move­result­object v1
    invoke­virtual { p0 }, Ljava/lang/Object;­>getClass()Ljava/lang/Class;
    move­result­object v2
    invoke­virtual { v2 }, Ljava/lang/Class;­>getName()Ljava/lang/String;
    move­result­object v2
    invoke­virtual { v1, v2 }, Ljava/lang/StringBuilder;­>append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    move­result­object v1
    const­string v2, "!"
    invoke­virtual { v1, v2 }, Ljava/lang/StringBuilder;­>append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    move­result­object v1
    invoke­virtual { v1 }, Ljava/lang/StringBuilder;­>toString()Ljava/lang/String;
    move­result­object v1
    invoke­static { v0, v1 }, Landroid/util/Log;­>d(Ljava/lang/String;Ljava/lang/String;)I
  .line 35
23 June 2016
Logging Removal
ProGuard configuration:
­assumenosideeffects class android.util.Log {
    public static boolean isLoggable(java.lang.String, int);
    public static int v(...);
    public static int d(...);
    public static int i(...);
    public static int w(...);
    public static int e(...);
    public static java.lang.String getStackTraceString(java.lang.Throwable);
}
23 June 2016
Logging Removal
Result:
Why are there still objects/method calls?
    const­string v1, "Hello world "
    invoke­direct { v0, v1 }, Ljava/lang/StringBuilder;­><init>(Ljava/lang/String;)V
    invoke­virtual { p0 }, Ljava/lang/Object;­>getClass()Ljava/lang/Class;
    move­result­object v1
    invoke­virtual { v1 }, Ljava/lang/Class;­>getName()Ljava/lang/String;
    move­result­object v1
    invoke­virtual { v0, v1 }, Ljava/lang/StringBuilder;­>append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    move­result­object v0
    const­string v1, "!"
    invoke­virtual { v0, v1 }, Ljava/lang/StringBuilder;­>append(Ljava/lang/String;)Ljava/lang/StringBuilder;
23 June 2016
Logging Removal
Second try:
Smali:
Log.d(TAG, String.format("Hello world %s!", this.getClass().getName());
Tip
const-string v1, "Activity"
const-string v2, "Hello world %s!"
new-array v3, v6, [Ljava/lang/Object;
const/4 v4, 0
invoke-virtual { p0 }, Ljava/lang/Object;->getClass()Ljava/lang/Class;
move-result-object v5
invoke-virtual { v5 }, Ljava/lang/Class;->getName()Ljava/lang/String;
move-result-object v5
aput-object v5, v3, v4
invoke-static { v2, v3 }, Ljava/lang/String;->format(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
move-result-object v2
invoke-static { v1, v2 }, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
23 June 2016
Logging Removal
ProGuard configuration:
­assumenosideeffects class android.util.Log {
    public static boolean isLoggable(java.lang.String, int);
    public static int v(...);
    public static int d(...);
    public static int i(...);
    public static int w(...);
    public static int e(...);
    public static java.lang.String getStackTraceString(java.lang.Throwable);
}
­assumenosideeffects class java.lang.String {
    public static java.lang.String format(...);
}
Tip
23 June 2016
Logging Removal
Result:
Better!
Tip
    new­array v0, v3, [Ljava/lang/Object;
    const/4 v1, 0
    invoke­virtual { p0 }, Ljava/lang/Object;­>getClass()Ljava/lang/Class;
    move­result­object v2
    invoke­virtual { v2 }, Ljava/lang/Class;­>getName()Ljava/lang/String;
    move­result­object v2
    aput­object v2, v0, v1
23 June 2016
Side Effect Checking
Explicit (for library classes/methods):
Implicit (for program classes/method):
● During optimization by analysing the actual code
● Can be prevented with -keep rules
Note: removes invocations not methods themselves!
-assumenosideeffects class xxx.yyy { … }
23 June 2016
Side Effect Example
public static int sum(int a, int b) {
   return a + b;
}
@Override
public void onCreate(Bundle savedInstanceState)
{
    …
    setContentView(xxx);
    sum(10, 30);
    …
}
  .line 57
    invoke­virtual { p0, p1 }, Lcom/example/HelloWorldActivity;­>setContentView(Landroid/view/View;)V
  .line 66
  .line 57
    invoke­virtual { p0, v2 }, Lcom/example/HelloWorldActivity;­>setContentView(Landroid/view/View;)V
  .line 63
    const/16 v0, 10
    const/16 v1, 30
    invoke­static { v0, v1 }, Lcom/example/HelloWorldActivity;­>sum(II)I
  .line 66
Optimized:
23 June 2016
DexGuard
Commercial extension of ProGuard
Additional protection features:
● String/Class/Asset/Resource/Native library encryption
● Native library interface obfuscation
● Hide sensitive method calls via reflection
● Code obfuscation (control flow, arithmetic obfuscation)
Resource shrinking
Resource / Metadata inlining
Multidex support
...
23 June 2016
DexGuard Overview
Shrinking
(-dontshrink)
Optimization
(-dontoptimize)
Obfuscation
(-dontobfuscate)
String encryption
Class encryption
Asset encryption
Resource
encryption
Native library
encryption
Code obfuscation
Resource inlining
Multidexing
Splitdexing
Zipalign
Signing
Reflect API calls
23 June 2016
DexGuard in Android builds
Compiled
XML res. DexGuard
Application
Java source
Libraries
Java bytec.
XML res.
Assets
Aapt
Javac
Libraries
Java bytec.
Processed
assets
Processed
XML res.
Dalvik
bytecode
Application
Java bytec.
Signatures
Application
Native src
Native
libraries
Processed
native
libraries
Gcc
23 June 2016
DexGuard in Android builds (2)
Jack
Dex
Guard
Application
Java source
Libraries
Java bytec.
XML res.
Assets
Aapt
Jill
Libraries
.jayce
Dalvik
bytecode
Assets
Compiled
XML res.
Signatures
Assets
Compiled
XML res.
Dalvik
bytecode
Signatures
Assets
Compiled
XML res.
Dalvik
bytecode
Jar
signer
Application
Native src
Native
libraries
Native
libraries
Native
libraries
Gcc
23 June 2016
Optimization
Features in addition to ProGuard:
● Parallel Optimization → faster on multi-core machines
● New modifier 'includecode' for -keep rules
● Support for more fine-grained side-effect configuration →
more effective code removal
23 June 2016
Logging Removal
Java Source:
Smali:
Log.d(TAG, "Hello world " + this.getClass().getName() + "!");
  .line 31
    invoke­virtual { p0, v5 }, Lcom/example/HelloWorldActivity;­>setContentView(Landroid/view/View;)V
  .line 33
    const­string v0, "Activity"
    new­instance v1, Ljava/lang/StringBuilder;
    invoke­direct { v1 }, Ljava/lang/StringBuilder;­><init>()V
    const­string v2, "Hello world "
    invoke­virtual { v1, v2 }, Ljava/lang/StringBuilder;­>append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    move­result­object v1
    invoke­virtual { p0 }, Ljava/lang/Object;­>getClass()Ljava/lang/Class;
    move­result­object v2
    invoke­virtual { v2 }, Ljava/lang/Class;­>getName()Ljava/lang/String;
    move­result­object v2
    invoke­virtual { v1, v2 }, Ljava/lang/StringBuilder;­>append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    move­result­object v1
    const­string v2, "!"
    invoke­virtual { v1, v2 }, Ljava/lang/StringBuilder;­>append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    move­result­object v1
    invoke­virtual { v1 }, Ljava/lang/StringBuilder;­>toString()Ljava/lang/String;
    move­result­object v1
    invoke­static { v0, v1 }, Landroid/util/Log;­>d(Ljava/lang/String;Ljava/lang/String;)I
  .line 35
23 June 2016
Logging Removal
Result:
Much better!
Possible due to more fine-grained configuration:
  .line 31
    invoke­virtual { p0, p1 }, Lcom/example/HelloWorldActivity;­>setContentView(Landroid/view/View;)V
  .line 35
­assumenoexternalsideeffects public final class java.lang.StringBuilder {
    public java.lang.StringBuilder();
    public java.lang.StringBuilder(int);
    public java.lang.StringBuilder(java.lang.String);
    public java.lang.StringBuilder append(java.lang.String);
    …
}
23 June 2016
More DexGuard Goodies
● Default configurations for applications/libraries supporting
many 3rd party libs
● Great support :-)
● Many samples
● Configuration debugging
● Java 8 language support → backported to Java 6/7 similar to
retrolambda
● Planned: Stream API support for older Android devices
● Planned: Native code obfuscation
23 June 2016
The End
Thanks for
your attention!

More Related Content

What's hot

21 Essential JavaScript Interview Questions
21 Essential JavaScript Interview Questions21 Essential JavaScript Interview Questions
21 Essential JavaScript Interview QuestionsArc & Codementor
 
Akash Institute P-Block Elements Notes Class 12 JEE Mains and Advanced
Akash Institute P-Block Elements Notes Class 12 JEE Mains and AdvancedAkash Institute P-Block Elements Notes Class 12 JEE Mains and Advanced
Akash Institute P-Block Elements Notes Class 12 JEE Mains and AdvancedAayush Gupta
 
Spring Framework
Spring Framework  Spring Framework
Spring Framework tola99
 
JavaScript - Chapter 13 - Browser Object Model(BOM)
JavaScript - Chapter 13 - Browser Object Model(BOM)JavaScript - Chapter 13 - Browser Object Model(BOM)
JavaScript - Chapter 13 - Browser Object Model(BOM)WebStackAcademy
 
Reactive Web - Servlet & Async, Non-blocking I/O
Reactive Web - Servlet & Async, Non-blocking I/OReactive Web - Servlet & Async, Non-blocking I/O
Reactive Web - Servlet & Async, Non-blocking I/OArawn Park
 
Quick flask an intro to flask
Quick flask   an intro to flaskQuick flask   an intro to flask
Quick flask an intro to flaskjuzten
 
UNIT 4 Software Testing Notes (Topic Wise)
UNIT 4 Software Testing Notes (Topic Wise)UNIT 4 Software Testing Notes (Topic Wise)
UNIT 4 Software Testing Notes (Topic Wise)HemaArora2
 
Web application development with Django framework
Web application development with Django frameworkWeb application development with Django framework
Web application development with Django frameworkflapiello
 
A Basic Django Introduction
A Basic Django IntroductionA Basic Django Introduction
A Basic Django IntroductionGanga Ram
 
Understanding the Dalvik bytecode with the Dedexer tool
Understanding the Dalvik bytecode with the Dedexer toolUnderstanding the Dalvik bytecode with the Dedexer tool
Understanding the Dalvik bytecode with the Dedexer toolGabor Paller
 
Django - Python MVC Framework
Django - Python MVC FrameworkDjango - Python MVC Framework
Django - Python MVC FrameworkBala Kumar
 
Web development with django - Basics Presentation
Web development with django - Basics PresentationWeb development with django - Basics Presentation
Web development with django - Basics PresentationShrinath Shenoy
 
Jdbc example program with access and MySql
Jdbc example program with access and MySqlJdbc example program with access and MySql
Jdbc example program with access and MySqlkamal kotecha
 
Android share preferences
Android share preferencesAndroid share preferences
Android share preferencesAjay Panchal
 
Understanding angular js
Understanding angular jsUnderstanding angular js
Understanding angular jsAayush Shrestha
 

What's hot (20)

21 Essential JavaScript Interview Questions
21 Essential JavaScript Interview Questions21 Essential JavaScript Interview Questions
21 Essential JavaScript Interview Questions
 
Asp.net control
Asp.net controlAsp.net control
Asp.net control
 
Akash Institute P-Block Elements Notes Class 12 JEE Mains and Advanced
Akash Institute P-Block Elements Notes Class 12 JEE Mains and AdvancedAkash Institute P-Block Elements Notes Class 12 JEE Mains and Advanced
Akash Institute P-Block Elements Notes Class 12 JEE Mains and Advanced
 
Spring Framework
Spring Framework  Spring Framework
Spring Framework
 
JavaScript - Chapter 13 - Browser Object Model(BOM)
JavaScript - Chapter 13 - Browser Object Model(BOM)JavaScript - Chapter 13 - Browser Object Model(BOM)
JavaScript - Chapter 13 - Browser Object Model(BOM)
 
Reactive Web - Servlet & Async, Non-blocking I/O
Reactive Web - Servlet & Async, Non-blocking I/OReactive Web - Servlet & Async, Non-blocking I/O
Reactive Web - Servlet & Async, Non-blocking I/O
 
Quick flask an intro to flask
Quick flask   an intro to flaskQuick flask   an intro to flask
Quick flask an intro to flask
 
UNIT 4 Software Testing Notes (Topic Wise)
UNIT 4 Software Testing Notes (Topic Wise)UNIT 4 Software Testing Notes (Topic Wise)
UNIT 4 Software Testing Notes (Topic Wise)
 
Web application development with Django framework
Web application development with Django frameworkWeb application development with Django framework
Web application development with Django framework
 
React js
React jsReact js
React js
 
A Basic Django Introduction
A Basic Django IntroductionA Basic Django Introduction
A Basic Django Introduction
 
Flask
FlaskFlask
Flask
 
Understanding the Dalvik bytecode with the Dedexer tool
Understanding the Dalvik bytecode with the Dedexer toolUnderstanding the Dalvik bytecode with the Dedexer tool
Understanding the Dalvik bytecode with the Dedexer tool
 
Django - Python MVC Framework
Django - Python MVC FrameworkDjango - Python MVC Framework
Django - Python MVC Framework
 
Web development with django - Basics Presentation
Web development with django - Basics PresentationWeb development with django - Basics Presentation
Web development with django - Basics Presentation
 
Jdbc example program with access and MySql
Jdbc example program with access and MySqlJdbc example program with access and MySql
Jdbc example program with access and MySql
 
Android share preferences
Android share preferencesAndroid share preferences
Android share preferences
 
django
djangodjango
django
 
React js basics
React js basicsReact js basics
React js basics
 
Understanding angular js
Understanding angular jsUnderstanding angular js
Understanding angular js
 

Similar to ProGuard / DexGuard Tips and Tricks

[MOPCON2018] Effectively shrink ProGuard rules for reducing APK size
[MOPCON2018] Effectively shrink ProGuard rules for reducing APK size[MOPCON2018] Effectively shrink ProGuard rules for reducing APK size
[MOPCON2018] Effectively shrink ProGuard rules for reducing APK sizeAnsgar Lin
 
[Gstar 2013] Unity Security
[Gstar 2013] Unity Security[Gstar 2013] Unity Security
[Gstar 2013] Unity SecuritySeungmin Shin
 
Audit your reactive applications
Audit your reactive applicationsAudit your reactive applications
Audit your reactive applicationsOCTO Technology
 
Core Java Programming Language (JSE) : Chapter VIII - Exceptions and Assertions
Core Java Programming Language (JSE) : Chapter VIII - Exceptions and AssertionsCore Java Programming Language (JSE) : Chapter VIII - Exceptions and Assertions
Core Java Programming Language (JSE) : Chapter VIII - Exceptions and AssertionsWebStackAcademy
 
Best Coding Practices For Android Application Development
Best Coding Practices For Android Application DevelopmentBest Coding Practices For Android Application Development
Best Coding Practices For Android Application DevelopmentKetan Raval
 
OPM Recipe designer notes
OPM Recipe designer notesOPM Recipe designer notes
OPM Recipe designer notested-xu
 
Mockito with a hint of PowerMock
Mockito with a hint of PowerMockMockito with a hint of PowerMock
Mockito with a hint of PowerMockYing Zhang
 
Advanced iOS Debbuging (Reloaded)
Advanced iOS Debbuging (Reloaded)Advanced iOS Debbuging (Reloaded)
Advanced iOS Debbuging (Reloaded)Massimo Oliviero
 
How to Perform Memory Leak Test Using Valgrind
How to Perform Memory Leak Test Using ValgrindHow to Perform Memory Leak Test Using Valgrind
How to Perform Memory Leak Test Using ValgrindRapidValue
 
Android reverse engineering - Analyzing skype
Android reverse engineering - Analyzing skypeAndroid reverse engineering - Analyzing skype
Android reverse engineering - Analyzing skypeMário Almeida
 
Generic Synchronization Policies in C++
Generic Synchronization Policies in C++Generic Synchronization Policies in C++
Generic Synchronization Policies in C++Ciaran McHale
 
"Xapi-lang For declarative code generation" By James Nelson
"Xapi-lang For declarative code generation" By James Nelson"Xapi-lang For declarative code generation" By James Nelson
"Xapi-lang For declarative code generation" By James NelsonGWTcon
 
Javascript Deofuscation A manual Approach
Javascript Deofuscation A manual ApproachJavascript Deofuscation A manual Approach
Javascript Deofuscation A manual ApproachGregory Hanis
 
JavaOne 2017 CON2902 - Java Code Inspection and Testing Power Tools
JavaOne 2017 CON2902 - Java Code Inspection and Testing Power ToolsJavaOne 2017 CON2902 - Java Code Inspection and Testing Power Tools
JavaOne 2017 CON2902 - Java Code Inspection and Testing Power ToolsJorge Hidalgo
 
Google I/O 2021 Recap
Google I/O 2021 RecapGoogle I/O 2021 Recap
Google I/O 2021 Recapfurusin
 
Bring the fun back to java
Bring the fun back to javaBring the fun back to java
Bring the fun back to javaciklum_ods
 
JavaOne 2016: Life after Modularity
JavaOne 2016: Life after ModularityJavaOne 2016: Life after Modularity
JavaOne 2016: Life after ModularityDanHeidinga
 

Similar to ProGuard / DexGuard Tips and Tricks (20)

Proguard android
Proguard androidProguard android
Proguard android
 
[MOPCON2018] Effectively shrink ProGuard rules for reducing APK size
[MOPCON2018] Effectively shrink ProGuard rules for reducing APK size[MOPCON2018] Effectively shrink ProGuard rules for reducing APK size
[MOPCON2018] Effectively shrink ProGuard rules for reducing APK size
 
[Gstar 2013] Unity Security
[Gstar 2013] Unity Security[Gstar 2013] Unity Security
[Gstar 2013] Unity Security
 
groovy & grails - lecture 7
groovy & grails - lecture 7groovy & grails - lecture 7
groovy & grails - lecture 7
 
Audit your reactive applications
Audit your reactive applicationsAudit your reactive applications
Audit your reactive applications
 
Core Java Programming Language (JSE) : Chapter VIII - Exceptions and Assertions
Core Java Programming Language (JSE) : Chapter VIII - Exceptions and AssertionsCore Java Programming Language (JSE) : Chapter VIII - Exceptions and Assertions
Core Java Programming Language (JSE) : Chapter VIII - Exceptions and Assertions
 
Best Coding Practices For Android Application Development
Best Coding Practices For Android Application DevelopmentBest Coding Practices For Android Application Development
Best Coding Practices For Android Application Development
 
OPM Recipe designer notes
OPM Recipe designer notesOPM Recipe designer notes
OPM Recipe designer notes
 
Mockito with a hint of PowerMock
Mockito with a hint of PowerMockMockito with a hint of PowerMock
Mockito with a hint of PowerMock
 
Advanced iOS Debbuging (Reloaded)
Advanced iOS Debbuging (Reloaded)Advanced iOS Debbuging (Reloaded)
Advanced iOS Debbuging (Reloaded)
 
How to Perform Memory Leak Test Using Valgrind
How to Perform Memory Leak Test Using ValgrindHow to Perform Memory Leak Test Using Valgrind
How to Perform Memory Leak Test Using Valgrind
 
Android reverse engineering - Analyzing skype
Android reverse engineering - Analyzing skypeAndroid reverse engineering - Analyzing skype
Android reverse engineering - Analyzing skype
 
Generic Synchronization Policies in C++
Generic Synchronization Policies in C++Generic Synchronization Policies in C++
Generic Synchronization Policies in C++
 
Java bad coding practices
Java bad coding practicesJava bad coding practices
Java bad coding practices
 
"Xapi-lang For declarative code generation" By James Nelson
"Xapi-lang For declarative code generation" By James Nelson"Xapi-lang For declarative code generation" By James Nelson
"Xapi-lang For declarative code generation" By James Nelson
 
Javascript Deofuscation A manual Approach
Javascript Deofuscation A manual ApproachJavascript Deofuscation A manual Approach
Javascript Deofuscation A manual Approach
 
JavaOne 2017 CON2902 - Java Code Inspection and Testing Power Tools
JavaOne 2017 CON2902 - Java Code Inspection and Testing Power ToolsJavaOne 2017 CON2902 - Java Code Inspection and Testing Power Tools
JavaOne 2017 CON2902 - Java Code Inspection and Testing Power Tools
 
Google I/O 2021 Recap
Google I/O 2021 RecapGoogle I/O 2021 Recap
Google I/O 2021 Recap
 
Bring the fun back to java
Bring the fun back to javaBring the fun back to java
Bring the fun back to java
 
JavaOne 2016: Life after Modularity
JavaOne 2016: Life after ModularityJavaOne 2016: Life after Modularity
JavaOne 2016: Life after Modularity
 

ProGuard / DexGuard Tips and Tricks

  • 1. 23 June 2016 ProGuard DexGuard Tips and Tricks Thomas Neidhart Developer @ GuardSquare
  • 2. 23 June 2016 ProGuard Overview Shrinking (-dontshrink) Optimization (-dontoptimize) Obfuscation (-dontobfuscate)
  • 3. 23 June 2016 ProGuard in Android builds Application Java bytec. ProGuard Processed Java bytec. Zip align Application Java source Libraries Java bytec. XML res. Assets Aapt Javac Libraries Java bytec. Dalvik bytecode Assets Compiled XML res. Signatures Assets Compiled XML res. Dalvik bytecode Signatures Assets Compiled XML res. Dalvik bytecode Dex Jar signer Application Native src Native libraries Native libraries Native libraries Gcc
  • 4. 23 June 2016 android { buildTypes { debug { minifyEnabled false } release { minifyEnabled true proguardFile getDefaultProguardFile('proguard-android.txt') // To enable optimization, use the following instead: // proguardFile getDefaultProguardFile('proguard-android-optimize.txt') proguardFile 'proguard-project.txt' } } } Build configuration Gradle: build.gradle
  • 5. 23 June 2016 Build configuration Used configurations: ● Specified proguardFiles in build.gradle ● consumerProguardFiles from libraries (automatically added by Android plugin) ● Proguard rules generated by aapt, located in build/intermediates/proguard-rules/<build- type>/aapt_rules.txt Tip
  • 6. 23 June 2016 Configuration Debugging Help for figuring out whats going on: ● Use '-printconfiguration config.pro' ● Use '-whyareyoukeeping class xxx.yyy ...' Tip com.example.HelloWorldActivity   is kept by a directive in the configuration. com.example.HelloWorldActivity: java.lang.String TAG   is not being kept. com.example.HelloWorldActivity: HelloWorldActivity() (18:18)   is kept by a directive in the configuration. com.example.HelloWorldActivity: void onCreate(android.os.Bundle)  (25:39)   implements       android.app.Activity: void  onCreate(android.os.Bundle)   is a library method.
  • 7. 23 June 2016 Keep rules Keep From being removed or renamed From being renamed Classes and class members -keep -keepnames Class members only -keepclassmembers -keepclassmembernames Classes and class members, if class members present -keepclasseswithmembers -keepclasseswithmembernames Hints: ● '-keep class xxx.yyy' will only keep the class itself (+ default ctor), not its members ● Avoid '-keep class xxx.yyy { *; }' rules, prefer '-keep class xxx.yyy { public protected *; }'
  • 8. 23 June 2016 Pattern matching Pattern types: ● Inclusion patterns: com.example.** ● Exclusion patterns: !com.example.foo.* Pattern analysis: ● Patterns are analyzed in sequential order ● Exclusion patterns must come first Tip
  • 9. 23 June 2016 Pattern example Keep everything in the package com.example and its subpackages, except for package com.example.internal: This won't work: Tip ­keep class !com.example.internal.**,              com.example.** {   *; } ­keep class !com.example.internal.**,              com.example.** {   *; } ­keep class !com.example.internal.** { *; } ­keep class com.example.** { *; } ­keep class !com.example.internal.** { *; } ­keep class com.example.** { *; }
  • 10. 23 June 2016 Notes and warnings “Closed-world assumption” ● Might lead to problems during optimization ● Better to resolve than to hide ● Warnings and Notes are handled separately (-dontnote) Tip 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 ... ­dontwarn twitter4j.internal.logging.** # last resort ­ignorewarnings ­dontwarn twitter4j.internal.logging.** # last resort ­ignorewarnings
  • 11. 23 June 2016 Shrinking Attributes: Default config only keeps *Annotation* Other useful / necessary attributes to keep: ● Signature ● InnerClasses ● LineNumberTable ● SourceFile (together with -renamesourcefileattribute '') Tip
  • 12. 23 June 2016 Optimization Various techniques: ● Method inlining ● Constant propagation ● Class merging ● Dead code elimination ● Code removal ● Peephole optimizations ● Variable allocations ● Field/Parameter/Exception removal ● ...
  • 13. 23 June 2016 Optimization limitations Extracted from user guide: Warning: 3rd party libraries might be obfuscated in a way that breaks these assumptions. Mitigations: ● -dontoptimize ● System property: -Doptimize.conservatively For best results, ProGuard's optimization algorithms assume that the processed code never intentionally throws NullPointerExceptions or ArrayIndexOutOfBoundsExceptions, or even OutOfMemoryErrors or StackOverflowErrors, in order to achieve something useful. For instance, it may remove a method call myObject.myMethod() if that call wouldn't have any effect. It ignores the possibility that myObject might be null, causing a NullPointerException. In some way this is a good thing: optimized code may throw fewer exceptions. Should this entire assumption be false, you'll have to switch off optimization using the -dontoptimize option. Tip
  • 14. 23 June 2016 Optimization Methods Optimization Technique Flags Safe? Impact Method inlining method/inlining/* Yes Peephole optimizations code/simplification/* Yes Unreachable Code removal code/removal/simple Yes Code removal code/removal/advanced Yes (ex. Obfuscated libs) Needed for logging removal, generally safe, but depends on configuration. Enum unboxing class/unboxing/enum Mostly yes Might lead to problems, especially when using EnumMap / EnumSet Variable allocation code/allocation/variable For Applications. Dx might crash when -keepparameternames is used (or LocalVariableTable is kept). Method de-synchronization method/marking/synchronized Yes Effect might not be noticable, Slow optimization Constant propagation field/propagation/value method/propagation/* Yes Class merging class/merging/* Mostly yes Might cause issues in rare cases. Field removal field/removal/writeonly Yes Tip
  • 15. 23 June 2016 Logging Removal Java Source: Smali: Log.d(TAG, "Hello world " + this.getClass().getName() + "!");   .line 31     invoke­virtual { p0, v5 }, Lcom/example/HelloWorldActivity;­>setContentView(Landroid/view/View;)V   .line 33     const­string v0, "Activity"     new­instance v1, Ljava/lang/StringBuilder;     invoke­direct { v1 }, Ljava/lang/StringBuilder;­><init>()V     const­string v2, "Hello world "     invoke­virtual { v1, v2 }, Ljava/lang/StringBuilder;­>append(Ljava/lang/String;)Ljava/lang/StringBuilder;     move­result­object v1     invoke­virtual { p0 }, Ljava/lang/Object;­>getClass()Ljava/lang/Class;     move­result­object v2     invoke­virtual { v2 }, Ljava/lang/Class;­>getName()Ljava/lang/String;     move­result­object v2     invoke­virtual { v1, v2 }, Ljava/lang/StringBuilder;­>append(Ljava/lang/String;)Ljava/lang/StringBuilder;     move­result­object v1     const­string v2, "!"     invoke­virtual { v1, v2 }, Ljava/lang/StringBuilder;­>append(Ljava/lang/String;)Ljava/lang/StringBuilder;     move­result­object v1     invoke­virtual { v1 }, Ljava/lang/StringBuilder;­>toString()Ljava/lang/String;     move­result­object v1     invoke­static { v0, v1 }, Landroid/util/Log;­>d(Ljava/lang/String;Ljava/lang/String;)I   .line 35
  • 16. 23 June 2016 Logging Removal ProGuard configuration: ­assumenosideeffects class android.util.Log {     public static boolean isLoggable(java.lang.String, int);     public static int v(...);     public static int d(...);     public static int i(...);     public static int w(...);     public static int e(...);     public static java.lang.String getStackTraceString(java.lang.Throwable); }
  • 17. 23 June 2016 Logging Removal Result: Why are there still objects/method calls?     const­string v1, "Hello world "     invoke­direct { v0, v1 }, Ljava/lang/StringBuilder;­><init>(Ljava/lang/String;)V     invoke­virtual { p0 }, Ljava/lang/Object;­>getClass()Ljava/lang/Class;     move­result­object v1     invoke­virtual { v1 }, Ljava/lang/Class;­>getName()Ljava/lang/String;     move­result­object v1     invoke­virtual { v0, v1 }, Ljava/lang/StringBuilder;­>append(Ljava/lang/String;)Ljava/lang/StringBuilder;     move­result­object v0     const­string v1, "!"     invoke­virtual { v0, v1 }, Ljava/lang/StringBuilder;­>append(Ljava/lang/String;)Ljava/lang/StringBuilder;
  • 18. 23 June 2016 Logging Removal Second try: Smali: Log.d(TAG, String.format("Hello world %s!", this.getClass().getName()); Tip const-string v1, "Activity" const-string v2, "Hello world %s!" new-array v3, v6, [Ljava/lang/Object; const/4 v4, 0 invoke-virtual { p0 }, Ljava/lang/Object;->getClass()Ljava/lang/Class; move-result-object v5 invoke-virtual { v5 }, Ljava/lang/Class;->getName()Ljava/lang/String; move-result-object v5 aput-object v5, v3, v4 invoke-static { v2, v3 }, Ljava/lang/String;->format(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String; move-result-object v2 invoke-static { v1, v2 }, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
  • 19. 23 June 2016 Logging Removal ProGuard configuration: ­assumenosideeffects class android.util.Log {     public static boolean isLoggable(java.lang.String, int);     public static int v(...);     public static int d(...);     public static int i(...);     public static int w(...);     public static int e(...);     public static java.lang.String getStackTraceString(java.lang.Throwable); } ­assumenosideeffects class java.lang.String {     public static java.lang.String format(...); } Tip
  • 20. 23 June 2016 Logging Removal Result: Better! Tip     new­array v0, v3, [Ljava/lang/Object;     const/4 v1, 0     invoke­virtual { p0 }, Ljava/lang/Object;­>getClass()Ljava/lang/Class;     move­result­object v2     invoke­virtual { v2 }, Ljava/lang/Class;­>getName()Ljava/lang/String;     move­result­object v2     aput­object v2, v0, v1
  • 21. 23 June 2016 Side Effect Checking Explicit (for library classes/methods): Implicit (for program classes/method): ● During optimization by analysing the actual code ● Can be prevented with -keep rules Note: removes invocations not methods themselves! -assumenosideeffects class xxx.yyy { … }
  • 22. 23 June 2016 Side Effect Example public static int sum(int a, int b) {    return a + b; } @Override public void onCreate(Bundle savedInstanceState) {     …     setContentView(xxx);     sum(10, 30);     … }   .line 57     invoke­virtual { p0, p1 }, Lcom/example/HelloWorldActivity;­>setContentView(Landroid/view/View;)V   .line 66   .line 57     invoke­virtual { p0, v2 }, Lcom/example/HelloWorldActivity;­>setContentView(Landroid/view/View;)V   .line 63     const/16 v0, 10     const/16 v1, 30     invoke­static { v0, v1 }, Lcom/example/HelloWorldActivity;­>sum(II)I   .line 66 Optimized:
  • 23. 23 June 2016 DexGuard Commercial extension of ProGuard Additional protection features: ● String/Class/Asset/Resource/Native library encryption ● Native library interface obfuscation ● Hide sensitive method calls via reflection ● Code obfuscation (control flow, arithmetic obfuscation) Resource shrinking Resource / Metadata inlining Multidex support ...
  • 24. 23 June 2016 DexGuard Overview Shrinking (-dontshrink) Optimization (-dontoptimize) Obfuscation (-dontobfuscate) String encryption Class encryption Asset encryption Resource encryption Native library encryption Code obfuscation Resource inlining Multidexing Splitdexing Zipalign Signing Reflect API calls
  • 25. 23 June 2016 DexGuard in Android builds Compiled XML res. DexGuard Application Java source Libraries Java bytec. XML res. Assets Aapt Javac Libraries Java bytec. Processed assets Processed XML res. Dalvik bytecode Application Java bytec. Signatures Application Native src Native libraries Processed native libraries Gcc
  • 26. 23 June 2016 DexGuard in Android builds (2) Jack Dex Guard Application Java source Libraries Java bytec. XML res. Assets Aapt Jill Libraries .jayce Dalvik bytecode Assets Compiled XML res. Signatures Assets Compiled XML res. Dalvik bytecode Signatures Assets Compiled XML res. Dalvik bytecode Jar signer Application Native src Native libraries Native libraries Native libraries Gcc
  • 27. 23 June 2016 Optimization Features in addition to ProGuard: ● Parallel Optimization → faster on multi-core machines ● New modifier 'includecode' for -keep rules ● Support for more fine-grained side-effect configuration → more effective code removal
  • 28. 23 June 2016 Logging Removal Java Source: Smali: Log.d(TAG, "Hello world " + this.getClass().getName() + "!");   .line 31     invoke­virtual { p0, v5 }, Lcom/example/HelloWorldActivity;­>setContentView(Landroid/view/View;)V   .line 33     const­string v0, "Activity"     new­instance v1, Ljava/lang/StringBuilder;     invoke­direct { v1 }, Ljava/lang/StringBuilder;­><init>()V     const­string v2, "Hello world "     invoke­virtual { v1, v2 }, Ljava/lang/StringBuilder;­>append(Ljava/lang/String;)Ljava/lang/StringBuilder;     move­result­object v1     invoke­virtual { p0 }, Ljava/lang/Object;­>getClass()Ljava/lang/Class;     move­result­object v2     invoke­virtual { v2 }, Ljava/lang/Class;­>getName()Ljava/lang/String;     move­result­object v2     invoke­virtual { v1, v2 }, Ljava/lang/StringBuilder;­>append(Ljava/lang/String;)Ljava/lang/StringBuilder;     move­result­object v1     const­string v2, "!"     invoke­virtual { v1, v2 }, Ljava/lang/StringBuilder;­>append(Ljava/lang/String;)Ljava/lang/StringBuilder;     move­result­object v1     invoke­virtual { v1 }, Ljava/lang/StringBuilder;­>toString()Ljava/lang/String;     move­result­object v1     invoke­static { v0, v1 }, Landroid/util/Log;­>d(Ljava/lang/String;Ljava/lang/String;)I   .line 35
  • 29. 23 June 2016 Logging Removal Result: Much better! Possible due to more fine-grained configuration:   .line 31     invoke­virtual { p0, p1 }, Lcom/example/HelloWorldActivity;­>setContentView(Landroid/view/View;)V   .line 35 ­assumenoexternalsideeffects public final class java.lang.StringBuilder {     public java.lang.StringBuilder();     public java.lang.StringBuilder(int);     public java.lang.StringBuilder(java.lang.String);     public java.lang.StringBuilder append(java.lang.String);     … }
  • 30. 23 June 2016 More DexGuard Goodies ● Default configurations for applications/libraries supporting many 3rd party libs ● Great support :-) ● Many samples ● Configuration debugging ● Java 8 language support → backported to Java 6/7 similar to retrolambda ● Planned: Stream API support for older Android devices ● Planned: Native code obfuscation
  • 31. 23 June 2016 The End Thanks for your attention!