PreEmptive Protection - DashO v8.1 User Guide

Dynamic Class Loading

Overview

The forName() method of java.lang.Class is the way to load classes dynamically at runtime. It is impossible for PreEmptive Protection - DashO to determine what classes are dynamically loaded in all cases. Consider the following code:

public Object getNewClass() {
    String newClassName = getUserInputString();
    try {
        Object newClass = Class.forName(newClassName).newInstance();
        return newClass;
    } catch(Exception e) {
        // handle
    }
}

This code loads a class by name and dynamically instantiates it. In addition, the name comes from a string input by the user. There is no way for DashO to predict which class names the user will enter. The solution is to exclude the names of all potentially loadable classes (method and field renaming can still be performed). This is where manual configuration is required.

Note:

Incorrect specification of dynamically loaded classes can cause obfuscated applications to fail at runtime.

Predictable Dynamic-Loading

The simplest case is when you know your application well enough to know exactly what classes could be loaded via dynamic-loading. If the dynamically loaded classes share a base class or common interface:

String s = getShapeName();
Shape myShape = (Shape)Class.forName(s).newInstance();
myShape.draw();

In this example, DashO’s can detect this pattern automatically and include all Shape classes. If another type of creation pattern is used the classes would need to be added individually in the entrypoints section of the DashO configuration file:

<entrypoints>
    <classes name="Triangle"/>
    <classes name="Rectangle"/>
</entrypoints>

In this case DashO will be able to remove unused methods from the Shape hierarchy.

Unpredictable Dynamic-Loading

In cases where the dynamically loaded classes would not know at the time the application is obfuscated, for example, a user interface building application could allow users of the application to include their own or third-party components, the existing classes must be added as unconditional entry points.

<entrypoints>
    <unconditional name="Triangle"/>
    <unconditional name="Rectangle"/>
</entrypoints>

This has several ramifications:

  • Regardless of removal options, no methods or fields will be removed from an unconditionally included class.

  • Regardless of renaming options, neither the class nor its members will be renamed.

  • All methods within the class will be treated as entry point methods.

These rules enforce the idea that your interface to as-yet-unknown classes will remain intact.

Reflection Report

DashO has several facilities to allow you to specify how or what is dynamically loaded. The fornamedetection option in DashO handles most or all dynamically loaded class instances.

<global>
    <option>fornamedetection</option>
</global>

DashO reports all places it finds usage of forName(). This is provided as part of the report file and as output after dependency analysis. Note that the fornamedetection option will not give a wrong answer but it may give no answer at all. Manual configuration is required in those instances where DashO reports “unable to determine” dynamically loaded class.

NOTE:
Reflection use public void com.yoyodyne.Application.getInterface() –
    java.lang.Class.newInstance() -
    [BaseInterface Possible: InterfaceImplementor]
Reflection use public boolean com.yoyodyne.Test.connect() -
    Class.forName()
Reflection use public float com.yoyodyne.Test.calculate() -
    Class.forName() - [com.yoyodyne.Linker]

Since DashO is unable to determine what class is dynamically loaded in the method connect(), manual configuration becomes necessary. The class that is dynamically loaded in this method must be included using the <classes> tag under the <entrypoints> section.

If DashO finds reflection usage and you do not specify the force global option, DashO will not create any output classes or jars.

PreEmptive Protection - DashO Version 8.1.0. Copyright © 2017 PreEmptive Solutions, LLC