图片是一个有趣的东西,一次偶然的机会发现可以用图片来达到文件的隐藏。
往图片文件的末尾添加数据,并不会影响图片的正常显示。于是做了一下的程序,将一个文件追加到图片中,然后在取出来;
大体思路是:
写入过程:
1、 选取一个载体图片文件A。
2、 获取A文件的原始大小sizeA。
3、 将这个大小记录到A文件的某个特定的位置PositionA,方便回头取数据用;
4、 将目标文件B已二进制形式写入到BufferB中。
5、 将此BufferB追加到A载体文件的末尾;
6、 关闭A载体文件,此时A文件末尾已添加上了目标文件;
取回过程:
1、 打开已追加内容的A文件。写入到Buffer中;
2、 从特定的位置取回A文件的原始大小sizeA;
3、 获取A文件当前大小sizeAA, 从Buffer中的SizeAA-sizeA位置开始到文件末尾的buffer1,
4、 将这个buffer1写到一个新的空文件中,这个文件就是原来的目标文件;
程序如下:// readData.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h" //#include<stdio.h> #include <fstream> #include <string.h> #include <stdio.h> #include <fcntl.h> #include <io.h> using namespace std; //打开一个文件将内容已二进制形式写入buffer char * openFileToBuffer(char * filepath); //得到文件的大小 int getFileSize(char *filepath); //将指定的buffer写入到指定位置的buffer中 //主要是将载体文件原始大小写入到文件的某一个指定的位置 void writeInfoToSpecialPos(char *filePath,char *destinationBuff,char *buffer,int buffersize,int FileBufferSize,int position); //将资源文件以追加的形式写入到载体文件的末尾 void appendFuntion(char * filePath,char *buffer,int buffersize); int _tmain(int argc, _TCHAR* argv[]) { //载体文件要偷渡的资源文件将会写入到此文件的末尾,文件写入的图片文件的末尾,但是不会影响文件的阅读显示! char *pathDest ="c:/destination.jpg"; //资源文件 char *pathSrc = "c:/source.rar"; //资源文件buffer char *Buffer = NULL; //载体文件buffer char *DestionBuffer = NULL; //用来存载体文件变动之前大小; char originsizeBuff[4] = {0}; //假设写到文件的位置为处 int orgposition = 4567; //取出资源文件到buffer中 Buffer = openFileToBuffer(pathSrc); //取出载体文件到buffer中 DestionBuffer = openFileToBuffer(pathDest); //得到载体文件变动之前大小 int sizeOrign = getFileSize(pathDest); //定义一个int指针,指向这个存储了载体文件大小的地址空间,这个地址空间是一个连续的,占用个字节(各个OS对int分配不同) int *p =&sizeOrign; //将载体原大小复制到定义好的个字节的buffer中,这样做就以二级制方式存好,要知道计算机就是这样,数据最终形式是 memcpy(originsizeBuff,p,4); //将载体文件原始大小(二级制方式存好)写入到载体文件指定位置, //这样做会损坏载体文件个字节的数据,相对图片而言,个字节,几乎没影响! writeInfoToSpecialPos(DestionBuffer,originsizeBuff,4,orgposition); //取资源文件大小 int BufferSize = getFileSize(pathSrc); //将资源文件写入到载体文件末尾; appendFuntion(pathA,Buffer,BufferSize); //扫尾 delete pathDest; delete pathSrc; return 0; } //写入到指定的位置是要用到的函数 void writeInfoToSpecialPos(char *destinationBuff,char *buffer,int buffersize,int position) { //其他边界检测代码 //其他边界检测代码 ofstream file; int i =0; while(i<buffersize) { destinationBuff[position+i]=buffer[i];//替换原来的四个字节 i++; } file.close(); } //写入到指定的位置是要用到的函数 void appendFuntion(char * filePath,char *buffer,int buffersize) { ofstream file; file.open(filePath,ios::binary|ios::app); if(file.good()) { file.write(buffer,buffersize);//追加到文件的末尾 file.close(); }else{ file.close(); } } char * openFileToBuffer(char * filepath) { ifstream fileA; char * buffer =NULL; int fileSize = getFileSize(filepath); buffer = new char[fileSize+1]; fileA.open(filepath,ios::binary); if(fileA.good()) { fileA.read(buffer,fileSize); fileA.close(); } fileA.close(); return buffer; } int getFileSize(char *filepath) { FILE * file = fopen(filepath,"rb"); if(file) { int size=filelength(fileno(file)); fclose(file); return size;//返回文件大小 } fclose(file); return 0; }
取回程序: // readData.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" //#include<stdio.h> #include <fstream> #include <string.h> #include <stdio.h> #include <fcntl.h> #include <io.h> using namespace std; char * openFileToBuffer(char * filepath); int getFileSize(char *filepath); char * getFileSpcialPosBuffer(char *filepath,int position); void saveBufferToFile(char * filepath,char *buffer,int buffersize); int getSizeFromSpecialPos(char *filepah,int position); int _tmain(int argc, _TCHAR* argv[]) { //经过追加后,载体文件已包含了追加的资源文件,已经在某一指定位置存好了此载体文件的原始大小 char *pathA ="c:/destination.jpg"; //输出文件 char *pathC = "c:/data.rar"; char *buffer=NULL; char *bufferC=NULL; int sizeA =0; int sizeB =0; int position =0; int times=0; sizeA = getFileSize(pathA); int orgposition = 4567; //从指定位置取出载体文件的原始大小 int orgsize = getSizeFromSpecialPos(pathA,orgposition); //从原始大小开始后的文件一定是追加上去的,所以取出此部分buffer,这部分的buffer就是追加的资源文件 bufferC = getFileSpcialPosBuffer(pathA,orgsize); //把bufferC存到新的文件中 saveBufferToFile(pathC,bufferC,sizeA-orgsize); delete bufferC; return 0; } char * openFileToBuffer(char * filepath) { ifstream fileA; char * buffer =NULL; int fileSize = getFileSize(filepath); buffer = new char[fileSize+1]; fileA.open(filepath,ios::binary); if(fileA.good()) { fileA.read(buffer,fileSize); fileA.close(); } fileA.close(); return buffer; } int getFileSize(char *filepath) { FILE * file = fopen(filepath,"rb"); if(file) { int size=filelength(fileno(file)); fclose(file); return size; } fclose(file); return 0; } char * getFileSpcialPosBuffer(char *filepath,int position) { ifstream file; char *buffer =NULL; int size = getFileSize(filepath);//载体文件的新的大小 buffer= new char[size-position];//新大小减去原始大小就是追加的文件大小。先申请这么大小的空间; file.open(filepath,ios::binary); if(file.good()) { file.seekg(position,ios::beg);//将文件游标指定原始文件大小位置, file.read(buffer,size-position);//取出追加的数据; file.close(); return buffer; } file.close(); return buffer; } void saveBufferToFile(char * filepath,char *buffer,int buffersize) { ofstream file; file.open(filepath,ios::binary); if(file.good()) { file.write(buffer,buffersize); }file.close(); } int getSizeFromSpecialPos(char *filepath,int position) { int size=0; int *p =&size; int size1 = getFileSize(filepath); char * buffer1 = new char[size1]; char buffer[4]= {0}; ifstream file; file.open(filepath,ios::binary); file.read(buffer1,size1); for(int i =0;i<4;i++) { buffer[i] = buffer1[position+i];//将指定位置的往后连续的四个字节取出来, } memcpy(p,buffer,4);//然后将这个取出来到个字节(存储的是原始载体文件大小的二进制)复制到int指针指向的一个用来int变量, //为什么这样做,因为其底层二进制存好的大小,已复制形式就避免编译器对数据的转换, //然后用int来存,就可以直接用了; delete buffer1; return size; }