程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> VC++ >> 實例編程:用VC寫個文件捆綁工具

實例編程:用VC寫個文件捆綁工具

編輯:VC++

  在2002年剛學VC的時候寫過文件捆綁工具,當時是配合自己寫的一個QQ木馬使用。後來去年在某個論壇上有人問起了文件捆綁的事,我就翻出以前的程序,寫下了這篇文檔,今天整理硬盤的時候,把這文章發了上來,其實很簡單。

  文件捆綁可以用在很多地方,比如木馬。也可以在發行軟件的時候把DLL捆綁在EXE文件後面,然後在EXE執行的時候動態調用DLL等等。。

  編譯環境:WIN2K+VC6。

  先假設我們要把 test1.exe和test2.exe這兩個文件捆綁成target.exe這一個文件,然後在運行target.exe的時候實現同時運行test1.exe和test2.exe。

  提一個小常識,PE格式的文件只要不修改文件頭和文件中間的內容,而只是在文件末尾添加數據,那麼這個PE文件可以正常執行。你可以試一試在命令行方式下執行copy test1.exe+test2.exe,命令執行完成後,test2.exe被添加到test1.exe文件尾,執行合並後的test1.exe雖然正常,但是test2.exe得不到執行。OK,這就是我們今天要解決的問題。我的想法是這樣的。把三個文件捆綁在一起,捆綁後target.exe實際包含三個文件,其中aaa.exe是我們自己寫的程序,test1.exe和test2.exe是我們要捆綁的程序。

  結構如下

  ---------------------------------------
  |aaa.exe|test1.exe|test2.exe|
  ---------------------------------------

  整個文件就叫target.exe,如果結構如上所示,那麼我們執行target.exe的時候實際上只有aaa.exe才會得到執行,這裡的aaa.exe是我們自己寫的,我們就讓aaa.exe多做點事,他要做的事就是:1、把test2.exe讀出來另存為c:\test2.exe,把test1.exe的內容讀出來另存為c:\test1.exe。2、調用CreateProcess來創建兩個新進程運行test1.exe和test2.exe。3、調用ExitProcess結束自身的進程。

  這樣一來我們的目的就達到了。同時為了隱蔽起見,我們可以把aaa.exe的窗口界面不顯示出來。

  但是又有一個問題,讀取的時候怎樣才能分辨出哪一段數據是test1.exe,哪一段數據是test2.exe?那我們就再想辦法把上面的結構再擴充一下。

