图片是一个有趣的东西,一次偶然的机会发现可以用图片来达到文件的隐藏。
往图片文件的末尾添加数据,并不会影响图片的正常显示。于是做了一下的程序,将一个文件追加到图片中,然后在取出来;
大体思路是:
写入过程:
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;
}