分类: C/C++
2008-03-18 13:57:54
将多个文件合并成一个最终可执行文件,运行这个最终文件时,就相当于运行了合并前的多个文件。这种程序在木马程序合并中会经常用到,你想知道它是怎么用程序实现的么?下面我就用我用VC6.0做的一个文件捆绑器的例子代码来告诉你,程序运行后界面如下: 图一 基本组成思想:其实,其中的构成思想非常简单。建立一个新的二进制文件,先写入你的捆绑程序的数据和其文件长度,再写入你要捆绑的第一个文件的数据和其文件长度,后再直接写入你要捆绑的第二个文件的数据和文件长度……,最后就可直接写入你要捆绑的最后一个文件的数据(不需其文件长度)。最终文件被执行时,也就是将上面的方法思想倒过来既可。(下面实例仅告诉你如何实现二个文件的捆绑,至于多个文件的捆绑,读者只需略加改动既可,详情请细看下载后的实例代码。) 下面我来讲讲如何具体将其来实现: 1、捆绑多个文件为一个可执行程序 先得到自身捆绑程序的文件长度和第一个要捆绑文件的文件长度,枚举第一个要捆绑文件有无图标,有的话就用它做为最终生成文件的图标,否则用自身捆绑程序所带默认图标做最终生成文件的图标。在新建二进制文件中写入自身捆绑程序的数据和其文件长度,再写入第一个要捆绑文件的数据及其文件长度,最后直接写入第二个文件的数据既可。 捆绑涵数代码实现如下: //绑定多个文件为一个可执行文件 |
bool CBindFileDlg::Bind_Files() { FILE* myself; //自身文件 FILE* out; //最终合成文件 FILE* in; //待绑定文件 int bytesin; int totalbytes = 0; struct _stat ST; unsigned int finder = 0x12345678; unsigned int i, k; int l=1; //状态显示 char buff[20]; //状态显示 his_name = strFirstFilePath; //第一个绑定的文件名 _stat(my_name, &ST); modify_data.my_length = ST.st_size; if (modify_data.my_length == 0) { MessageBox("绑定文件中,自身文件长度为零时出错!","错误"); return false; } buf = (BYTE *)malloc(modify_data.my_length); if (buf == NULL) { MessageBox("绑定文件中,分配自身文件长度时出错!","错误"); return false; } myself = fopen(my_name, "rb"); //打开自身文件 if (myself == NULL) { free(buf); MessageBox("绑定文件中,打开自身文件时出错!","错误"); return false; } bytesin = fread(buf, 1, modify_data.my_length, myself); fclose(myself); if (bytesin != modify_data.my_length) { free(buf); MessageBox("绑定文件中,不能完全读取自身文件内容时出错!","错误"); return false; } for (i = 0; i < modify_data.my_length - sizeof(finder); i += sizeof(finder)) { for (k = 0; k < sizeof(finder); k++) { if (buf[i+k] != ((BYTE*)&finder)[k]) break; } if (k == sizeof(finder)) //定位并保存自身数据文件大小 { memcpy(buf+ i, &modify_data, sizeof(modify_data)); break; } } if (i >= modify_data.my_length - sizeof(finder)) { free(buf); MessageBox("绑定文件中,不能定位自身文件时出错!","错误"); return false; } if (_stat(strFirstFilePath, &ST) != 0 || ST.st_size == 0) { free(buf); MessageBox("绑定文件中,读取第一个要绑定文件时出错!","错误"); return false; } list_my_icons(); out = fopen(strFinalFilePath, "wb"); //创建最终合成文件 if (out == NULL) { free(buf); MessageBox("绑定文件中,创建绑定后生成的合成文件时出错!","错误"); return false; } totalbytes += fwrite(buf, 1, bytesin, out); in = fopen(strFirstFilePath, "rb"); //打开第一个要绑定的文件 if (in == NULL) { free(buf); MessageBox("绑定文件中,打开第一个要绑定文件时出错!","错误"); return false; } //写入第一个要绑定文件的长度到合成文件中 totalbytes += fwrite(&ST.st_size, 1, sizeof(ST.st_size), out); //写入最终分解后文件执行方式的标志位(同步或异步执行) UpdateData(TRUE); //传控件值到变量m_Sync中 totalbytes += fwrite(&m_Sync, 1, sizeof(int), out); while (bytesin = fread(buf, 1, modify_data.my_length, in)) { totalbytes += fwrite(buf, 1, bytesin, out); } fclose(in); //关闭第一个绑定文件句柄 //设置进度条显示 m_Progress.SetRange(0,500); for (int m = 0; m < 500; m++) m_Progress.SetPos(m); m_Parts = _ltoa(l, buff, 10); m_Parts += _T("个文件已绑定"); UpdateData(FALSE); l++; in = fopen(strSecondFilePath, "rb"); //打开第二个要绑定的文件 if (in == NULL) { free(buf); MessageBox("绑定文件中,打开第二个要绑定文件时出错!","错误"); return false; } while (bytesin = fread(buf, 1, modify_data.my_length, in)) { totalbytes += fwrite(buf, 1, bytesin, out); } //设置进度条显示 m_Progress.SetRange(0,500); for (int n = 0; n < 500; n++) m_Progress.SetPos(n); m_Parts = _ltoa(l, buff, 10); m_Parts += _T("个文件已绑定"); UpdateData(FALSE); l++; fclose(in); //关闭第二个绑定文件句柄 fclose(out); //关闭最终合成文件句柄 free(buf); //释放缓冲区 return true; } |
2、释放最终合成文件并同时运行它们。 打开自身文件,从中得到自身捆绑程序的文件长度,便可将文件指针定位到第一个被捆绑文件的位置,读取其文件长度和其数据,将其读出数据写入第一个新建文件中。同样,通过已读取的自身捆绑程序文件长度和第一个被捆绑文件的文件长度加上其保存这两个文件长度值的字节数,既可准确定位第二个被捆绑文件的位置,读取其数据,写入到第二个新建文件中。同时,运行这两个文件,最后再删除这两个文件既可。 释放最终合成文件的代码具体实现如下: //分解已合并的文件,同时运行它们 |
void CBindFileDlg::Unbind() { FILE* myself; //自身文件 FILE* out; //分解后文件 int bytesin; int totalbytes = 0; char temp_exe1[] = "temp1.exe"; //分解后的绑定文件名一 char temp_exe2[] = "temp2.exe"; //分解后的绑定文件名二 int SyncFlag; //文件最终执行标志 buf = (BYTE*)malloc(modify_data.my_length); myself = fopen(my_name, "rb"); //打开最终合成文件 if (myself == NULL) { free(buf); MessageBox("分离文件中,打开自身文件时出错!","错误"); return; } out = fopen(temp_exe1, "wb"); //创建第一个绑定的文件 if (out == NULL) { free(buf); MessageBox("分离文件中,创建第一个被绑定文件时出错!","错误"); return; } //将文件指针定位到捆绑器程序长度尾部 fseek(myself, modify_data.my_length, SEEK_SET); //读取第一个绑定文件的长度 if (fread(&prog1_length, sizeof(prog1_length), 1, myself) == 0) { free(buf); MessageBox("分离文件中,读取第一个被绑定文件长度时出错!","错误"); return; } //读取最终文件执行方式(同步或异步执行) if (fread(&SyncFlag, sizeof(int), 1, myself) == 0) { free(buf); MessageBox("分离文件中,读取第一个被绑定文件长度时出错!","错误"); return; } //读取第一个文件内容并写入 while (bytesin = fread(buf, 1, sizeof(buf), myself)) { if (totalbytes + bytesin > prog1_length) bytesin = prog1_length - totalbytes; totalbytes += fwrite(buf, 1, bytesin, out); } fclose(out); //关闭第一个绑定文件句柄 #ifdef DEBUG_PRINT fprintf(stderr, "已复制 %d 字节!\n", totalbytes); #endif DEBUG_PRINT totalbytes = 0; out = fopen(temp_exe2, "wb"); //创建第二个绑定的文件 if (out == NULL) { free(buf); MessageBox("分离文件中,创建第二个被绑定文件时出错!","错误"); return; } //将文件指针定位到最终合成文件中的第二个绑定文件头部, 偏移量 == //(捆绑器自身文件长度+保存第一个绑定文件长度所占字节数+保存最终文件执行标志所占字节数+第一个绑定文件长度) fseek(myself, modify_data.my_length + sizeof(modify_data.my_length) + sizeof(int) + prog1_length, SEEK_SET); //读取第二个绑定文件内容并写入 while (bytesin = fread(buf, 1, sizeof(buf), myself)) { totalbytes += fwrite(buf, 1, bytesin, out); } fclose(out); //关闭第二个绑定文件句柄 #ifdef DEBUG_PRINT fprintf(stderr, "已复制 %d 字节\n", totalbytes); #endif DEBUG_PRINT fclose(myself); //关闭最终合成文件句柄 if (totalbytes == 0) { free(buf); MessageBox("分离文件中,在自身文件中没有被分离的对象!","错误"); return; } free(buf); //释放缓冲区 if(!SyncFlag) //0 -- 同步执行,1 -- 异步执行 { //置为分解后,为同步执行方式 Create_Process(temp_exe1, false); Create_Process(temp_exe2, false); } else { //置为分解后,为异步执行方式 Create_Process(temp_exe1, true); Create_Process(temp_exe2, true); } } |
其中具体实现细节问题,可在下载实例代码后,仔细查看既可(内有详细注释)。 |