35

I discovered that it is possible to extract the hard-coded strings from a binary.
For example the properties view of Process Explorer displays all the string with more than 3 characters.

Here is the code of a simple executable that I wrote to simply test it:

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>

int _tmain(int argc, _TCHAR* argv[])
{
    _TCHAR* hiddenString1 =_T("4537774B-CC80-4eda-B3E4-7A9EE77991F5");
    _TCHAR* hiddenString2 =_T("hidden_password_or_whatever");
    for (int i= 0; i<argc; i++) {
        if (0 == _tcscmp(argv[i],hiddenString1)) {
            _tprintf (_T("The guid argument is correct.\n")); }
        else if (0 == _tcscmp(argv[i],hiddenString2)) {
            _tprintf (_T("Do something here.\n")); }
    }

    _tprintf (_T("This is a visible string.\n"));
    //Keep Running
    Sleep(60000);
    return 0;
}

The strings can clearly be extracted from the corresponding executable:
alt text

I think that it is a little too easy to find the strings.

My questions are:

  1. How to simply hide hiddenString1 or hiddenString2 in the executable?
  2. Is there a more secure way to use "cheat code" than with some obscure hidden input?
Spooky
  • 2,966
  • 8
  • 27
  • 41
Winz
  • 496
  • 1
  • 6
  • 7
  • 1
    Is this question about the GUID or about strings in general? – xtofl May 29 '09 at 17:20
  • The GUID was just an example: there are URLs for http requests that I would like to hide too. – Winz May 29 '09 at 17:27
  • 2
    Hiding URLs for http requests isn't going to work. Anyone with a sniffer will be able to see exactly what your app is doing, and doing so would be much easier than examining the memory of your process. – JoeG Jan 19 '10 at 15:48
  • [How to hide a string in binary code?](http://stackoverflow.com/q/1356896/995714) – phuclv Feb 02 '16 at 16:30
  • You can refer to [this](http://crypto.stackexchange.com/a/9612/2747) - it explains what is functional encryption and fully homomorphic encryption. – StefanS May 11 '16 at 11:49

9 Answers9

34

Welcome to the wider world of defensive programming.

There are a couple of options, but I believe all of them depend on some form of obfuscation; which, although not perfect, is at least something.

  1. Instead of a straight string value you can store the text in some other binary form (hex?).

  2. You can encrypt the strings that are stored in your app, then decrypt them at run time.

  3. You can split them across various points in your code, and reconstitute later.

Or some combination thereof.

Bear in mind, that some attacks go further than looking at the actual binary. Sometimes they will investigate the memory address space of the program while it's running. MS came up with something called a SecureString in .Net 2.0. The purpose being to keep the strings encrypted while the app is running.

A fourth idea is to not store the string in the app itself, but rather rely on a validation code to be submitted to a server you control. On the server you can verify if it's a legit "cheat code" or not.

NotMe
  • 87,343
  • 27
  • 171
  • 245
  • 2
    Nice options. Since the questioner is specifically concerned about hiding a Windows GUID string -- which is just a hexadecimal number -- that data could also be stored as a few ints. – Drew Dormann May 29 '09 at 14:51
  • I would like to add to your nice answer the possibility to salt the password. – AndersK Mar 31 '15 at 15:01
  • 1
    @CyberSpock: I'm not sure the purpose of salting it would be. The string (salted or not) is stored in the binary and therefore is subject to discovery. Which means there are only two solutions: obfuscate to at least make it a little harder or don't store it in the app at all. – NotMe Mar 31 '15 at 21:16
  • it may be more difficult to spot a password if it is salted since it would be an algorithm to compare passwords with one another but anyway it is all for naught. – AndersK Apr 01 '15 at 16:17
  • i just tried converting my arrayed string (char str[] = {'H', 'i', '\0'}) to a sequence of hex bytes and they are discover-able in very same way – duckduckgo Feb 18 '16 at 01:03
  • @duckduckgo They would be because that's how it is stored in memory (in both scenarios). One simple way around it is to pick a different datatype like an short or int but still you can see the hex codes. What you could do then devise your own obfuscation technique applies to the hex values like bit shifting, adding junk, etc. – ActiveX Nov 09 '22 at 02:02
20

There are many ways to obscure data in an executable. Others here have posted good solutions -- some stronger than others. I won't add to that list.

Just be aware: it's all a cat-and-mouse game: it is impossible to guarantee that nobody will find out your "secret".

No matter how much encryption or other tricks you use; no matter how much effort or money you put into it. No matter how many "NASA/MIT/CIA/NSA" types are involved in hiding it.

It all comes down to simple physics:
If it were impossible for any user to pull out your secret from the executable and "unhide" it, then the computer would not be able to unhide it either, and your program wouldn't be able to use it. Any moderately skilled developer with enough incentive will find the way to unhide the secret.

The moment that you have handed your executable to a user, they have everything they need to find out the secret.

The best you can hope for is to make it so hard to uncover the secret that any benefits you can get from knowing the secret become not worth the hassle.

So, it's OK to try to obscure the data if it's merely "not-nice" for it to be public, or if the consequences of it becoming public would just be "inconvenient". But don't even think of hiding in your program "the password to your master client database", a private key, or some other critical secret. You just can't.

If you have truly critically secret information that your program will somehow need but should NEVER become public information (like a private key), then you will need to have your program talk to a remote server under your control, apply appropriate authentication and authorization controls (that is, make sure only the approved people or computers are able to make the request to the server), and have that server keep the secret and use it.

Euro Micelli
  • 33,285
  • 8
  • 51
  • 70
  • 1
    Well said. And true crackers are quite formidable, you won't be able to stop them with a small trick. They will notice the hotspot where you play with strings and patiently for the application to decrypt it to see the real thing. – toto May 31 '09 at 03:08
10

The simplest way is to encrypt them with something trivial like xor or rot-13, and then decrypt them on the fly when they're used. That will eliminate casual viewing of them, but it won't stop anyone with much experience at reversing.

Rob K
  • 8,757
  • 2
  • 32
  • 36
6

In addition to those methods Chris mentions you could also use a hashing algorithm. If all you want to do is check if the correct ID was specified you don't actually need to store the whole ID in your program.

  • Create a hash (MD5, SHA, etc) of the string/password/id you want to compare against, maybe add a 'salt' value to it. Store this in your program
  • When the program is run, do the same algorithm on the input string/password/id and compare the two hashes to see if they match.

This way the actual text is never stored in your program and they cannot reverse engineer your program to find out what the original text was because hash algorithms are one-way only.

Andre Miller
  • 15,255
  • 6
  • 55
  • 53
  • be careful, collisions for some hashes (e.g. md5) can be found relatively easy these days.. – Josef Pfleger May 29 '09 at 14:24
  • I'm not sure that's a problem for this use. – Head Geek May 29 '09 at 14:29
  • 1
    You can go further, and just do the public key-only side of a publc key encryption deal. that'll handle the collision issue. It's also one of the more secure ways to do it - as secure as the encryption algorithm you use, even after it's dug out via hex editor. – Ben Barden Apr 02 '13 at 18:05
5

There are URLs for http requests that I would like to hide too.

If your app is making the request, there is no point hiding this. Running an app like fiddler, http analyzer, or one of dozens of other free and readily available methods will show all the traffic your app is creating.

CaffGeek
  • 21,856
  • 17
  • 100
  • 184
3

Here is the method I use for this purpose. First, I use the the Strings tool by Sysinternals to display the strings in an EXE or DLL. I then use the following small tool (see article) to replace these strings with a scrambled array of characters stored as an arithmetic expression: for example: instead of the string: "this is a test" I will place the following code: (which is automatically generated by this tool)

WCHAR T1[28];
 T1[22] = 69;
 T1[15] = 121 - 17;
 T1[9] = L':' + -26;
 T1[12] = L't' - 1;
 T1[6] = 116 - 1;
 T1[17] = 117 - 12;
 T1[3] = 116 - 1;
 T1[14] = L'' - 3;
 T1[13] = L'w' - 3;
 T1[23] = 69;
 T1[26] = L'Y' + 3;
 T1[19] = 111 + 0;
 T1[21] = L'k' - 34;
 T1[27] = L'\\' - 8;
 T1[20] = L'B' + 32;
 T1[4] = 42 + -10;
 T1[25] = L'm' - 17;
 T1[16] = L'H' + 18;
 T1[18] = L'A' + 56;
 T1[24] = 68;
 T1[1] = 105 - 1;
 T1[11] = L'k' - 6;
 T1[10] = 66 + 50;
 T1[2] = 105;
 T1[0] = 117 - 1;
 T1[5] = L'k' - 2;
 T1[8] = 89 + 8;
 T1[7] = 32;

There are many solutions to this problem and none of them (including mine) is perfect, however there are ways to scramble, disguise, and hide the sensitive strings. You can of course encrypt them and decrypt during runtime (see this article), but I find more important to make these string disappear among the bits and bytes of the executable file and it works. After running my tool, you won't find "this is a test" in the executable file.

Michael Haephrati
  • 3,660
  • 1
  • 33
  • 56
3

The best you can do is to code your password or other string that you want to hide as char array. For example:

std::string s1 = "Hello";   // This will show up in exe in hex editor
char* s2 = "World";   // this will show up in exe in hex editor
char s3[] = {'G', 'O', 'D'}; // this will not show up in exe in hex editor.
Frank Bollack
  • 24,478
  • 5
  • 49
  • 58
  • 1
    In this simple programm in C `char s3[] = {'G', 'O', 'D'}; int n = sizeof(s3)/sizeof(s3[0]); printf("%d\n", n);`, I find the text with the hex editor -> `.D$.G.D$.O.D$.D.D$.` in the build executable. – Tuksn Jun 14 '14 at 09:27
  • I saw that if data is in heap the string into the executable is in plain, if is in stack the string disappears. I am aware that this is very compiler/platform dependant (I am on win 10) – Zac Jun 08 '21 at 10:53
2

If there's a specific string you don't want people to be able to see, then encrypt it and decrypt at runtime.

If you don't want people to see your GUID, then construct it from bytes, rather than constructed from a string:

const GUID SecretGuid = 
      { 0x4537774B, 0xCC80, 0x4eda, { 0x7A, 0x9E, 0xE7, 0x79, 0x91, 0xF5 } };
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
2

Will all your secret codes be GUIDs or was that just an example?

Perhaps store your secret as a binary guid:

const GUID SecretGuid =
    { 0x4537774B, 0xCC80, 0x4eda, { 0x7A, 0x9E, 0xE7, 0x79, 0x91, 0xF5 } };

Then convert your supplied guid from string to binary format and compare the two binary guids.

Kevin Newman
  • 2,437
  • 1
  • 15
  • 12
  • The GUID was just an example. There are URLs for http requests that I would like to hide too. – Winz May 29 '09 at 15:41
  • 8
    Everyone who has the knowledge to look for strings in your excutable will be able to start a sniffer and watch for HTTP-Request from your app. In fact I would try the sniffer first before looking for strings. – Martin Thurau May 29 '09 at 17:48