# Constants Obfuscation

As for native code, the constants used in a Java class can provide hints for the reverse engineers about the purpose of the class.

This pass can be used to hide constants by masking them in a table.

If we consider the initialization of a ChaCha block in which the first four entries are initialized with `"expand 32-byte k"`

:

```
this.matrix[ 0] = 0x61707865;
this.matrix[ 1] = 0x3320646e;
this.matrix[ 2] = 0x79622d32;
this.matrix[ 3] = 0x6b206574;
```

After applying this pass, the initialization looks like this:

```
ChaCha20.a[ 0] = 0x2262775c;
ChaCha20.a[ 2] = 0x2fd5c988;
ChaCha20.a[ 4] = 0x093052e7;
ChaCha20.a[ 9] = 0x6b6cbd0a;
ChaCha20.a[10] = 0x79ec4b16;
ChaCha20.a[11] = 0x48c2f323;
ChaCha20.a[12] = 0x535be40d;
ChaCha20.a[13] = 0x5870b603;
...
this.matrix[ChaCha20.a[9] ^ 0x6B6CBD0A] = a[10] ^ 0x189C3373;
this.matrix[ChaCha20.a[0] ^ 0x2262775D] = a[11] ^ 0x7BE2974D;
this.matrix[ChaCha20.a[2] ^ 0x2FD5C98A] = a[12] ^ 0x2A39C93F;
this.matrix[ChaCha20.a[4] ^ 0x093052E4] = a[13] ^ 0x3350D377;
```

The `ChaCha20.a[]`

array holds the **masked** constants and the original `matrix`

accesses are
replaced with a lookup to the `ChaCha20.a[]`

array.

## When to use it?

You should enable this pass when you have (hard-coded) constants that are involved in sensitive computations.

## How to use it?

Within the dProtect configuration file we can enable this protection through:

```
-obfuscate-constants <class specifier>
```

In addition, it is highly recommended to combine this pass with Arithmetic Obfuscation as constants are usually associated with an arithmetic computation.

## Implementation

In its current form, this obfuscation pass works by tabulating the constants and by masking them with a xor.

Programmatically, the pass implements a Proguard `ClassVisitor`

that is used to add the static
`OPAQUE_CONSTANTS_ARRAY`

attribute:

```
@Override
public void visitProgramClass(ProgramClass programClass) {
ClassBuilder classBuilder = new ClassBuilder(programClass);
classBuilder.addAndReturnField(AccessConstants.PRIVATE |
AccessConstants.STATIC,
"OPAQUE_CONSTANTS_ARRAY", "[J");
}
```

`OPAQUE_CONSTANTS_ARRAY`

is a `long[]`

array that is used to store the masked constants collected by pass.
The collection of the constants is performed with the combination of an `InstructionVisitor`

and
a `ConstantVisitor`

.

Let’s consider the protection of `iconst_3`

(pushing 3 onto the stack).

This instruction can be visited tanks to the `InstructionVisitor.visitSimpleInstruction()`

overloaded method:

```
@Override
public void visitSimpleInstruction(..., SimpleInstruction instruction) {
switch (instruction.opcode) {
case Instruction.OP_ICONST_3: {
// Processing
}
}
```

The pass processes the value 3 associated with this instruction, by inserting (if not already present) the constant in an internal array of the pass:

```
// Processing
int value = instruction.constant;
int index = getOrInsert((long)value);
```

When inserting the value, the pass also generates a random *key* that is used to mask the original constant:

```
// Processing
int value = instruction.constant;
int index = getOrInsert((long)value);
Long key = keys.get(value); // Masking Key associated with the constants value
```

Then, the pass replaces the original `iconst_3`

with a lookup into the `OPAQUE_CONSTANTS_ARRAY`

:

```
// Equivalent to OPAQUE_CONSTANTS_ARRAY[index] ^ key
____.getstatic("OPAQUE_CONSTANTS_ARRAY")
.ldc(index)
.laload()
.l2i()
.ldc(key.intValue())
.ixor()
.__());
```

On the other hand, the `OPAQUE_CONSTANTS_ARRAY`

is filled with the (masked) constants by updating
the `static { }`

constructor of the class:

```
new InitializerEditor().addStaticInitializerInstructions(
____ -> {
// Equivalent to new long[constants.size()]
____.ldc(constants.size())
.newarray(Instruction.ARRAY_T_LONG)
.putstatic(programClass, arrayField);
// Push the constans
for (int i = 0; i < constants.size(); ++i) {
Long value = constants.get(i);
Long key = keys.get(value);
Long encoded = value ^ key;
____.getstatic(programClass, arrayField)
.sipush(i)
.ldc2_w(encoded)
.lastore();
}
});
```

## Limitations

First, this pass does handle (yet) double or float constants. In addition, the constants targeted by this
pass are **ALWAYS** masked with a xor operation which could be improved by using random arithmetic-based masking.

This pass is also unlikely resilient against a Jadx plugin or a Proguard-based deobfuscation pass that would
identify the `OPAQUE_CONSTANTS_ARRAY`

attribute and the instructions that use it.

JEB Decompiler also published a blog post about how this protection can be defeated: *Reversing dProtect*.

###### Attacks

###### Reversing dProtect - Constants Scrambling

*This blog post explains how JEB Decompiler can recover constants protected with dProtect.*

###### DOptUnsafeArrayAccessSubstV3.java

*JEB Script used for recovering obfuscated constants.*