Click here to Skip to main content
Click here to Skip to main content

Literal string encryption as part of the build process

By , 17 Mar 2005


Have you ever wished there was a way to use strings for messages, passwords or other text inside your app that didn't require you to use a literal string, because you were worried about someone finding the strings in your EXE ? Wish no more, CXR is here.

What does it do?

CXR is a combination of a text parser, a stream cipher and C source code generator. You define your literal text strings in a ".CXR" file as part of your normal coding process, using standard C/C++ constructs. Then, when you build your project, the CXR program will encrypt those strings and generate a new .CPP file that is compiled into your project, automatically. The process is somewhat like what happens with .IDL files when you are working on an ATL project.


Here's an example:
You create a .CXR file that contains your string definitions and a unique password:
// my .CRX file
// here is my password definition:
// CXRP = "SexyBeast"		
// here are some strings:				

// my first string   
const char* pString1 = _CXR("AbcdEfg1234  blah\tblah"); 

// string #2
const char* pString2
       = _CXR("This is a long one, not that it should matter...");

As you can see, the only difference between this and standard C/C++ is the _CXR specifier. The comment line with the password is required, and any text you want encrypted must be inside a _CXR(...) specifier. Anything else in the file will be copied over to the output .CPP unchanged. So, that's how you set up the .CXR file. When you build your project, the CXR parser will read this file and generate a .CPP that looks like this:

#ifdef _USING_CXR
// my first string
const char* pString1 = "ab63103ff470cb642b7c319cb56e2dbd591b63a93cf88a";
const char* pString1 = _CXR("AbcdEfg1234  blah\tblah");  // my first string

#ifdef _USING_CXR

// string #2
const char* pString2 = 
// string #2
const char* pString2 = 
...more stuff below...

Presto. The CXR parser has encrypted your strings.

OK, how do i get my strings back?

The "...more stuff below..." is actually the decryptor code. That decryptor code is compiled into your project, with the CXR password you gave. So, all you have to do to is this:
CString csString1 = _CRX(pString1);
// pString1 = "ab63103ff470cb642b7c319cb56e2dbd591b63a93cf88a"
// and now csString1 = "AbcdEfg1234  blah\tblah";

Note the #ifdef _USING_CXR tags. Because of these, you can disable the CXR strings by simply changing a single #define - to make testing easier. If _USING_CXR is not defined, all your strings revert to their unencrypted form and the "_CXR" turns into a macro that does nothing. If _USING_CXR is defined, your strings take on their encrypted forms and the _CXR macro becomes a call to the decrypting code. It's (almost) totally seamless.

It can't be that easy

Well, it's almost that easy. There are some steps you need to follow to add your .CRX file to your project and to enable the CXR parser. But, these are all one-time things. Once you set them up the first time, you never have to do it again.

Setting up

  1. Build the CXR.EXE and put it somewhere in your path (in your WinNT or Windows folder, perhaps).

  2. Create your .CRX file. Create a file that has your password definition and your literal text strings. Follow these rules:
    • A .CXR file must contain a password line of the form:
      // CXRP = "MyPasswordString"
      Where the password string is any string you want. The "// CXRP =" part is required.

    • All text strings that are to be encrypted must be enclosed in a _CXR(...) tag.

    • _CXR(...) tags can not span multiple lines.

    • CXR currently does not support Unicode. All your strings will be treated by the encoder as if they were ANSI strings. Using this in a Unicode build will probably cause you large headaches. Unicode support is planned in the future, but it isn't supported right now.

  3. Create a .H file for your strings. Really, this is just a basic C/C++ issue. CXR will generate a .CPP file with your encoded strings. But, as with any extern strings, if you want to use them in your code, you have to define them somewhere. In the example above, I would create a file called "strings.h" and add the following:
    extern const char* pString1;
    extern const char* pString2;

  4. Add the .CXR file to your project. You have to do this manually (right click on your project in the File View, select the .CXR file, etc.).

  5. Add a new .CPP file to your project. The CXR parser will generate a .CPP file for you. But, you have to tell the compiler to compile it. So, add another file to your project. If your .CXR file was named "Strings.CXR", add "Strings.CPP" to your project - just type in the name when the file dialog pops up. Since this file doesn't exist yet, Visual Studio will ask if you want to add a reference to it anyway. Say Yes. The first time you build, the .CPP will be created.

  6. Set the custom build options. Find your .CXR file in the Project / Settings, menu. Check "Always use custom build step". On the Custom Build tab, in the "Commands" section, enter the following:
    cxr.exe -i $(InputPath) -o $(ProjDir)\$(InputName).cpp
    This will cause Visual Studio to call CXR.EXE with the name of your .CXR file as input and the same name, but with a .CPP extension as output.

    In the "Outputs" section, enter:

    This tells the compiler that this file needs to be recompiled when the .CXR file changes.

  7. Add cxr_inc.h to your project and add #include "cxr_inc.h" in every file in which you want to use the encrypted strings. There is a copy of this file in the sample "Test" project. But, it looks just like this:
    #ifndef CRXHeaderH
    #define CRXHeaderH
    #define _USING_CXR
    #ifndef _USING_CXR
    #define _CXR(x) x
    #define _CXR(x) __CXRDecrypt(x)
    extern CString __CXRDecrypt(const char *pIn);
    This file defines the macros you need to use to get your strings. This is also a good place to turn off the _USING_CXR macro, if you want to use your strings un-encrypted for any reason.

  8. That's it! I know it looks like a lot. But again, the previous steps only have to be done once. After the setup is complete, the only interaction you'll have with CXR is when you edit and access your strings.

