Class Splitter Obfuscation Algorithm

Authors

Ashok Purushotham (ashok@cs.arizona.edu)
Rathna Prabhu Rajendran (prabhu@cs.arizona.edu)

Description

A class C is split into two classes C1 and C2, such that C2 inherits from C1. C1 has fields and methods that only refer to themselves, whereas C2 has fields and methods that can refer to themselves as well as fields and methods in C1. Bytecode references to C will have to be replaced with references to C2.

Dependency Graph Generation
We create a dependency graph G for class C. The nodes of G are the members of C. There is an edge from A to B in G, if the declaration of A must be in scope of B. If there is a path from C to Y in G, then Y must be declared in the child class during splitting. If there is a path from X to Y in G, then either X and Y are both declared in the same class or X is declared in the parent class C1.

Topological sort of the Dependency Graph
We perform a topological sort of the dependency graph to know what methods and variables are to be put in which classes. We decide on the placement of the methods and fields in the inheritance tree, based on the results of the topological sort. For instance, the method P must be in the scope of the class in which Q is defined. So Q can be put in the same class as P or in some class inheriting from the class defining P. This ensures that the obfuscation is semantics preserving and gives the same results as before.

Example

Consider the following simple code sample C.java, to which we'll apply the obfuscation technique.

        class C {
          float f;
          int v;
          public C( ) { }
          public void P( ) {
            f = 1.2;
          }
          public void Q( ) {
            v = 1;
            P( );
          }
        }
    

After obfuscating:

        class C0 {
          float f;
          int v;
          public C0( ) { }
        }
        class C1 extends C0 {
          public C1( ) { }
          public void P( ) {
            f = 1.2;
          }
        }
        class C extends C1 {
          public C( ) { }
          public void Q( ) {
            v = 1;
            P( );
          }
        }
    

Configuration

No additional configuration parameters are required to carry out this obfuscation.

References