[Code Obfuscation: ProGuard and R8 Tools Review]

In terms of code, obfuscation refers to making a program's source text or code impossible to analyze or modify during decompilation while keeping its functionality. Obfuscation is used to protect code from unauthorized access.

How it works

The majority of obfuscation methods transform the following aspects of code:

  • Data: makes code elements seem like something else
  • Code stream: makes the program's logic look absurd or undetermined
  • Format structure: applies various data formatting techniques, renaming identifiers, deleting code comments, etc.

In this article, we'll discuss two obfuscators: ProGuard by GuardSquare and R8 by Google. This are the most popular tools at the time of writing.

ProGuard is the coolest kid on the block. Everyone's heard of it and knows how to use it.

Research into the optimization process for Android builds will also turn up R8. R8 is a bit of a mystery kid with ambitions and famous parents. When you start reading about it, you start to hear a voice in the back of your head whispering "Come to R8."

How ProGuard works

ProGuard aims to change the names of objects, classes, and methods to deter analysis by reverse engineers. It also optimizes code by deleting unused resources in a program. Some argue that ProGuard can't be called a classical obfuscator, but that doesn't change the fact that it still obfuscates code.

ProGuard is an open-source utility that works with Java code. It's also written using Java. The program is a jar file that reorganizes the symbols in our code, optimizing and strengthening it.

The author of one article very clearly explained ProGuard's rules:

The rules of ProGuard are transferred from project to project and are considered untouchable. It works, so why change it. Otherwise, you could get red lines that no one knows or wants to know how to fix. The rules were defined by some oracle. If you wants to find them, you need to spin 7 times, turn into a bird, and fly southwest two hours and forty-three minutes.

The way ProGuard works can be divided into several stages:

  1. Retrieving the defined rules
  2. Optimization
  3. Removal of resources involved in optimization
  4. Renaming objects
  5. Recording the project in the designated directory in the updated state

You can launch ProGuard with a manual command:

java -jar proguard.jar @android.pro

proguard.jar is the ProGuard project and android.pro are the rules for how it works with input and output data.

ProGuard is the most popular code optimization and security solution. It's practically the only option available, given that the other programs are either behind a paywall or sitting in Github gathering dust. Using them isn't the best idea, because the main problem in the minification, mixing, repacking, and optimization of code is that a collision can occur at any time because it's difficult to consider everything that can happen with the code. Moreover, it's essential to use as many tests as possible with this type of utility.

The states of PG's optimization

img1

An application build

img2

All the artifacts of the optimization process are indicated as rectangles, and the optimization itself is shown as arrows with the corresponding titles. So, .jar files are shrunk and then (already changed) are optimized, etc. Each of the optimizations are optional: shrink, optimize, obfuscate, or preverify. You don't need to obfuscate or shrink code if you don't need to. However, the order of operation can't be changed. In PG's current integration, you can't optimize code before you shrink it. This rule exists to reduce extra work. The idea is like with wallpaper: it's better to remove it and then clean it up than the other way around (you'll understand this better when you start to optimize).

You can read more about each stage here

ProGuard increases the time of a build. To solve this issue, you can divide its settings into application "flavors," meaning you'll turn ProGuard off when you don't need it, such as during the development flavor.

How D8 and R8 work

Google positions D8 as a next-generation DEX compiler and R8 as an obfuscator.

Let's recalls the PG scheme for building an application. The .dex file is complied with the DEX complier.

img3

This is how the compilation process for .dex looked before D8. Note the number of steps.

Compilation scheme after D8:

pic5

D8 took over the desugar stage and reduced the overall number of steps, leading to:

  • Faster complization of source code.
  • Reduction in the size of the outpput .dex.

Now let's have a look at the build process after R8 was introduced:

img7

It optimized the build process by reducing intermediary steps.

By default R8 is used with version 3.4 AGP and D8 with an older version.


R8 vs ProGuard

What Google says:

R8 (together with D8) shrinks and compiles .dex 2 times faster in compact and full modes.

The size of the output .dex is a bit smaller than with PG.

What GuardSquare says:

Long ago, in 2019, GuardSquare argued inf avor of PG, nothing the large amount of optmized code. As of 2024, R8 has significantly improved in terms of code optimization in comparison to ProGuard. R8 offers one-way optimization and activates additional modes for improving productivity up to 30%.

Conclusions:

  • The task, third-party services, and mobile application are the components that determine the final size of the application, its speed, and how safe it is to use. The requirements for each of these components define which solution to implement.
  • The build process for Android applications is composed of these main stages: java / kotlin compilation and dex compilation. There are strict contracts between these main stages that can lead to additional stages. For example, code and resource optimization.
  • Build optimization includes these stages: shrinking the code and resources (memory); optimizing the code (speed); and obfuscation (security).
  • Obfuscation involves making code difficult to analyze while maintaining its functionality. Confusing names is one of many obfuscation techniques that are used in popular optimizers.
  • ProGuard is a java byte code optimizer that can optimize Android application builds. It was developed by GuardSquare.
  • D8 and R8 are tools developed by Google to improve the build process (D8) and its optimization (R8). R8 is advertised as a replace for ProGuard.

Materials:

Shrink, obfuscate, and optimize your app  |  Android Studio  |  Android Developers

ProGuard Manual: Home | Guardsquare

Other helpful links:

Android Developers, Medium. Practical ProGuard rules examples.

Android Developers, Medium. Troubleshooting ProGuard issues on Android

IMStudio, Medium. Android Journey: Proguard, D8, R8 what are they?

Otus, YouTube. ProGuard / R8 …

Android Developers, YouTube. Shrinking Your App with R8.

Yonatan V. Levin. Android CPU, Compilers, D8 & R8.

Jake Wharton, R8 Optimizations.