In detail

CXR is fairly simple. The parser scans the .CXR input file, looking for two things: 1. the password line and 2: quoted strings inside _CXR(...) tags. Anything else it just copies to the output as-is. When it finds a _CXR tag, it encrypts the string with your password, converts the encrypted data to printable characters and outputs the encrypted version, along with the original version, in an #ifdef...#endif chunk. The parser is somewhat dumb; it doesn't understand much C/C++; it only knows to looks for the password and _CXR("..."), this is what prevents the use of multi-line text and Unicode. It does, however understand the syntax of C/C++ literal strings (including all escapes documented in K&R v2).

The encryption code is based on the quick and small Sapphire II stream cipher, from Crypto++. XOR would work equally as well, since we're only concerned about obfuscating the strings, not in keeping them secure against decryption attack.

You must be stupid. This won't stop crackers

No, I'm not stupid. I know that this by itself won't stop crackers. This is only a part of a complete defense. Of course if they find and watch the CXR decryption code, they can see the decrypted strings coming out; but they would have to know to look for it and find it, first. What CXR really does is it stops them from finding your "Registation complete!" and "Your trial period has expired!" messages with a simple string scan of the .EXE. Protection against crackers (as cracking itself) is a black art, not a science. As I see it, every twist and turn you can throw at the crackers stands a chance of being the one that causes them to give up and move on to the next target. Every barrier you can put in their way is a good one.


  • 9 Aug, 2002 - Changed character encoding from hex digits (1,2,3..f) to offset-based. This obscures the strings even better. Fixed the demo package.
  • 17 Mar 2005 - updated source code



About the Author

Chris Losinger
Software Developer
United States United States

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberMichael Haephrati מיכאל האפרתי4-Dec-12 2:18 
Newscxr branch on google codememberpaleozogt13-Jan-10 5:32 
Generaldirect encryptionmemberpatrick.steal20-Jul-07 6:45 
GeneralRe: direct encryption [modified]memberChris Losinger20-Jul-07 6:57 
Questionweird problemmemberpatrick.steal3-Jul-07 7:17 
AnswerRe: weird problemmemberChris Losinger3-Jul-07 7:36 
News! Two Problems [modified]memberSynetech23-May-06 5:16 
GeneralThings I had to change to compile CXRmemberHokei2-Mar-06 10:41 
GeneralRe: Things I had to change to compile CXRmemberHokei14-Mar-06 20:42 
GeneralRe: Things I had to change to compile CXRmemberichscheissdirinsgsichthey11-Sep-06 6:20 
GeneralThanks, and improvementsmemberBoniolopez18-Jan-06 7:16 
GeneralRe: Thanks, and improvementsmemberHokei2-Mar-06 9:24 
GeneralRe: Thanks, and improvementsmemberBoniolopez2-Mar-06 10:56 
GeneralCXR for LinuxmemberVoom6-May-05 20:25 
GeneralRe: CXR for LinuxmemberHokei14-Mar-06 20:45 
GeneralRe: CXR for Linuxmemberpaleozogt13-Jan-10 5:59 
GeneralcoolmemberProxy4NT12-Apr-05 2:09 
GeneralYou can do (very) basic xor encryption with the preprocessorsmemberAnonymous17-Mar-05 20:39 
GeneralRe: You can do (very) basic xor encryption with the preprocessorsmemberAnonymous17-Mar-05 20:58 
QuestionDoesn't work with \ at the end?membermjimenez17-Mar-05 13:01 
AnswerRe: Doesn't work with \ at the end?memberChris Losinger17-Mar-05 14:59 
GeneralSuggestion for obfuscated stringssitebuilderMichael Dunn5-Oct-02 18:30 
GeneralRe: Suggestion for obfuscated stringsmemberChris Losinger6-Oct-02 12:23 
GeneralRe: Suggestion for obfuscated stringssitebuilderMichael Dunn6-Oct-02 12:35 
GeneralRe: Suggestion for obfuscated stringsmemberChris Losinger6-Oct-02 16:59 


Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130619.1 | Last Updated 17 Mar 2005
Article Copyright 2002 by Chris Losinger
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid