How to Hide a String in Binary Code

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!

hiding char strings in c

You can do some math with it for example:

static unsigned char secret[] = {'m' + 10, 'y' + 10, 's' + 10, 'e' + 10, 'c' + 10, 'r' + 10, 'e' + 10, 't' + 10, 's' + 10, 't' + 10, 'r' + 10, 'i' + 10, 'n' + 10, 'g' + 10};

as your secret string may be in the RO segment:

char *decode(const unsigned char *str, int c)
{
int len = 0;
char *ml, *cl;
while(*str != abs(c))
len++;
ml = malloc(len + 1);
if(ml != NULL)
{
cl = ml;
while(*str != abs(c))
*cl++ = *str++ + c;
*cl = 0;
}
return ml;
}

of course it is easier to write the script which will code your string literals for you. The coding mechanism may be much more complicated - in the example I just is something trivial

Example coding function in C

#define VNAMEMAX 20
#define VVALUEMAX 200

typedef struct
{
char vname[VNAMEMAX];
char vvalue[VVALUEMAX];
}VDEF_T;


VDEF_T varialbles[] =
{
{.vname = "mystring",.vvalue = "Something very secret"},
{.vname = "secret_var",.vvalue = "Something even more secret" },
{0,},
};

int code(VDEF_T *v, char *fname, int c)
{
FILE *fp = fopen(fname, "wt");
int result = (fp == NULL) * -1;

if (!result)
{
fprintf(fp, "#ifndef _MYSECRET\n#define _MYSECRET\n\n\n");
while (!result && v->vname[0])
{
fprintf(fp, "static unsigned char %s[] = {\n\t\t", v->vname);
for (int i = 0; i <= strlen(v->vvalue); i++)
{
if (fprintf(fp, "0x%02x,", v->vvalue[i] + c) < 0)
{
result = -1;
break;
}
}
if (fprintf(fp, "};\n\n") < 0) result = -1;
v++;
}
if(fprintf(fp, "#endif") < 0) result = -1;
fclose(fp);
}
return result;
}

And the result .h file;

#ifndef _MYSECRET
#define _MYSECRET


static unsigned char mystring[] = {
0x5d,0x79,0x77,0x6f,0x7e,0x72,0x73,0x78,0x71,0x2a,0x80,0x6f,0x7c,0x83,0x2a,0x7d,0x6f,0x6d,0x7c,0x6f,0x7e,0x0a,};

static unsigned char secret_var[] = {
0x5d,0x79,0x77,0x6f,0x7e,0x72,0x73,0x78,0x71,0x2a,0x6f,0x80,0x6f,0x78,0x2a,0x77,0x79,0x7c,0x6f,0x2a,0x7d,0x6f,0x6d,0x7c,0x6f,0x7e,0x0a,};

#endif

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.

Hiding binary values in a number list

Credit to Julien Bernu for the idea; I was hoping he'd flesh out the idea and post as an answer, but it's been awhile so I decided to implement it so others could benefit from the idea.

I'm not positive this is a superior strategy to my original algorithm, but it does in fact address my specific concern so it's worth thinking about.

Pros:

  • Modifies each color value by a maximum of +/- 1 (instead of +/- 2)
  • Retains the ability to distinguish NULL from 00000000

Cons:

  • Breaks algorithm symmerty (must now track which image is the original, or mark it in the modified image)
  • Cannot make use of parts of the image with max or min color value (0 or 255), depending on what bit lines up with that color value

Following is the reworked, simplified example. Note that I had to add another pixel to the image data in order to store the information, because of some 0 and 255 values.

def encode(pic_data, file_data):
"""encode pic_data with the information stored in file_data"""
# file data is shorter than pic_data, I test for it in the real code
# would also need to make sure that the length of pic_data is greater than
# the length of file_data by the number of 0s and 255s in it, to be safe
new_pic_data = pic_data.copy()
offset = 0
for i in range(len(file_data)):
# Now, 1 is 1 and 0 is -1, which still allows us to
# distinguish 0 from nothing
data_value = 1 if file_data[i] == '1' else -1
# rgb max value is between 0 and 255
while pic_data[i + offset] == 0 and data_value == -1:
offset += 1
while pic_data[i + offset] == 255 and data_value == 1:
offset += 1
new_pic_data[i + offset] += data_value

return new_pic_data


def decode(pic_data_original, pic_data_modified):
"""
extract a binary string from the differences between the input
data sets
"""
# both data sets have to be the same length
new_file_data = ['1' if (pic_data_modified[i] - pic_data_original[i] == 1)
else '0' if (pic_data_modified[i] - pic_data_original[i] == -1)
else ''
for i in range(len(pic_data_original))]
return ''.join(i for i in new_file_data)


binary_string = '01100001' # the data to be hidden
flat_rgb_data = [18, 15, 255, 0, 151, 0, 254, 199, 21, 180, 105, 205] # the picture

# [17, 16, 255, 1, 150, 0, 253, 198, 20, 181, 105, 205]
encoded_rgb_data = encode(flat_rgb_data, binary_string)

# getting binary_string back, '01100001'
decoded_data = decode(flat_rgb_data, encoded_rgb_data)

print(decoded_data)

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