Renaming and Refactoring#
The DEX plugin provides smart renaming capabilities: renaming of items is done consistently throughout the code base.
Most internal items can be renamed (internal items are those defined in the DEX, as opposed to external items, simply referenced in the DEX, but whose definition is located elsewhere). What can be renamed:
- class names (as well as interfaces and enums defined in the DEX)
- method names
- field names
- labels (addresses)
- package names
- variables (in decompiled units)

Renaming Methods#
Proper refactoring is especially important when renaming non-static methods (virtual methods, interface methods) which may be part of a hierarchy of other methods, overridden parents or overriding children.
Example: renaming B:a() should also rename A.a() and C.a()
A.a():Object
|
B.a():String
|
C.a():String
Renaming must also take into account indirect references to methods, something common when invoking virtual methods located in other classes, but which can be used to obfuscate a program further.
A.a()
|
B.a() - within B: invoke-virtual A.a() -> actually refers to B.a()
Things can get relatively complicated when hierarchies involve multiple inheritance through one or more interfaces.
Renaming Fields#
To some degree, the same applies to fields. Unlike methods, fields cannot be overridden; they are always accessed in a direct way, i.e. resolution is entirely determined at compile-time. However, field masking adds complications.
A.i:int public
|
B.i:int public - this field masks A.i
Shall a rename action of A.i also rename B.i? Conversely, shall renaming B.i also rename A.i? Theoretically, no. Those two fields are not related. However, at the moment, the DEX plugin renames both fields to maintain some degree of visual consistency with the original binary, regardless of whether field masking was done voluntarily or not, with obfuscating intent or not.
This is likely to change with the addition of an option to let users decide how they want to perform renaming.
Reorganizing code#
Packages can also be renamed. Users can also create additional packages and move packages and classes to other packages.
This feature can come in handy when dealing with obfuscated code for which entire type hierarchies were flattened out into a handful (sometimes single) set of packages. Most obfuscators, including the ubiquitous Proguard or r8, can do that.
If you want to explore refactoring further, in particular hierarchy reconstruction, have a look at this sample script DexCluster.py.
Forcing inner classes#
Classes can be moved inside other classes or methods. Whenever it is deemed possible, a class moved inside a method will be made anonymous. This process of anonymizing classes is an efficient way to defeat name-based obfuscation and annotation-scrapping-based obfuscation, that usually prevent the reconstruction of inner classes in general, and anonymous classes in particular.
While drag&dropping in the GUI is an option for targeted refactoring, scripting is always preferable for bulk operations. Refer to IDexUnit.moveTo() in the API doc.
Auto-rename#
Auto-renaming is an optional standard Action also implemented by the DEX plugin. As its name implies, it can perform automatic blanket renaming of all items of a unit. In the case of DEX units, they include types, methods, fields, etc.
The action is semi-customizable by each plugin, as can be seen in the API. In the case of the DEX plugin, three policies are implemented. Each policy defines a set of legal characters for items. The loosest policy permits all characters in the printable ascii range (something already relatively strict considering the actual legal character ranges for Java identifiers); the strictest considers all current names (except those that were already defined) invalid, and therefore, will rename everything.
The obfuscation applied below is using right-to-left unicode characters to complicate rendering:
After auto-renaming (standard policy):



