/*Hide - A little tool to hide data in image files from noobsCopyright (C) 2007 Lars Stoltenow <penma@penma.de>This program is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the Free SoftwareFoundation; either version 2 of the License, or (at your option) any laterversion.This program is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR APARTICULAR PURPOSE. See the GNU General Public License for more details.You should have received a copy of the GNU General Public License along withthis program; if not, write to the Free Software Foundation, Inc., 51 FranklinSt, Fifth Floor, Boston, MA 02110, USA*/#include <stdio.h>#define M_UNDEFINED 0#define M_HIDE 1#define M_UNHIDE 2void usage(){ fprintf(stderr, "Usage:\n" "\thide [ <options> ] <srcfile> <destfile>\n" "\thide [ <options> ] <srcfile>\n" "\n" "<srcfile> specifies the file that's to be embedded in <destfile>, 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]; int srcsize, destsize; // Count the bytes...! fseek(srcfile, 0, SEEK_END); fseek(destfile, 0, SEEK_END); srcsize = ftell(srcfile); destsize = ftell(destfile); // Rewind both files then. fseek(srcfile, 0, SEEK_SET); fseek(destfile, 0, SEEK_SET); // 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 function 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; char *srcname = NULL, *destname = NULL; int skip_options = 1; // Skip the program name by default. int c; int mode = M_UNDEFINED; // Scan the arguments. for (c = skip_options; c < argc; c++) { if (!strcmp(argv[c], "--help") || !strcmp(argv[c], "-h") || !strcmp(argv[c], "-?")) { usage(); return 0; } // Unparsed option! Start whinign if it is one... if (argv[c][0] == '-') { // Cancel argument parsing (just tell the user about more unknown // options). fprintf(stderr, "hide: unrecognized option %s\n", argv[c]); mode = M_UNDEFINED; skip_options = argc; } } if ((argc - skip_options) == 2) { // Assume there are two filenames specifying the source and destination // file. mode = M_HIDE; // This is no mistake. There is no need to waste memory by copying // that string. srcname = argv[skip_options + 0]; destname = argv[skip_options + 1]; } if ((argc - skip_options) == 1) { // Assume there is one filename specifying the file to be decoded. mode = M_UNHIDE; // This is again no mistake! srcname = argv[skip_options + 0]; } // For some reasons it can be useful to not force any filenames to be // specified (just think of --help). So scan them, if any. if (srcname != NULL) { srcfile = fopen(srcname, "r"); if (srcfile == NULL) { perror("hide: Error opening source file"); return 1; } if (destname != NULL) { destfile = fopen(destname, "r"); if (destfile == NULL) { perror("hide: Error opening destination file"); fclose(srcfile); return 1; } } } switch (mode) { case M_UNDEFINED: // This mostly means argument errors. Yell it out to the poor user! fprintf(stderr, "hide: Not enough or wrong arguments\n"); fprintf(stderr, "Use the '--help' option to get a list of available options.\n"); return 1; break; case M_HIDE: // Output to the output file. (It's stdout for now.) return hide(srcfile, destfile, stdout); break; case M_UNHIDE: // Dump the hidden file to the output file. (It's stdout for now.) return unhide(srcfile, stdout); break; }}