How to Hide Strings in a Exe or a Dll

How to hide strings in a exe or a dll?

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.

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!

Hide or remove unwanted strings from windows executable release

Windows API functions are loaded from dlls, like kernel32.dll. In order to get the loaded API function's memory address, a table of exported function names from the dll is searched. Thus the presence of these names.

You could manually load any Windows API functions you reference with LoadLibrary. The you could look up the functions' addresses with GetProcAddress and functions names stored in some obfuscated form. Alternately, you could use each function's "ordinal" -- a numeric value that identifies each function in a dll). This way, you could create a set of function pointers that you will use to call API functions.

But, to really make it clean, you would probably have to turn off linking of default libraries and replace components of the C Runtime library that are implicitly used by the compiler. Doing this is a hasslse, though.

How to hide exe dll in C++?

If you use the static versions of the libraries, their code will be compiled directly into your EXE, and then you won't need DLLs at all.

But, if you need to use DLLs, then you can compile them into your EXE's resources, and then extract them at runtime to temp files before using them. You won't be able to statically link to any of the DLL functions at compile-time, or else your app won't run at all. But you can dynamically load them at runtime using LoadLibrary() and GetProcAddress() (or, if you compiler supports it, use delay-loading), which will allow you to extract the DLLs before calling their functions.

Hide string from basic viewing (e.g. Notepad)

Alphabet number/place in alphabet

You can convert each letter of the alphabet, to the number that respectively the place of that letter.

  • a = 1
  • b = 2
  • ...
  • z = 26

This program is a quick 'tool' do this type of encoding. Separate it from your actual project.

Save as: MyStringEncoder.cpp and compile

#include <iostream>
#include <string>

using namespace std;

string encodeMyString(string s) {
string encodedString;
string alphabet = "abcdefghijklmnopqrstuvwxyz";
for (int i = 0; i < s.length(); i++) {
char toEncode = s[i];
for (int j = 0; j < alphabet.length(); j++) {
if (toEncode == alphabet[j]) {
encodedString += to_string(j +1);
encodedString += "_";
}
}
}

encodedString.erase(encodedString.length() -1, encodedString.length());
return encodedString;
}

int main() {
cout << "Give in string to encode: ";

string stringToEncode;
cin >> stringToEncode;

cout << encodeMyString(stringToEncode);
cin.ignore().get();
}

When you enter a string, it will be reversed to numbers. So "hello" will become "8_5_12_12_15".

In your actual program; you have to have these two functions:

#include <iostream>
#include <string>
#include <sstream>
#include <vector>

using namespace std;

//Needed in your actual program
char toAlpha(int n) {
return "abcdefghijklmnopqrstuvwxyz"[n-1];
}
string decodeMyString(string encodedString) {
stringstream ss(encodedString);
string part;
vector<int> partList;

while (getline(ss, part, '_')) {
partList.push_back(stoi(part));
}

string decodedString;
for (int i = 0; i < partList.size(); i++) {
decodedString += toAlpha(partList[i]);
}

return decodedString;
}
//----------------------------------

int main() {

cout << decodeMyString("8_5_12_12_15");
}

By putting the encoded number-string into the function decodeMyString() it'll get reversed back to "hello", because the eight character of the alphabet is "h", the fifth is "e",...

This way someone opening your file would only see numbers, but not actually words.

Of course, you still have to build in support for spaces and other special characters. But it's just a quick example.

Caesar Cipher

This cipher is one of the most basic and first versions of encryption, yes, this is actually encryption because you need a key to encrypt and decrypt it. However, it's a very weak form of encryption.

Anyway, it works like this.
You have the alphabet, and you shift it a specific times.
So,

ABCDEFGHIJKLMNOPQRSTUVWXYZ

BCDEFGHIJKLMNOPQRSTUVWXYZA

Is shifted, one time.

So, 1 is your 'secret' key.

#include <iostream>
#include <string>
#include <sstream>
#include <vector>

using namespace std;

//Function to encrypt
string toCaesar(string s, int key) {
string alphabet = "abcdefghijklmnopqrstuvwxyz";

for (int i = 0; i < s.length(); i++) {
for (int j = 0; j < alphabet.length(); j++) {
if (s[i] == alphabet[j]) {
int index = j + key;
if (index >= 26) index = index - 26;
s[i] = alphabet[index];
break;
}
}
}

return s;
}

//Function to decrypt
string decryptCaesar(string s, int key) {
string alphabet = "abcdefghijklmnopqrstuvwxyz";

for (int i = 0; i < s.length(); i++) {
for (int j = 0; j < alphabet.length(); j++) {
if (s[i] == alphabet[j]) {
int index = j - key; //Only difference is the MINUS here
if (index >= 26) index = index - 26;
s[i] = alphabet[index];
break;
}
}
}

return s;
}

int main() {
int inputKey;
string stringToEncrypt;

cout << "Give your key: ";
cin >> inputKey;
cout << "String to encrypt: ";
cin >> stringToEncrypt;

cout << toCaesar(stringToEncrypt, inputKey) << endl;
cout << decryptCaesar("fgh", 5);
}

This is weak, not only because it can be easily brute-forced. But also because if you take the most for common letter in English ('e') and the most for common in your cipher, you already have one of the 26 letters.

Note

However, note that both of these methods are weak, and unsecure.
What you are trying to do is called security through obfuscation. And is dissadvised.

Another thing you're maybe interested in, is source code obfuscation.



Related Topics



Leave a reply



Submit