c++embedxxd

In C++, how do you read a file that is embedded in an executable?


I had a photo named photo.jpg. I used xxd -i to generate a C++ file for my image file. And the output is something like this:

unsigned char photo_jpg[] = {

    0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,

    0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x84,...};

unsigned int photo_jpg_len = 24821;

I embedded that file into my main.cpp file and built it to generate my executable.

How could I possibly read that part of the hex dump which is my image file from the executable?

What have I tried...?

I used xxd myfile.exe > file.txt.

When I examine the hex dump of my executable generated with xxd, I see that the bytes of my photo_jpg character array are somewhere in the executable. You can see that in the image below: It is a screenshot of my executable hex dump.

How could I read that and store it inside of a character array like it was before being embedded into my executable?


Solution

  • At first, I converted my zip file to a string which was with this command:

    xxd -p archive.zip > myfile.txt

    Then I used this code to generate a multiline string in C++ of the hex dump of my zip file:

    #include <fstream>
    #include <string>
    int main()
    {
        std::ifstream input("file.txt");
        std::ofstream output("string.txt");
        std::string double_coute = "\"";
        std::string line;
        while (getline(input, line))
        {
            std::string to_be_used = double_coute + line + double_coute + "\n" ;
            output << to_be_used;
        }
        output.close();
        input.close();
        return 0;
    }
    

    After that, I put the contents of string.txt inside a global variable. Using the below function I was able to write a program that generates a zip file.

    void WriteHexDatatoFile(std::string &hex)
    {
        std::basic_string<uint8_t> bytes;
    
        // Iterate over every pair of hex values in the input string (e.g. "18", "0f", ...)
        for (size_t i = 0; i < hex.length(); i += 2)
        {
            uint16_t byte;
    
            // Get current pair and store in nextbyte
            std::string nextbyte = hex.substr(i, 2);
    
            // Put the pair into an istringstream and stream it through std::hex for
            // conversion into an integer value.
            // This will calculate the byte value of your string-represented hex value.
            std::istringstream(nextbyte) >> std::hex >> byte;
    
            // As the stream above does not work with uint8 directly,
            // we have to cast it now.
            // As every pair can have a maximum value of "ff",
            // which is "11111111" (8 bits), we will not lose any information during this cast.
            // This line adds the current byte value to our final byte "array".
            bytes.push_back(static_cast<uint8_t>(byte));
        }
    
        // we are now generating a string obj from our bytes-"array"
        // this string object contains the non-human-readable binary byte values
        // therefore, simply reading it would yield a String like ".0n..:j..}p...?*8...3..x"
        // however, this is very useful to output it directly into a binary file like shown below
        std::string result(begin(bytes), end(bytes));
        std::ofstream output_file("khafan.zip", std::ios::binary | std::ios::out);
        if (output_file.is_open())
        {
            output_file << result;
            output_file.close();
        }
        else
        {
            std::cout << "Error could not create file." << std::endl;
        }
    }
    

    But what is the point?

    The point is you could have any kind of resource inside your zip file. In this way, you could generate needed resources with your program and do some stuff with them. I think that's pretty cool.