1

I have a string literal that's used in a number of different places around my executable.

Let's say something like:

const char *formatString = "Something I don't want to make obvious: %d";

int format1(char *buf) { sprintf(buf, formatString, 1); }
int format2(char *buf) { sprintf(buf, formatString, 2); }

//...

Now, this string literal becomes very obvious inside the executable code, because it's embedded literally.

Is there any way to avoid this by forcing the compiler to, for example, generate assembly instructions (e.g. mov [ptr + 4], 0x65) instructions to create the strings, instead of embedding the strings literally?

I don't want to do an obfuscation of any sort -- I simply want to avoid making the string obvious inside the executable. (I also don't want to have to modify my code in every single place the string is used.)

Is this possible?

5
  • 3
    The way I do this is to build the string at run-time starting from an encrypted version. But that's the same as obfuscation... Commented Oct 2, 2011 at 4:39
  • 1
    Agreed with Mystical. This is exactly the definition of obfuscation. If your program is secure, you don't have to worry about people knowing the format strings. Commented Oct 2, 2011 at 6:12
  • @Downvoters: Uhm, care to comment? Commented Oct 2, 2011 at 7:17
  • When I read this kind of questions I cannot help but wonder: what do you really want to achieve? It seems that you are worrying about (malicious?) users smart enough to watch inside your executable but not willing to try very hard at it. I didn't downvote but would appreciate a bit of background before upvoting... Commented Oct 2, 2011 at 7:34
  • @Francesco: It's not a commercial program or anything, so it's just for learning on my part, on controlling the binary output of the compiler. Commented Oct 2, 2011 at 7:51

3 Answers 3

4

To avoid pasting encrypted strings into code by hand, you can create a macro which would mark strings that need obfuscation and a function which decrypts them:

#define OB(s) dec("START_MARK_GUID" s "\0" "END_MARK_GUID")
const char* dec(const char* s) { ... }
...
const char* s = OB("not easily readable"); // on all strings needed
const char* s = OB("either");

The function must do two things:

  1. If the parameter starts with START_MARK_GUID, simply return the original string (without the guids). This will allow you to use unobfuscated executable too, e.g. when debugging.

  2. If it starts with ENCRYPTED_MARK_GUID, deobfuscate first then return a new string. In C you will have to care about memory lifetime here; in C++ you could simply return std::string().

Finally, create an obfuscator program which looks for GUIDs in a compiled binary and encrypts data between them. It is only a few lines in Python or similar language. I also recommend to fix EXE's CRC back after, though my program worked even without that.

You can change guids with less unique identifiers to save some space. Also you can improve this to make decryption happen only one time (e.g. write string ID among with ENCRYPTED_MARK_GUID and keep decrypted strings in a dictionary by that ID).

Sign up to request clarification or add additional context in comments.

Comments

2

Obfuscation is probably your best bet. Use a simple obfuscation (such as XOR), and unobfuscate it into another variable at the beginning of your program before running any code that needs the string.

4 Comments

Hm... so what I understand is that it's not possible to force the compiler to create the strings locally through instructions or whatever? They have to be shared globally (and literally) somehow?
It is possible if you modify the compiler or do it via a macro, but I've not come across one that does it by default.
Modifying the compiler obviously doesn't work, but how would a macro work? I'd have to generate everything by hand and put it into the source code, right? (i.e. no way to automate it without external tools and stuff?)
Yes, but you'd only have to do it once (per obfuscation mechanism).
0

Pretty soon with C++11 you'll be able to use user-defined literals.

constexpr const char*
operator"" _decrypto(const char*, size_t len)
{
  //  decrypt input string.
}

const char* formatString = "encrypted gibberish"_decrypto;

int format1(char* buf) { sprintf(buf, formatString, 1); }
int format2(char* buf) { sprintf(buf, formatString, 2); }

int
main()
{
}

gcc is working on this furiously and I think IBM has this already. Not sure about the status of Visual Studio. This compiled on a patched gcc.

2 Comments

I think you goofed a bit on what the was being asked. The OP wanted it to not appear as cleartext in the object code. The constexpr operator decrpyts the string at compile time and stores it as a constant. So you essentially did exactly the opposite. The constexpr should encrypt it(where it will be stored obfuscated in the executable), and it should be decrypted at runtime before use.
@Tim Yes, you're right. I think I got started thinking about it from the obfuscation angle for some reason. I'll rethink this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.