A look inside an Android app protector

Let’s have a quick look at one feature of this well-known Android application protector, the string encryption mechanism. The app in question is a version of Cyanide.

First, access to strings inside a protected class are replaced by calls to a static private decryption routine. That routine accesses a static private array containing all protected strings within the class. That array is created by the class initializer upon loading:

1

The decryption routine usually takes 3 arguments, although in some simpler cases, it may only take two arguments. The arguments may also be shuffled. (Note: from a Dalvik standpoint, that routine is oddly structured. Although JEB’s decompiled output is structurally fine, a for-loop construct cannot be created, mainly because of the irregular jump inside the first if-cond branch.)

The screenshot below represents that decryption routine. The name was obfuscated by the app protector. Notice the constant numerals that have been circled in that code snippet: they are the decryption routine characteristics.

2

The following screenshot shows the same piece of code after marking it up. As you can see, the encryption algorithm is fairly simple: the current output character is derived from the previous character as well as the current byte of the encryptedStrings array. A constant (-8 in this case) is added to yield the final character. The initial length (length) as well as initial character (curChar) are also offset by hard-coded constants. These three constants (0x3E, 0x199, -8) characterize the decryption routine, and are unique for each routine. The curChar parameter acts as the decryption key.

3

You may customize this Python script to decrypt the strings:

#!/usr/bin/python
# decryptor

# customize
strings = [0x4C, 0xE, 2, 9, -7, 0x10, -54, 0x3E, 0x17, -9, -44, 0x4C, 0xA, ...]
c0, c1, c2 = (0x199, 0x3E, -8)

def decrypt(length, curChar, pos):
  length += c0
  curChar += c1
  r = ''
  for i in range(length):
    r += chr(curChar & 0xFF)
    curEncodedChar = strings[pos]
    pos += 1
    curChar = curChar + curEncodedChar + c2
  return r

Combined with reflection (another feature of the protector), the protection can be pretty effective.

Published by

Nicolas Falliere

Author of JEB.

10 thoughts on “A look inside an Android app protector”

  1. So, as I understood, it does not make any sense to spend money to buy Dexguard. Right?
    I am thinking how to hide string data in apk. In .NET word it is easy…

    1. Dexguard is effective for blanket processing. However, like nearly all protections, it will only slow down a determined attacker.

  2. DexGuard has been updated a couple of times in the meanwhile, so the above techniques no longer work… DexGuard’s goal is to raise the bar against reverse engineering and cracking. It is pretty effective — even security experts spend a lot of time studying its output, which is different for every application.

    (I am the developer of ProGuard and DexGuard)

  3. Thanks for sharing!
    I checked this, but found it is still an advanced Java obfuscation. Also I tried many ways except this one. You may try APK Protect PC Edition. This is free and have the same function.
    I noticed a very effective method. APK Protect Professional Edition, this is very different from other methods: http://www.apkprotect.com.

Leave a Reply

Your email address will not be published. Required fields are marked *


The reCAPTCHA verification period has expired. Please reload the page.

*