如何将多个文件捆绑成一个可执行文件

 

                           如何将多个文件捆绑成一个可执行文件

作者:徐景周

 

下载示例程序代码(http://www.csdn.net/cnshare/soft/10/10356.shtm)

 

将多个文件合并成一个最终可执行文件,运行这个最终合成文件后,就相当于运行了合并前的多个文件。这种程序在木马程序合并中会经常用到,你想知道它是怎么用程序实现的么?下面我就拿我用VC6.0做的一个文件捆绑器的实例代码来告诉你,实例程序运行后的界面如下:

 

图例

基本构成思想:其实,文件捆绑的构成思想非常简单,它主要可分为合并文件和分解释放文件二大部分。合并文件时:建立一个新的二进制文件,先写入你的捆绑程序的自身数据和其文件长度,再写入你要捆绑的第一个文件的数据和其文件长度,后再直接写入你要捆绑的第二个文件的数据和其文件长度……,最后可直接写入你要捆绑的最后一个文件的数据(不再需要其文件长度)。分解释放最终合成文件时:也就是将上面的方法思想倒过来既可,打开最终合成文件,读取源捆绑程序自身文件长度,将文件指针移到捆绑程序自身数据后,读取第一个被绑定文件的长度,接着读取其后长度大小的一段文件数据并写入到一新建文件1中,再读取第二个被绑定文件的长度,接着读取其后长度大小的一段文件数据并写入到新建文件2中……,直到最后,就可直接读取最后一个被绑定文件的数据并将其写入到最后一个新建文件中既可。(下面实例代码仅告诉你如何实现二个文件的捆绑,至于多个文件的捆绑,读者只需按上面所说略加改动既可,实现详情请查看下载后的实例代码。)

 

下面我来讲讲文件捆绑最核心的部分,以及如何将其用代码来实现的方法:

1、 捆绑多个文件为一个可执行程序

思路:先获得捆绑程序自身的文件长度和第一个被捆绑文件的文件长度,枚举出第一个被捆绑文件的图标,有图标的话就用它做为最终生成文件的图标,否则就用捆绑程序自身所带图标做为最终生成文件的图标。然后,新建一个二进制文件,在其中写入捆绑程序自身的文件数据和其文件长度,接着写入第一个被捆绑文件的文件长度和最终合成文件的运行方式标志位(同步还是异步运行),紧接着再写入第一个被捆绑文件的文件数据,最后直接写入第二个被捆绑文件的文件数据既可。

l         合并程序涵数的具体代码实现如下:

//绑定二个文件为一个可执行文件

bool CBindFileDlg::Bind_Files()

{

…… (省略:此部分代码用来定义各成员变量)

 

     his_name = strFirstFilePath; //第一个绑定的文件名

 

     _stat(my_name, &ST);         //获取自身捆绑文件信息

     modify_data.my_length = ST.st_size; //得到自身文件长度

     buf = (BYTE *)malloc(modify_data.my_length); //分配一定大小缓冲区

     myself = fopen(my_name, "rb");  //打开自身文件

 

     //先读取捆绑程序自身文件数据

     bytesin = fread(buf, 1, modify_data.my_length, myself);

fclose(myself);

 

    ……(省略:此部分代码用来获取自身文件和第一个被捆绑文件长度,以及获取最终合成文件的图标)

 

     out = fopen(strFinalFilePath, "wb"); //创建最终合成文件

  

     //先将前面读出的自身捆绑程序的数据写入最终合成文件中

     totalbytes += fwrite(buf, 1, bytesin, out);

 

     in = fopen(strFirstFilePath, "rb");  //打开第一个要绑定的文件

     //写入第一个要绑定文件的长度到最终合成文件中

     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); //关闭第一个绑定文件句柄

 

     in = fopen(strSecondFilePath, "rb");   //打开第二个要绑定的文件

    

//直接写入第二个要绑定文件的数据到最终合成文件中

     while (bytesin = fread(buf, 1, modify_data.my_length, in))

     {

          totalbytes += fwrite(buf, 1, bytesin, out);

}

……(省略:此部分代码用来关闭文件句柄)

}

2、  释放最终合成文件并同时运行它们

思路:打开自身文件,从中得到捆绑程序自身的文件长度,将文件指针定位到捆绑程序自身数据后的第一个被捆绑文件的位置,读取其第一个被捆绑文件的文件长度和最终合成文件释放后的运行方式标志(同步还是异步方式执行),接着读取其第一个被捆绑文件的文件数据,将其读出数据直接写入到一个新建的二进制文件中。同样,通过已读取的捆绑程序自身文件长度和第一个被捆绑文件的文件长度再加上其保存这两个文件长度值的字节数及最终合成文件释放后的运行标志所占字节数,既可准确定位出第二个被捆绑文件的文件数据所在的指针位置,读取其文件数据后,直接写入到一个新建二进制文件中。最后,根据前面读出的文件释放后的运行标志,来决定以何种方式来运行释放的这两个文件,如果是同步方式,顺序运行后会删除这两个生成文件,异步方式则会同时运行而不会删除这二个生成文件。

l           释放最终合成文件的代码具体实现如下:

//分解已合并的文件,同时运行它们

void CBindFileDlg::Unbind()