-----------------------------------------------------
  |aaa.exe|test1.exe|test2.exe|len2|len1|
  -----------------------------------------------------

  在文件最後面再加兩段數據,分別用來存放test1.exe的文件長度和test2.exe的文件長度。並且固定len2和len1為30字節的長度。這樣在aaa.exe得到執行的時候先後面的兩個30字節內容,內容就是兩個文件的長度,再根據這兩個長度就可以准確讀取到test1.exe和test1.exe的內容。
 
  看看aaa.exe程序的關鍵代碼:

    CFile fSource(_pgmptr,CFile::modeRead | CFile::modeNoTruncate); //得到target.exe的文件長度
    int iSourceLength = fSource.GetLength();
    fSource.Seek(iSourceLength-60,CFile::begin);//移動文件指針到第test2.exe文件的末尾

    char buffer[40];
    ZeroMemory(buffer,40);
    fSource.Read(buffer,30);//讀取第len2的內容,也就是test2.exe的長度

    int iTargetLength = atoi(buffer);
    fSource.Seek(iSourceLength-iTargetLength-60,CFile::begin);//移動文件指針到test2.exe文件的開頭

    CFile fTarget("c:\\test2.exe",CFile::modeCreate | CFile::modeWrite |

  CFile::modeNoTruncate);//創建一個新文件為c:\\test2.exe

    char *pBuffer = new char[iTargetLength];//分配緩沖區
    ZeroMemory(pBuffer,iTargetLength);
    fSource.Read(pBuffer,iTargetLength);//將第test2.exe文件讀到緩沖區
    fTarget.Write(pBuffer,iTargetLength);//將緩沖區內容寫入c:\test2.exe
    delete []pBuffer;

  好了,現在test2.exe文件已經讀出來了,接下來就是要讀test1.exe的內容,過程大同小異

    fSource.Seek(iSourceLength-30,CFile::begin);//將文件指針移動到len1的開頭
    ZeroMemory(buffer,40);
    fSource.Read(buffer,30);//讀取len1的內容,len1的內容是test1.exe文件的長度


    int filelen = atoi(buffer);
    fSource.Seek(iSourceLength-60-filelen-iTargetLength,CFile::begin);//將文件指針移動到test1.exe文件頭
    fTarget.Open("c:\\test2.exe",CFile::modeCreate | CFile::modeWrite | CFile::modeNoTruncate);

    pBuffer = new char[filelen];
    ZeroMemory(pBuffer,filelen);

    fSource.Read(pBuffer,filelen);//將test1.exe文件讀到緩沖區
    fTarget.Write(pBuffer,filelen);//將test1.exe文件寫入c:\test1.exe
    
    delete []pBuffer;
    fSource.Close();
    fTarget.Close();

  現在我們就用CreateProcess來運行創建兩個新進程就可以運行c:\test1.exe和c:\test2.exe了。創建新進程的代碼很簡單我就不寫了。

  這部分是寫完了,但是我們捆綁文件的部分還沒寫完,重新新建一個基於對話框的程序。

    CFile fSource("c:\\aaa.exe",CFile::modeReadWrite | CFile::modeNoTruncate); //就是上面我們寫的aaa.exe
    fSource.SeekToEnd();//移動文件指針到文件尾

    CFile fFirstFile(m_FirstFile,CFile::modeRead | CFile::modeNoTruncate); //這段代碼是把test1.exe添加到aaa.exe尾部
    int ilen = fFirstFile.GetLength();
    int len = ilen;
    char *pBuffer = new char[ilen];
    ZeroMemory(pBuffer,ilen);

    fFirstFile.Read(pBuffer,ilen);
    fSource.Write(pBuffer,ilen);
    fFirstFile.Close();
    delete pBuffer;


    CFile fSecondFile(m_SecondFile,CFile::modeRead | CFile::modeNoTruncate); //這段代碼是捆綁test2.exe的
    ilen = fSecondFile.GetLength();
    pBuffer = new char[ilen];
    ZeroMemory(pBuffer,ilen);
    fSecondFile.Read(pBuffer,ilen);
    fSource.Write(pBuffer,ilen);
    fSecondFile.Close();
    delete pBuffer;



    char tempbuffer[30];//將test2.exe的長度轉換成字符串,如果長度不夠30就添加空格至30,再添加到文件尾部
    ZeroMemory(tempbuffer,30);
    itoa(ilen,tempbuffer,10);
    
    while (strlen(tempbuffer) < 30)
    {
        strcat(tempbuffer," ");
    }

    fSource.Write(tempbuffer,30);

   ZeroMemory(tempbuffer,30);//將test2.exe的長度轉換成字符串,如果長度不夠30就添加空格至30,再添加到文件尾部
    itoa(len,tempbuffer,10);
    
    while (strlen(tempbuffer) < 30)
    {
        strcat(tempbuffer," ");
    }
    
    fSource.Write(tempbuffer,30);

    fSource.Close();

    ::MessageBox(NULL,"捆綁完成","提示",MB_ICONINFORMATION);

  OK,這樣我們就生成了一個新文件target.exe,這個target.exe的結構上面已經說了。執行target.exe後,aaa.exe首先得到執行,然後test1.exe和test2.exe都會執行。為了增強隱蔽性,我們在aaa.exe的OnInitDialog()函數裡寫下如下代碼:

    ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW);
    ::MoveWindow(m_hWnd,0,0,0,0,TRUE);
這樣aaa.exe執行的時候沒窗口,也不會在任務欄上顯示任務條。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved