Hiding Strings in Obfuscated Code

Hiding strings in Obfuscated code

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.

How to hide a string in binary code?

I'm sorry for long answer.

Your answers are absolutely correct, but the question was how to hide string and do it nicely.

I did it in such way:

#include "HideString.h"

DEFINE_HIDDEN_STRING(EncryptionKey, 0x7f, ('M')('y')(' ')('s')('t')('r')('o')('n')('g')(' ')('e')('n')('c')('r')('y')('p')('t')('i')('o')('n')(' ')('k')('e')('y'))
DEFINE_HIDDEN_STRING(EncryptionKey2, 0x27, ('T')('e')('s')('t'))

int main()
{
std::cout << GetEncryptionKey() << std::endl;
std::cout << GetEncryptionKey2() << std::endl;

return 0;
}

HideString.h:

#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/seq/enum.hpp>

#define CRYPT_MACRO(r, d, i, elem) ( elem ^ ( d - i ) )

#define DEFINE_HIDDEN_STRING(NAME, SEED, SEQ)\
static const char* BOOST_PP_CAT(Get, NAME)()\
{\
static char data[] = {\
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH_I(CRYPT_MACRO, SEED, SEQ)),\
'\0'\
};\
\
static bool isEncrypted = true;\
if ( isEncrypted )\
{\
for (unsigned i = 0; i < ( sizeof(data) / sizeof(data[0]) ) - 1; ++i)\
{\
data[i] = CRYPT_MACRO(_, SEED, i, data[i]);\
}\
\
isEncrypted = false;\
}\
\
return data;\
}

Most tricky line in HideString.h is:

BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH_I(CRYPT_MACRO, SEED, SEQ))

Lets me explane the line. For code:

DEFINE_HIDDEN_STRING(EncryptionKey2, 0x27, ('T')('e')('s')('t'))

BOOST_PP_SEQ_FOR_EACH_I(CRYPT_MACRO, SEED, SEQ)
generate sequence:

( 'T'  ^ ( 0x27 - 0 ) ) ( 'e'  ^ ( 0x27 - 1 ) ) ( 's'  ^ ( 0x27 - 2 ) ) ( 't'  ^ ( 0x27 - 3 ) )

BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH_I(CRYPT_MACRO, SEED, SEQ))
generate:

'T' ^ ( 0x27 - 0 ), 'e' ^ ( 0x27 - 1 ), 's' ^ ( 0x27 - 2 ), 't' ^ ( 0x27 - 3 )

and finally,

DEFINE_HIDDEN_STRING(EncryptionKey2, 0x27, ('T')('e')('s')('t'))
generate:

static const char* GetEncryptionKey2()
{
static char data[] = {
'T' ^ ( 0x27 - 0 ), 'e' ^ ( 0x27 - 1 ), 's' ^ ( 0x27 - 2 ), 't' ^ ( 0x27 - 3 ),
'\0'
};
static bool isEncrypted = true;
if ( isEncrypted )
{
for (unsigned i = 0; i < ( sizeof(data) / sizeof(data[0]) ) - 1; ++i)
{
data[i] = ( data[i] ^ ( 0x27 - i ) );
}
isEncrypted = false;
}
return data;
}

data for "My strong encryption key" looks like:

0x00B0200C  32 07 5d 0f 0f 08 16 16 10 56 10 1a 10 00 08  2.]......V.....
0x00B0201B 00 1b 07 02 02 4b 01 0c 11 00 00 00 00 00 00 .....K.........

Thank you very much for your answers!

Java - Are there any ways to obfuscate/hide strings to prevent against decompilation?

You can put them in a resource file and encrypt it using AES (for example). Then on the application initialization extract the data.

Obfuscate Strings in Java

Taking a look back at this question after almost 2 years, This question has gotten quite a lot of attention, I have found some obfuscators that I ended up using for String obfuscation but every Obfuscation can be broken. This is my List of obfuscators that encrypts Strings I will start of by listing paid obfuscators.

1. Zelix Klass Master

Their official website is https://zelix.com

This is one of the best java obfuscators for either jar or android in my opinion.
How ever It's not cheap as expected because of how good the obfuscator is.

A single license can cost you $239 If you are a small developer or $479 if you are a team of developer (Comapany).

You can see the list of features here

2. DexGuard

Their official website is https://www.guardsquare.com/en

DexGuard is an Obfuscator made by the people who are behind Proguard

This is the second best obfuscator in my opinion. The name obfuscation is way better then the name obfuscation on Zelix.

I am not sure about their pricing since I have never used it but I have seen it being used on applications. How ever you can request a pricing here

Free Obfuscators.

You can find free alternative's such as StringCare and Paranoid

They aren't as good as the one's I listed above, It would take at most 5 seconds for someone with basic knowledge of java to crack your program with these two tools.

Obfuscation: hide hardcoded values in java

For one, you shouldn't just write

String FROM_CHAR2=new String(new char[]{102,114,111,109,95,99,104,97,114,115,95,50});

It's a dead give-away that the char array is actually a String.

You can do a combination of the followings:

  1. put your "String" in an int[] array
  2. or even better, break your String into several int arrays
  3. calculate/manipulate the array's values at various stage of the application, so its value will only become valid at a certain interval during a runtime, guaranteeing that it won't be deciphered at a curious glance by decompiling your code
  4. passes the array(s) back and forth, through local variables, back to instance variables, etc, before finally converting the arrays to a single array to be passed to the String constructor
  5. immediately set the String to null after use, just to reduce the amount of time the actual String exist at runtime

Techniques for obscuring sensitive strings in C++

Basically, anyone with access to your program and a debugger can and will find the key in the application if they want to.

But, if you just want to make sure the key doesn't show up when running strings on your binary, you could for instance make sure that the key is not within the printable range.

Obscuring key with XOR

For instance, you could use XOR to split the key into two byte arrays:

key = key1 XOR key2

If you create key1 with the same byte-length as key you can use (completely) random byte values and then compute key2:

key1[n] = crypto_grade_random_number(0..255)
key2[n] = key[n] XOR key1[n]

You can do this in your build environment, and then only store key1and key2 in your application.

Protecting your binary

Another approach is to use a tool to protect your binary. For instance, there are several security tools that can make sure your binary is obfuscated and starts a virtual machine that it runs on. This makes it hard(er) to debug, and is also the convential way many commercial grade secure applications (also, alas, malware) is protected.

One of the premier tools is Themida, which does an awesome job of protecting your binaries. It is often used by well known programs, such as Spotify, to protect against reverse engineering. It has features to prevent debugging in programs such as OllyDbg and Ida Pro.

There is also a larger list, maybe somewhat outdated, of tools to protect your binary.

Some of them are free.

Password matching

Someone here discussed hashing password+salt.

If you need to store the key to match it against some kind of user submitted password, you should use a one-way hashing function, preferrably by combining username, password and a salt. The problem with this, though, is that your application has to know the salt to be able to do the one-way and compare the resulting hashes. So therefore you still need to store the salt somewhere in your application. But, as @Edward points out in the comments below, this will effectively protect against a dictionary attack using, e.g, rainbow tables.

Finally, you can use a combination of all the techniques above.



Related Topics



Leave a reply



Submit