Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hiding strings in Obfuscated code

I just Obfuscated my Android code using proguard and then decompiled it. There are a number of strings I would really like to hide from prying eyes. When I decompiled my code the strings were there for everyone to see...and change. One of the strings is a URL to my licensing server and they could in effect change the url to point to a fake server (as I will be releasing the server code to the public). What is the best way of hiding this sort of information?

Also, I noticed that the R class strings are all random numbers but I can't find the R class in the decompiled code. Where is it?

Foe example I see: new SimpleCursorAdapter(localActivity, 2130903058, localCursor, arrayOfString, arrayOfInt);

2130903058 is a layout file but what is it referencing? The number means nothing unless it is pointing to some sort of address.

like image 493
jax Avatar asked Dec 13 '10 09:12

jax


People also ask

Can you obfuscate obfuscated code?

Obfuscation means to make something difficult to understand. Programming code is often obfuscated to protect intellectual property or trade secrets, and to prevent an attacker from reverse engineering a proprietary software program. Encrypting some or all of a program's code is one obfuscation method.

What is string obfuscation?

String obfuscation is an established technique used by proprietary, closed-source applications to protect intellectual property. Furthermore, it is also frequently used to hide spyware or malware in applications. In both cases, the techniques range from bit-manipulation over XOR operations to AES encryption.

Should I obfuscate my code?

If you're deploying code in untrusted environments where you want to protect your source code, you should almost always use at least a basic obfuscator to rename functions, methods, and properties to make decompiling take a bit more effort.


2 Answers

Assuming you are happy with obscure rather than secure, there a number of mechanisms you could use, but obfuscaters like proguard are not going to be able to help you.

To achieve this you will need to do encoding or encryption of the string yourself, the approach you use depends on what you are trying to defend against, if it you are just trying to hide from obvious inspection, than encoding may be sufficient (see android.util.Base64, http://developer.android.com/reference/android/util/Base64.html). Note that encoding is in NO WAY SECURE and all it will to is remove the obvious reference to your site.

If you are trying to defend against something more, then you could move to actually encrypting the string, to do this you would use a symmetric cipher like AES via javax.crypto.Cipher, http://www.androidsnippets.org/snippets/39/index.html provides a decent usage example. Again this is more annoying then secure to would be hackers, as you will need to store the key somewhere in your jar thus negating any cryptographic security.

To make this clearer, the basic steps would be:

  1. Manually create an encrypt your string using a known key.
  2. Convert your code to use a decrypted version of this string, example:

Before:

public class Foo {     private String mySecret = "http://example.com";      ... } 

Becomes:

public class Foo {     private String encrypted = "<manually created encrypted string>";     private String key = "<key used for encryption";     private String mySecret = MyDecryptUtil.decrypt(encrypted, key);      ... } 

A (good) alternative to all of this is considering using a third party drm solution such as the licensing server google provides http://android-developers.blogspot.com/2010/07/licensing-service-for-android.html. This may be more secure than something you roll your self, but is subject to very similar limitations to what I described above.

like image 142
Mark Hibberd Avatar answered Sep 22 '22 18:09

Mark Hibberd


Hi all.

  1. Let secret be the text you want to hide

  2. Find the keyhash of your debug/release.keystore. Let k1 be this key.

(use tools keytool+openssl: keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64 )

  1. Use a tool (external to the android code) to encrypt secret with k1

    encrypted = encode (secret, k1)

(For instance: https://jwt.io, for java: https://github.com/jwtk/jjwt).

  1. In your android java code write down encrypted. When you need the decoded version of encrypted (this is, the original secret) write

original = decode(encrypted, get_my_keyhash_programmatically() )

That's all. This works because the original secret is not shown on java source code, neither the k1 to decode it. And, if a hacker wants to print your decoded secret, he must change code and recompile, signing his .apk with his own keystore not yours, and thus not getting the right original secret. (The "only" point is whether k1 can be figured out from your original .apk).

Note: get_my_keyhash_programmatically():

try {     PackageInfo info = getPackageManager().getPackageInfo(             "el nombre de su paquete por ejemplo com.tarea.u8",             PackageManager.GET_SIGNATURES);     for (Signature signature : info.signatures) {         MessageDigest md = MessageDigest.getInstance("SHA");         md.update(signature.toByteArray());         Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));     } } catch (PackageManager.NameNotFoundException e) {  } catch (NoSuchAlgorithmException e) {  } 
like image 43
cibercitizen1 Avatar answered Sep 24 '22 18:09

cibercitizen1