如何将多个文件捆绑成一个可执行文件
內容:
下載示例程序代碼
將多個文件合并成一個最終可執行文件,運行這個最終合成文件后,就相當于運行了合并前的多個文件。這種程序在木馬程序合并中會經常用到,你想知道它是怎么用程序實現的么?下面我就拿我用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); //直接退出程序,不顯示捆綁程序畫面
}
}
以上部分代碼的具體實現的細節問題,可在下載實例代碼后,仔細查看源碼既可(內有詳細注釋)。
聯系方式:
地址:陜西省西安市勞動路2號院六單元
郵編:710082
作者EMAIL:jingzhou_xu@163.net
未來工作室(Future Studio)
總結
以上是生活随笔為你收集整理的如何将多个文件捆绑成一个可执行文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 代码写累了来这看看,笑笑
- 下一篇: Go协程池设计思路(Task-Job-W