text is visible in compiled script

Jan 27, 2016 at 8:41am
Hi

I only started looking at c++ yesterday..

I've written a simple script that downloads files from different URL's and writes them to the correct locations on my Linux PC.

I've compiled the script using :
[code]g++ test.cpp -o new -lcurl[code]

If I cat the file I can see the individual URL's in the output. They are bit obscure but you can still make out whats going on.

I also run a system command from the script, and again that is quiet easy to read if you cat the compiled script.

I want to give this to a couple of colleagues, but I'd like to make it hard for the casual user to see the actual URL's or system command.

Any way to stop that ? or to hide / obscure the plain text ?

Thanks :D
Jan 31, 2016 at 1:40pm
If you're viewing the finished binary as a plain text file, you might see the string constants stored in the file, as you see. The compiler has to store these values somewhere, so they end up unencrypted in the output binary.

What you're looking for is encryption. For the simplest of cases, you can use bitwise-xor encryption. In your code, you use the encrypted version and decrypt the strings before you use them. A decryption function:

1
2
3
4
5
6
7
void decrypt(char* buffer, const char* key, size_t bufsize)
{
    for(size_t i = 0; i < bufsize; ++i)
    {
        buffer[i]= ^= key[i];
    }
}


The good thing about bitwise-xor encryption, is that the decryption and encryptions functions are exactly the same. Now for an example:

1
2
3
4
5
6
7
8
int main()
{
    char encrypted[] = {106, 77, 102, 105, 104}; //"hello" encrypted using the key
    const char key[] = {2, 40, 10, 5, 7}; //Our key
    decrypt(encrypted, key, 5); //Decrypt our string
    std::cout << encrypted << std::endl; //Prints "hello"
    return 0;
}


You simply use the encrypted values in your binary, which will then be stored in the resulting executable. Then just before you use the values, you decrypt them. Note that this isn't a very good security measure (anyone with a disassembler can pause the code just after the decryption function, showing the decrypted string), but the strings surely won't show up in the resulting executable directly.
Last edited on Jan 31, 2016 at 1:40pm
Feb 5, 2016 at 1:41pm
Thanks for the reply.
I've added this in to test with and I get an error when I try to compile it :

1
2
test.cpp: In function ‘void decrypt(char*, const char*, size_t)’:
test.cpp:23:20: error: expected primary-expression before ‘^=’ token


Any ideas ? Thanks

Feb 5, 2016 at 3:18pm
There is a simple syntax error typo'd on that line. Take a look at the provided code and see if you can figure it out.
Last edited on Feb 5, 2016 at 3:18pm
Feb 5, 2016 at 4:22pm
Thanks sorted that !

changed
1
2
3
        buffer[i]= ^= key[i];
to
        buffer[i] ^= key[i];


When I run this I get:
hello{�


Why do I get the extra characters ?
Thanks
Feb 5, 2016 at 5:37pm
Do you know the difference between these two:
1
2
char foo[] = {'w', 'o', 'r', 'l', 'd' };
char bar[] = "world";
Feb 5, 2016 at 6:18pm
Possibly :)

foo[] is an array and bar[] a string ?
Feb 5, 2016 at 7:28pm
What does that mean for the two of them?
Feb 5, 2016 at 7:41pm
One is a string of characters, the other is an array of individual letters.
Feb 5, 2016 at 8:26pm
What are the sizes of foo[] and of bar[] ?
Feb 6, 2016 at 6:03pm
the same, i think
Feb 6, 2016 at 6:13pm
Think again.
Last edited on Feb 6, 2016 at 6:13pm
Feb 6, 2016 at 7:02pm
hmmmmmmm................
Feb 6, 2016 at 7:02pm
They both act the same basically, I guess the array needs an explicit null termination sequence.
Feb 7, 2016 at 8:51am
I've compiled the script using :
g++ test.cpp -o new -lcurl


@TomT

Just some advice not related to your problem, always compile with the warning level set high:

g++ -std=c++14 -Wall -Wextra -pedantic-errors test.cpp -o new -lcurl

Warnings are a good thing, they tell you where you may have problems with your code.

Good Luck !!
Feb 7, 2016 at 10:46am
Another hint:
the output (that produces mysterious characters) is calling one of these functions: http://www.cplusplus.com/reference/ostream/ostream/operator-free/
Feb 8, 2016 at 9:45am
Feb 8, 2016 at 11:14am
Good. Do you understand the (minute) difference of the solutions?

Recap:
1
2
3
char foo[] = {'w', 'o', 'r', 'l', 'd' };
char bar[] = "world";
std:.string gaz = "world";

The foo is an array of characters.
The bar is an array of characters.
The gaz is a std::string object.

The foo is initialized with an array of characters. The initilizer array has 5 characters and thus the foo has 5 elements.
The bar is initialized with an array of characters. The initilizer array has 6 characters and thus the foo has 6 elements.
The gaz is initialized with an array of characters. The initilizer array has 6 characters but string stores only the first 5 non-null elements.

1
2
3
std::cout << gaz;
std::cout << bar;
std::cout << foo;

The string gaz has its own output operator that correctly outputs the 5 characters of "world".
The bar outputs exactly "world", because there is a null character after the 'd'.
We have no idea what prints after the 'd' of foo, because those memory locations can have anything.

In other words, the "world" is a shorthand for writing {'w', 'o', 'r', 'l', 'd', 0 }

The array used in Shadowwolf's program did not include a terminating null. Hence, it does print random characters after the hello.


The use of std::string cunningly avoids many issues that one encounters with plain array.
Last edited on Feb 8, 2016 at 11:15am
Feb 8, 2016 at 12:40pm
Thanks for this explanation.
That make sense.. sort of :)
Mar 7, 2016 at 5:38pm
Thanks for the advise on this query.

I've used: http://create.stephan-brumme.com/hide-strings-executable/ which works well, but the resulting code ends up hard to read as I'm referenceing encoded values in an array and then writing them using decode(arr[1])

eg:

std::cout << decode(arr[1]);
not :
std::cout << gaz;

This gets hard work when the code is encoded URLs, paths and files etc.

is there a neater, easier to read why to do this with out making the strings fully visible ?

I'm not looking for total security, just the ability to make the code harder to decompile or read the strings from.

Thanks :)

Topic archived. No new replies allowed.