/* Hide - A little tool to hide data in image files from noobs Copyright (C) 2007 Lars Stoltenow This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA */ #include void usage() { // FIXME: Replace with some getopts calls, same with argument parser. fprintf(stderr, "Usage:\n" "\thide [ ] \n" "\thide [ ] \n" "\n" " specifies the file that's to be embedded in , or\n" "the file where embedded data should be extracted from.\n" "\n" "Available options:\n" "\t--help or -h or -? Show this help message.\n" ); } int hide(FILE *srcfile, FILE *destfile, FILE *outfile) { unsigned char srcbyte, destbytes[4]; // Read bytes from destination file until the end is reached. do { // Check if the source file has still bytes to offer, if not, include // null bytes (I think they always fit). :) if (feof(srcfile)) { srcbyte = 0x00; } else { fread(&srcbyte, 1, 1, srcfile); } // Read 4 bytes from the destination file to include the data there. fread(destbytes, 1, 4, destfile); // Empty the lower 2 bits. destbytes[0] &= 0xfc; destbytes[1] &= 0xfc; destbytes[2] &= 0xfc; destbytes[3] &= 0xfc; // Include the bits from the source file. destbytes[0] += (srcbyte >> 0) & 0x03; destbytes[1] += (srcbyte >> 2) & 0x03; destbytes[2] += (srcbyte >> 4) & 0x03; destbytes[3] += (srcbyte >> 6) & 0x03; // Write out the new data. fprintf(outfile, "%c%c%c%c", destbytes[0], destbytes[1], destbytes[2], destbytes[3]); } while (!feof(destfile)); // Make sure the files are closed! The calling unction won't do this. fclose(srcfile); fclose(destfile); return 0; } int unhide(FILE *srcfile, FILE *outfile) { unsigned char srcbytes[4]; // Go through the file and push bits to the output. do { // Get new bytes! fread(srcbytes, 1, 4, srcfile); // And write them to the output! fprintf(outfile, "%c", (srcbytes[0] & 0x03) | ((srcbytes[1] & 0x03) << 2) | ((srcbytes[2] & 0x03) << 4) | ((srcbytes[3] & 0x03) << 6)); } while (!feof(srcfile)); // Make sure the file gets closed! The calling routine won't do this for us. fclose(srcfile); return 0; } int main(int argc, char *argv[]) { FILE *srcfile, *destfile; if ((argc == 2) && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h") || !strcmp(argv[1], "-?"))) { usage(); return 0; } if (argc == 3) { // Assume there are two filenames specifying the source and destination // file. srcfile = fopen(argv[1], "r"); if (srcfile == NULL) { perror("hide: Error opening source file"); return 1; } destfile = fopen(argv[2], "r"); if (destfile == NULL) { perror("hide: Error opening destination file"); fclose(srcfile); return 1; } // Output to the output file. (It's stdout for now.) return hide(srcfile, destfile, stdout); } if (argc == 2) { // Assume there is one filename specifying tzhe file to be decoded. srcfile = fopen(argv[1], "r"); if (srcfile == NULL) { perror("hide: Error opening source file"); return 1; } // Dump the hidden file to the output file. (It's stdout for now.) return unhide(srcfile, stdout); } // Reaching here mostly means argument errors. Yell it out to the poor user! fprintf(stderr, "hide: Not enough arguments\n"); fprintf(stderr, "Use the '--help' option to get a list of available options.\n"); return 1; }