/* * piggyback.c (c) 2005 by Torben H. Nielsen * * requires openssl-dev * compile with gcc -o piggyback -l crypto piggyback.c * (perhaps with -O3) * * return values: * 0: success * 1: could not open file * 2: md5 mismatch */ /***************************************************************** * ToDo: * V At detach, remove() outfile if data md5 mismatch is detected * V detach - read options field * - ReWrite commandline args handling * - Compression * - Encryption/Decryption */ #include #include #include #include #include #include "gzcompress.h" #define CHUNK_SIZE 512 void printusage( void ) { printf("piggyback by hoerup\n"); printf("Usage: piggyback [options] attach \n"); printf(" piggyback detach \n\n"); printf("Options:\n"); printf(" --compress: use gzcompression on payload data\n"); printf("\n"); exit(0); } int main(int argc, char *argv[]) { FILE *carrierfile, *payloadfile, *outfile; int carrieridx; unsigned char buf[CHUNK_SIZE]; unsigned char md5sum[16]; unsigned char md5string[33]; unsigned char options[8]; unsigned char tmpstr[40]; unsigned char header[80]; char *ptr; int num, bytes_extracted; int pointer, headerpointer; int i; MD5_CTX md5; if( !( (argc ==4 && strcmp(argv[1],"attach") ) || (argc == 5 && strcmp(argv[1],"detach")) ) ) { printusage(); } carrieridx = 2; //create output-file with 644 permissions umask(022); if ( strcmp(argv[1], "attach")==0 ) { //attach carrierfile = fopen(argv[carrieridx], "r"); payloadfile = fopen(argv[carrieridx+1], "r"); outfile = fopen(argv[carrieridx+2], "w"); if (carrierfile == 0) { printf("Could not open carrier file (%s) for reading\n", argv[carrieridx]); return 1; } if (payloadfile == 0) { printf("Could not open payload file (%s) for reading\n", argv[carrieridx+1]); return 1; } if (outfile == 0) { printf("Could not open output file (%s) for writing\n", argv[carrieridx+2]); return 1; } for (i=0;i<8;i++) options[i] = 0; pointer=0; while (!feof(carrierfile)) { num = fread(buf, 1, CHUNK_SIZE, carrierfile); fwrite(buf, 1, num, outfile); pointer += num; } MD5_Init(&md5); while (!feof(payloadfile)) { num = fread(buf, 1, CHUNK_SIZE, payloadfile); fwrite(buf, 1, num, outfile); MD5_Update(&md5, buf, num); } MD5_Final(md5sum, &md5); for (i=0; i<16; i++) fprintf(outfile, "%02x", md5sum[i]); sprintf(header, "%08x", pointer); for (i=0; i<8; i++) { sprintf(tmpstr, "%c", options[i]+48); //ascii(48)='0' strcat(header, tmpstr); } fprintf(outfile, header, 16); MD5_Init(&md5); MD5_Update(&md5, header, 16); MD5_Final(md5sum, &md5); for (i=0; i<16; i++) fprintf(outfile, "%02x", md5sum[i]); fclose(carrierfile); fclose(payloadfile); fclose(outfile); } else { //detach carrierfile = fopen(argv[carrieridx], "r"); outfile = fopen(argv[carrieridx+1], "w"); if (carrierfile == 0) { printf("Could not open carrier file (%s) for reading\n", argv[carrieridx]); return 1; } if (outfile == 0) { printf("Could not open output file (%s) for writing\n", argv[carrieridx+1]); return 1; } //header size is 80 bytes fseek(carrierfile, -80, SEEK_END); headerpointer = ftell(carrierfile); fread(header, 1, 80, carrierfile); ptr = header + 32; strncpy(tmpstr, ptr, 16); MD5_Init(&md5); MD5_Update(&md5, tmpstr, 16); MD5_Final(md5sum, &md5); md5string[0] = 0; for (i=0; i<16;i++) { sprintf(tmpstr, "%02x", md5sum[i]); strcat(md5string, tmpstr); } ptr += 16; strncpy(tmpstr, ptr, 32); tmpstr[32] = 0; if (strncmp(md5string, tmpstr, 32) != 0) { printf("Header MD5 checksum mismatch!\n"); return 2; } // Read data-pointer ptr = header + 32; strncpy(tmpstr, ptr, 8); tmpstr[8] = 0; //make tmpstr a 0-terminated string pointer = strtol(tmpstr, (char **)NULL, 16); // Read Options fields ptr += 8; strncpy(options, ptr, 8); for (i=0; i<8; i++) options[i] -= 48; bytes_extracted = 0; fseek(carrierfile, pointer, SEEK_SET); MD5_Init( &md5 ); num=CHUNK_SIZE; while ( num == CHUNK_SIZE) { num = headerpointer - pointer; num -= bytes_extracted; if ( num >= CHUNK_SIZE ) num = CHUNK_SIZE; fread(buf, 1 , num, carrierfile); fwrite(buf, 1, num, outfile); MD5_Update( &md5, buf, num); bytes_extracted += num; } fclose(carrierfile); fclose(outfile); MD5_Final(md5sum, &md5); md5string[0] = 0; for (i=0; i<16; i++) { sprintf(tmpstr, "%02x", md5sum[i]); strcat( md5string, tmpstr); } strncpy(tmpstr, header, 32); tmpstr[32] = 0; if (strncmp(md5string, tmpstr, 32) !=0) { printf("Payload MD5 checksum mismatch!\n"); remove( argv[carrieridx+1] ); return 2; } } return 0; }