2015-06-11

DexGuard is a commercial tool used for protecting android binaries (APK) mainly from reversing and tampering. It provides features like code obfuscation, class encryption, string encryption, asset/resource encryption, tamper protection, anti-debugger checks, VM/Environment checks, SSL pinning etc.

Me and my colleague Sachinraj decided to evaluate the enterprise version of DexGuard 6.1. After our analysis, It was clear that DexGuard String Encryption which looks more like a tricky obfuscation and is easily reversible. We compiled a sample android application with DexGuard String and Class encryption enabled.

As per DexGuard documentation,

You can encrypt entire classes by specifying them with the option -encryptclasses.

For example:

There are a few alternative ways to specify which constant strings in the code should be encrypted, with the option -encryptstrings. The shortest way is to specify the strings literally:

The sample android application contains two activity. The first activity contains an OK button which on press will invoke the second activity using Intent. We pass a hardcoded secret string from first activity to the second activity via Intent extra.

The  source code of the first activity (MainActivity.java) is shown below:

We defined the following rules in dexguard-project.txt

The above rules should encrypt the string SuperZS3cur!ty0R0CK3S and encrypt the classes MainActivity and Secret. We compiled the code with DexGuard enabled and analysed the APK using Mobile Security Framework which is configured to use the CFR decompiler. You can also use CFR decompiler in standalone to decompile the APK. Due to the protection enforced by DexGuard, we got large chunk of decompiled java files with strange names.



Since we have the MainActivity.java, we started our analysis from there.


Here if you observe the above decompiled code, there are two strange imports.

import o.\u062f;
import o.\u706c;

As the decompiled source contains the following code,

public class MainActivity extends \u062f {

public Button \u02c9;



If you compare it with our initial source code, you can easily conclude that  \u062f is nothing but ActionBarActivity and \u02c9 is the button variable bt.

Lets look into the second import file o.\u706c.

If you convert \u706c to unicode text, you will get 灬.

Now we need to find the file o/灬.java

The file contains the following code

This decompiled code looks like CFR decompiler failed at some places to decompile it completely but gave us a good hint about the logic. If you analyse the code, you can see the line which contains the code.

view.putExtra("SECURE", \u706c.\u02ca(0, 0, 0).intern());

This looks similar to ask.putExtra("SECURE",secret); in our initial source code. Now it’s clear that \u706c.\u02ca(0, 0, 0).intern() method is responsible for decrypting the encrypted secret at Runtime. If we can successfully recreate this method, then we will be able to decrypt the secret. CFR decompiler did half the job for us and remaining is on us.

We created a Java program with the above decryption method and it welcomed us with lots of errors.

We added appropriate data types but still we had some missing code there. After looking into this code, We figured out the pseudo logic of the decryption method.

This line if(var3_5 != null) ** GOTO lbl19 gave us a hint about the logic.
var3_5 is nothing but the byte array \u02cb. It will never become null. So the following code (marked in red) will never get invoked.

So we removed those unnecessary code and again if you carefully observe the code, you can see that GOTO lbl19 goes inside the do-while loop and there is two lines of code (marked in blue) which is skipped for the first time execution of the loop and when the first loop is finished, the successive loops will include the code. So we quickly wrote a PoC with that logic.

File: DexRev.java

If you run the above PoC, you will get the output.

Decrypted: SuperZS3cur!ty0R0CK3S

And DexGuard’s so called String Encryption is reversed!.

NOTE

Later we came to know about an old blog that talks about string decryption in DexGuard. We also found that the blog was talking about the issue identified in an older version of DexGuard and we saw the following comment from the author of DexGuard.

Disclosure

This issue was reported to Eric, the founder of ProGuard and DexGuard. Eric Acknowledged the Report asked for a PoC and mentioned that string encryption is lightweight and when employed with class encryption, it will be difficult to obtain the plaintext information.

Show more