This patch was created to show the differences between the generic gzip 1.2.4 distribution and the gzip-steg-1.2.4 distribution downloadable here. This file includes: * Andrew Brown's original 1994 patches against gzip 1.2.4 * Ken Pizzini's one-line patch to fix a filedescriptor bug introduced by Andrew. To use this patch: (download gzip sources from www.gzip.org) tar -xvf gzip-1.2.4.tar patch -p0 < gzip-steg-1.2.4.patch (build as per usual for your platform) Patch maintained by: web [at] wiretapped.net --- gzip-1.2.4-orig/deflate.c Fri Aug 13 22:35:31 1993 +++ gzip-1.2.4/deflate.c Sun May 1 05:13:48 1994 @@ -71,6 +71,31 @@ static char rcsid[] = "$Id: deflate.c,v 0.15 1993/06/24 10:53:53 jloup Exp $"; #endif +/* gzsteg: our declarations */ + +extern int steg; /* steganography flag */ +extern int sfd; /* file descriptor */ +extern int stegidx; /* 0-7: next bitpos 8-39: length bit */ +extern ulg steglength; /* file length (bytes) */ +extern ulg stegbits; /* file length (bits) */ +extern uch stegbyte; /* next byte */ + +local int steg_rbit() +{ + ush retval; + + if(stegidx>=8) { /* 39..8 = length */ + stegidx--; + return ((steglength & (1L<<(stegidx-7L)))!=0); + } + if(stegidx==7) + read(sfd,&stegbyte,1); + retval = ((stegbyte & (1L<= MIN_MATCH && match_length <= prev_length) { +/* + * gzsteg: now we know that match_length is long enough for our needs we + * make room for our bit, then hide it. + */ + + if(steg && stegbits) { + if(prev_length>MIN_MATCH+1) { + prev_length--; + if(steg_rbit()) + prev_length|=1; + else + prev_length&=(~1); + stegbits--; + } + else if(prev_length==MIN_MATCH+1) + prev_length--; + } check_match(strstart-1, prev_match, prev_length); --- gzip-1.2.4-orig/inflate.c Sat Aug 14 00:50:20 1993 +++ gzip-1.2.4/inflate.c Sun May 1 05:14:06 1994 @@ -111,6 +111,35 @@ #include "gzip.h" #define slide window +/* gzsteg: our declarations */ + +extern int steg; /* steganography flag */ +extern int sfd; /* file descriptor */ +extern int stegidx; /* bits in 0..7 or 8..39 */ +extern ulg steglength; /* file length (bytes) */ +extern ulg stegbits; /* file length (bits) */ +extern uch stegbyte; /* next byte */ +local void steg_wbit OF((int b)); + +local void steg_wbit(b) /* write bit */ + int b; +{ + if(stegidx>=8 && stegidx<=39) { /* 39..8 = length */ + if(b) steglength|=(1L<<(stegidx-8L)); + if(stegidx==8) + stegbits=steglength*8; + stegidx--; + return; + } + if(b) stegbyte|=(1<v.n - ((unsigned)b & mask_bits[e]); DUMPBITS(e) Tracevv((stderr,"\\[%d,%d]", w-d, n)); + +/* + * gzsteg: bit 0 of n is ours, so long as n>3 (MIN_MATCH) + */ + + if(n>3 && steg) + steg_wbit(n&1); /* do the copy */ do { --- gzip-1.2.4-orig/gzip.c Thu Aug 19 23:39:43 1993 +++ gzip-1.2.4/gzip.c Sun May 1 05:13:53 1994 @@ -198,6 +198,17 @@ /* local variables */ +/* gzsteg: our variables */ + +local struct stat stegstat; +local char stegname[MAX_PATH_LEN]; +int steg=0; +int sfd; +int stegidx=39; +ulg steglength=0L; +ulg stegbits; +uch stegbyte=0; + int ascii = 0; /* convert end-of-lines to local OS conventions */ int to_stdout = 0; /* output to stdout (-c) */ int decompress = 0; /* decompress (-d) */ @@ -259,6 +270,7 @@ {"quiet", 0, 0, 'q'}, /* quiet mode */ {"silent", 0, 0, 'q'}, /* quiet mode */ {"recursive", 0, 0, 'r'}, /* recurse through directories */ + {"steg", 1, 0, 's'}, /* gzsteg: hide/reveal file */ {"suffix", 1, 0, 'S'}, /* use given suffix instead of .gz */ {"test", 0, 0, 't'}, /* test compressed file integrity */ {"no-time", 0, 0, 'T'}, /* don't save or restore the time stamp */ @@ -347,6 +359,7 @@ #ifndef NO_DIR " -r --recursive operate recursively on directories", #endif + " -s --steg hide/reveal file in compressed data", " -S .suf --suffix .suf use suffix .suf on compressed files", " -t --test test compressed file integrity", " -v --verbose verbose mode", @@ -478,7 +491,8 @@ strncpy(z_suffix, Z_SUFFIX, sizeof(z_suffix)-1); z_len = strlen(z_suffix); - while ((optc = getopt_long (argc, argv, "ab:cdfhH?lLmMnNqrS:tvVZ123456789", + while ((optc = getopt_long (argc, argv, + "ab:cdfhH?lLmMnNqrs:S:tvVZ123456789", longopts, (int *)0)) != EOF) { switch (optc) { case 'a': @@ -523,6 +537,10 @@ z_len = strlen(optarg); strcpy(z_suffix, optarg); break; + case 's': /* gzsteg: set steganography flag */ + steg = 1; + strcpy(stegname,optarg); + break; case 't': test = decompress = to_stdout = 1; break; @@ -558,6 +576,27 @@ file_count = argc - optind; +/* + * gzsteg: open input/output file depending on steg flag + */ + + if(steg) { + if(decompress) + sfd=OPEN(stegname,O_WRONLY|O_CREAT|O_BINARY,RW_USER); + else { + sfd=OPEN(stegname,O_RDONLY|O_BINARY,RW_USER); + fstat(sfd,&stegstat); + steglength=stegstat.st_size; + stegbits=(steglength*8)+32; + } + if(sfd == -1) { + fprintf(stderr, "%s: ", progname); + perror(stegname); + exit_code = ERROR; + return; + } + } + #if O_BINARY #else if (ascii && !quiet) { @@ -598,6 +637,17 @@ if (list && !quiet && file_count > 1) { do_list(-1, -1); /* print totals */ } + +/* gzsteg: close our file */ + + if(steg) { + if(!decompress && stegbits) + fprintf(stderr,"%s: %ld bytes too large to hide\n", + stegname, + stegbits/8); + close(sfd); + } + do_exit(exit_code); return exit_code; /* just to avoid lint warning */ }