How to hide a string in binary code?

Viewed 64071

Sometimes, it is useful to hide a string from a binary (executable) file. For example, it makes sense to hide encryption keys from binaries.

When I say “hide”, I mean making strings harder to find in the compiled binary.

For example, this code:

const char* encryptionKey = "My strong encryption key";
// Using the key

after compilation produces an executable file with the following in its data section:

4D 79 20 73 74 72 6F 6E-67 20 65 6E 63 72 79 70   |My strong encryp|
74 69 6F 6E 20 6B 65 79                           |tion key        |

You can see that our secret string can be easily found and/or modified.

I could hide the string…

char encryptionKey[30];
int n = 0;
encryptionKey[n++] = 'M';
encryptionKey[n++] = 'y';
encryptionKey[n++] = ' ';
encryptionKey[n++] = 's';
encryptionKey[n++] = 't';
encryptionKey[n++] = 'r';
encryptionKey[n++] = 'o';
encryptionKey[n++] = 'n';
encryptionKey[n++] = 'g';
encryptionKey[n++] = ' ';
encryptionKey[n++] = 'e';
encryptionKey[n++] = 'n';
encryptionKey[n++] = 'c';
encryptionKey[n++] = 'r';
encryptionKey[n++] = 'y';
encryptionKey[n++] = 'p';
encryptionKey[n++] = 't';
encryptionKey[n++] = 'i';
encryptionKey[n++] = 'o';
encryptionKey[n++] = 'n';
encryptionKey[n++] = ' ';
encryptionKey[n++] = 'k';
encryptionKey[n++] = 'e';
encryptionKey[n++] = 'y';

…but it's not a nice method. Any better ideas?

PS: I know that merely hiding secrets doesn't work against a determined attacker, but it's much better than nothing…

Also, I know about assymetric encryption, but it's not acceptable in this case. I am refactoring an existing appication which uses Blowfish encryption and passes encrypted data to the server (the server decrypts the data with the same key).

I can't change the encryption algorithm because I need to provide backward compatibility. I can't even change the encryption key.

23 Answers

One can use llvm-obfuscator (e.g. this fork) to have transparent string encryption. Setup may be kind of painful, especially if you want to integrate this in XCode (instructions available online 1, 2, but require adaptations for each new release of llvm and of XCode).

As others mentioned obfuscating strings is not a good way to achieve protection. If you do not want a casual examination of the string in the binary executable; then there are a couple of things that I would do.

I would create a large master string (Ms) and embed individual parts of the string to be protected (S1) inside it at different locations in the string (p1,p2,p3... etc) Make those locations quite random. At each location, I will place a small substring of S1. Each substring can be of varying length (l1, l2, etc). Then in the code, I'll dynamically retrieve each part and concatenate all the parts together to reconstruct S1 in code. The code therefore stores two arrays of integers: One for the getting each substring position [p1,p2,p3...], and the second array will explain how many characters to read from each position [l1,l2,l3...].

In such a case the master string (Ms) would be visible, but the curious person will not be able to know how to get back S1 unless the code is reverse engineered, the two arrays retrieved and the same process carried out. Of course the master string (Ms) should be reasonably large and quite random.

In a few cases such strings can be made stronger. In case you have a way to use different strings for the same internal task the string was helping to carry out. For e.g. I may want to dynamically construct a pepper for hashing... I would concatenate the current unix timestamp to the above(s1) and use the s1+timestamp as the string.

Of course, if the string to be protected is a constant then this additional timestamp based approach is not possible.

This was inspired by an incident in the story of Alibaba: One of the 40 thieves had found out Alibaba's house in the village. He used a chalk to write a 'x' on that house door. Fortunately, Alibaba's girlfriend saw it -- and realized the thief will return back with the other 39 and attack the house. So she marked an 'x' in all the houses of the village. That is what made me think, the same thing could be done -- just chop the string to be obfuscated and bury each part in the entire "village" master string.

Hope this is in line with what was asked and it helps. Feedback appreciated.

Related