/* * fakewav -- hide in / extract from fake wav files * Dec 22 2001 * by itouh */ #define PROGNAME "fakewav" #define PROGVERSION "1.0" #include #include /* exit() */ #include /* stat() */ #include /* vfprintf() */ #include /* strncpy(), strrchr() */ #define uchar unsigned char #define ulong unsigned long #define FILENAMELEN 200 #define PASSWDLEN 200 #define BUFLEN (1024*1024) //1MBytes typedef enum {TRUE, FALSE} bool; typedef enum {ENCRYPT, DECRYPT} crypt_type; void mkOutfile(const char *fname_org, const bool allowOverwrite); void arrangeEndian(void *v, const int size, FILE *fin); void errexit(char *fmt, ...); int cryptbyte(size_t size, FILE *fin, FILE *fout); void writewavhd(FILE *fout, int size); int checkwavhd(FILE *fin); char *removeDirFromFilename(char *fname); char passwd[PASSWDLEN+1]; //終端'\0'を格納するために +1する ulong filebytecounter; //ファイル先頭からのバイト数をかぞえる(単調増加) crypt_type actmode = ENCRYPT; /* * handling arguments */ int main(int argc, char *argv[]){ int i; static bool passdefined = FALSE; //passwdが定義されるとTRUE、されてないとF static bool allowOverwrite = TRUE; //outputfileを上書きできればTRUE /* * arguments */ if(argc<=1 || strncmp(argv[1],"-h",2)==0 || strncmp(argv[1],"-v",2)==0){ fprintf(stderr, PROGNAME " version " PROGVERSION "\n"); fprintf(stderr, "usage: " PROGNAME " [-de] [-i] [-p] inputfilename..\n"); fprintf(stderr, "option: -e,-c (default) encrypt inputfiles and output 'inputfilename.wav'\n"); fprintf(stderr, " -d,-x decrypt inputfiles and output files excluding '.wav'\n"); fprintf(stderr, " -i disallow to overwrite existing files\n"); fprintf(stderr, " -p\"pass phrase\" specify password/phrase\n"); exit(1); } for(i=1; i BUFLEN){ if((res=cryptbyte(BUFLEN, fin, fout))!=0) errexit("error %d in reading '%s' and writing '%s'", res, fname, newfname); inputfilesize -= BUFLEN; } if(inputfilesize != 0){ if((res=cryptbyte(inputfilesize, fin, fout))!=0) errexit("error %d in reading '%s' and writing '%s'", res, fname, newfname); } fclose(fout); fclose(fin); printf(" wrote '%s'\n", newfname); return; } /* * ファイルを指定バイトだけ読みこみ、暗号化/復号化して、書き込む * out: 1==error, 0==ok */ int cryptbyte(size_t size, FILE *fin, FILE *fout){ uchar buf[BUFLEN]; int i; static int passlen = 0; if(passlen==0){ passlen = strlen(passwd); if(passlen==0) passlen = 1; #ifdef DEBUG fprintf(stderr, "passlen = %d\n", passlen); #endif /* DEBUG */ } /* * バイト列を読みこみ */ if(fread(buf, 1, size, fin)!=size) return 1; /* * ファイルの暗号化 * 1バイトづつ passwdとファイルの中身を足してmoduloとったもの * ただし、passwdはビット反転させる */ for(i=0; i=0; i--){ if(fwrite(p+i, 1, 1, fout)!=1) errexit("error occurs in writing an wav file!"); } } return; } /* * エラー文を表示して、このプログラムを終了する */ void errexit(char *fmt, ...){ va_list ap; va_start(ap, fmt); fprintf(stderr, "%s: ", PROGNAME); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); va_end(ap); exit(EXIT_FAILURE); } /* WAVヘッダの構造 * 数値はリトルエンディアン、符号あり string filesize-8 string string wavfilesize-8=inputfsize+44 R I F F n n n n W A V E f m t ' ' ' 'は半角空白 fmtsize:16(見たまま) |fmt〜 pcm:1(無圧縮) fmt-size |pcm chanl sample/sec byte/sec chnl:2(stereo) 10 00 00 00|01 00 02 00 44 ac 00 00 10 b1 02 00 sample:44100 byte:176400 = sample * blok 〜fmt| |data〜 block:4byte block bit |string datasize |data =2byte(=16bit)*2(=stereo) 04 00 10 00|d a t a n n n n |n n.. bit:16(stereo16bit) datasize:wavfilesize-44 = inputfilesize(見たまま) 44100 == 0xac44 176400 == 0x2b110 */ /* * wav ファイルのヘッダ部分を書き出す */ void writewavhd(FILE *fout, int inputfilesize){ long n; short h; fprintf(fout, "RIFF"); n = inputfilesize + 44; arrangeEndian(&n, sizeof(n), fout); fprintf(fout, "WAVEfmt "); n = 16; //16bit arrangeEndian(&n, sizeof(n), fout); h = 1; //pcm-type: MS non-compression arrangeEndian(&h, sizeof(h), fout); h = 2; //channel: stereo arrangeEndian(&h, sizeof(h), fout); n = 44100; arrangeEndian(&n, sizeof(n), fout); n = 176400; //44100(sampling/sec) * 2byte(16bit) * 2(stereo) arrangeEndian(&n, sizeof(n), fout); h = 4; //2byte(16bit) * 2(stereo) arrangeEndian(&h, sizeof(h), fout); h = 16; arrangeEndian(&h, sizeof(h), fout); fprintf(fout, "data"); n = inputfilesize; arrangeEndian(&n, sizeof(n), fout); } /* * ファイル先頭を読み込み、wavファイルであるか照合する * out: 1..error, 0..OK */ int checkwavhd(FILE *fin){ const int checksize = 16; char wavbuf[checksize]; // wavファイルかどうかチェックする if(fread(wavbuf, 1, checksize, fin)!=checksize) return 1; if(strncmp(wavbuf, "RIFF", 4)!=0 || strncmp(wavbuf+8,"WAVEfmt ",8)!=0) return 1; return 0; } /* * 出力ファイル名がディレクトリを含んでいれば削除する * その結果、出力はカレントディレクトリになされる */ char *removeDirFromFilename(char *fname){ int i; char *p = fname; for(i=0; i