{

  ……(省略掉:此部分代码主要用来定义成员变量)

 

  myself = fopen(my_name, "rb");  //打开最终合成文件

  out = fopen(temp_exe1, "wb");   //创建第一个释放的生成文件

 //将文件指针定位到捆绑器程序尾部

  fseek(myself, modify_data.my_length, SEEK_SET);

 

 //读取第一个绑定文件的长度 

  fread(&prog1_length, sizeof(prog1_length), 1, myself);

 

 //读取最终文件执行方式(同步或异步执行)

  fread(&SyncFlag, sizeof(int), 1, myself) ;

    

 //读取第一个文件内容并写入到新建的temp1.exe文件中

  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);  //关闭第一个绑定文件句柄

   totalbytes = 0; //重新清零

   out = fopen(temp_exe2, "wb");      //创建第二个释放的生成文件

 /*将文件指针定位到最终合成文件中的第二个绑定文件头部, 偏移量 ==(捆绑器自身文件长度+保存第一个绑定文件长度所占字节数+保存最终文件执行标志所占字节数+第一个绑定文件长度)*/

fseek(myself,modify_data.my_length+ sizeof(modify_data.my_length) + sizeof(int) + prog1_length, SEEK_SET);

   

 //读取第二个绑定文件内容并写入到新建的temp2.exe文件中

 while (bytesin = fread(buf, 1, sizeof(buf), myself))

 {

     totalbytes += fwrite(buf, 1, bytesin, out);

  }

 

……(省略:此部分代码用来关闭文件句柄和决定生成文件的运行方式)

 }

3、判断何时捆绑文件,何时又分解释放最终合成文件。

思路:由于本程序采用将捆绑程序自身直接作为最终合成文件的文件头,再把被绑定文件数据附加其后的方式来生成最终合成文件的。所以,只要知道捆绑程序自身的文件长度,根据文件长度是否大于原文件长度,就可判断出是否该释放分解文件了。可在初始化对话框涵数OnInitDialog()增加此判断,及可知道是否是最终合成文件(要不要释放内部绑定文件)。本例程用VC6.0采用静态连接方式生成的Release版,文件长度为184K,大于184K(184*1024)字节,既可判断出该做释放分解操作。

l         故判断是捆绑还是释放文件的代码具体实现如下:

BOOL CBindFileDlg::OnInitDialog()

{

 ……(省略:此部分代码用于初始化一些变量)

 

//获取自身文件名到my_mane变量中

::GetModuleFileName(0, my_name, sizeof(my_name));

 

struct _stat ST;

_stat(my_name, &ST);    //获取自身文件信息(长度)

/*在此加入捆绑器程序的最终大小,来判断文件执行时是绑定文件还是分解执行文件当发现自身文件大小大于原大小184K时,为释放内部合成文件*/

if(ST.st_size > 184*1024)

{

   Unbind(); //分离文件并运行

  exit(0);    //直接退出程序,不显示捆绑程序画面

}

}

 

以上部分代码的具体实现的细节问题,可在下载实例代码后,仔细查看源码既可(内有详细注释)。

 

联系方式:

未来工作室(Future Studio)

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
程序员的必经之路! 【限时优惠】 现在下单,还享四重好礼: 1、教学课件免费下载 2、课程案例代码免费下载 3、专属VIP学员群免费答疑 4、下单还送800元编程大礼包 【超实用课程内容】  根据《2019-2020年中国开发者调查报告》显示,超83%的开发者都在使用MySQL数据库。使用量大同时,掌握MySQL早已是运维、DBA的必备技能,甚至部分IT开发岗位也要求对数据库使用和原理有深入的了解和掌握。 学习编程,你可能会犹豫选择 C++ 还是 Java;入门数据科学,你可能会纠结于选择 Python 还是 R;但无论如何, MySQL 都是 IT 从业人员不可或缺的技能!   套餐中一共包含2门MySQL数据库必学的核心课程(共98课时)   课程1:《MySQL数据库从入门到实战应用》   课程2:《高性能MySQL实战课》   【哪些人适合学习这门课程?】  1)平时只接触了语言基础,并未学习任何数据库知识的人;  2)对MySQL掌握程度薄弱的人,课程可以让你更好发挥MySQL最佳性能; 3)想修炼更好的MySQL内功,工作中遇到高并发场景可以游刃有余; 4)被面试官打破沙锅问到底的问题问到怀疑人生的应聘者。 【课程主要讲哪些内容?】 课程一:《MySQL数据库从入门到实战应用》 主要从基础篇,SQL语言篇、MySQL进阶篇三个角度展开讲解,帮助大家更加高效的管理MySQL数据库。 课程二:《高性能MySQL实战课》主要从高可用篇、MySQL8.0新特性篇,性能优化篇,面试篇四个角度展开讲解,帮助大家发挥MySQL的最佳性能的优化方法,掌握如何处理海量业务数据和高并发请求 【你能收获到什么?】  1.基础再提高,针对MySQL核心知识点学透,用对; 2.能力再提高,日常工作中的代码换新貌,不怕问题; 3.面试再加分,巴不得面试官打破沙锅问到底,竞争力MAX。 【课程如何观看?】  1、登录CSDN学院 APP 在我的课程中进行学习; 2、移动端:CSDN 学院APP(注意不是CSDN APP哦)  本课程为录播课,课程永久有效观看时长 【资料开放】 课件、课程案例代码完全开放给你,你可以根据所学知识,自行修改、优化。  下载方式:电脑登录课程观看页面,点击右侧课件,可进行课程资料的打包下载。
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值