0

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?

  • 2
    *You're now ready to work with the files in your resource library! See the section on `cmrc::embedded_filesystem`.* - Did you see [that section](https://github.com/vector-of-bool/cmrc#the-cmrcembedded_filesystem-api)? – Evg Nov 12 '22 at 14:38
  • Do not tag C for C++ questions. – Eric Postpischil Nov 12 '22 at 14:41
  • @Evg Yes, I've seen that part before. But I didn't know how to proceed. I tried adding my executable to my resource library in another project but I couldn't open my zip file from it. In all the examples that I've seen in the github repository of the cmrc module, the resource files were present somewhere in the project. I want to retrieve my zip file only from my executable and not use any helper files. – Michael_313 Nov 12 '22 at 14:46
  • I embed arbitrary binary data into my executable by using `xxd -i foo.zip xxd_foo.cpp`, and access the data through the `foo_zip` global array and the length from the `foo_zip_len` global variable. – Eljay Nov 12 '22 at 14:46
  • Are you trying to use a file embedded in an executable from a different executable? – rici Nov 12 '22 at 17:39
  • @rici Yes, I want to write a program which extracts a zip file, and that zip file is embedded to an executable. – Michael_313 Nov 13 '22 at 06:14
  • @Eljay I used your suggestion and updated my question. Thanks. – Michael_313 Nov 13 '22 at 08:01

1 Answers1

0

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.