生活随笔
收集整理的這篇文章主要介紹了
EXE捆绑机制作原理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?一直都對EXE捆綁機很感興趣,想知道那種運行一個EXE文件就相當于運行多個EXE文件的軟件是什么原理.之前學習了PE文件知識,再加上一段研究時間,終于寫出了一個EXE捆綁機(軒轅EXE捆綁機http://bbs.pediy.com/showthread.php?s=&postid=191958#post191958).其實捆綁機在不懂之前感覺很神秘,弄懂它的原理后就很簡單了,下面就開始解說捆綁機的制作原理.
??想實現運行一個EXE文件同時運行其它多個EXE文件,必須要把多個EXE文件"組合"成一個EXE文件,而這一個EXE文件還必須有"分解"的能力,這樣才能把捆綁起來的EXE分離出來,使之正常運行.而"組合"也可以有多種形式,比如把EXE文件一個一個的加到文件末尾,或者以資源形式組合到一個EXE文件中,還有復雜一點的利用專用的安裝打包工具組合(例如安裝時捆綁的流氓軟件).下面主要介紹最簡單的第一種組合方式,也稱為傳統式捆綁機,其他方式可以觸類旁通,舉一反三.
??我把捆綁之前的文件叫宿主文件,其他EXE文件依次捆綁在宿主文件尾部.宿主文件運行的時候檢查自身文件大小,如果發現比"純潔"的宿主文件大就說明有別的EXE文件捆綁在宿主文件后,那么就把那個文件從自身讀出來創建成一個新文件,否則就什么都不做退出(具體請參加源碼).
??捆綁就更簡單了,一般需要另寫一個專門用來捆綁的程序,我管它叫主程序.主程序要和宿主文件協調工作,以規范的方式捆綁文件這樣宿主文件才能讀出捆綁的文件.比如在軒轅EXE捆綁機中就是簡單的在宿主文件后先寫入捆綁文件的大小,然后就是整個EXE文件.這樣宿主文件先讀出一個大小,再按大小讀取相應個字節就能分解出EXE文件.
??運行方式:一般都是創建成一個新的EXE文件,并運行.不知道能不能直接讀入內存運行,我功力太差就只能寫文件了.功能強大一些的捆綁機還可以加入對運行程序的控制,比如隱藏運行,定時運行,關閉后自動刪除等.
??軒轅EXE捆綁機制作初衷就是為了技術研究,根本沒打算做成一個黑客工具,對捆綁的文件沒有進行特殊處理(比如對文件每一個字節和文件大小進行異或運算,這里僅提供個思路),捆綁的文件運行后會在c:\windows\temp下創建捆綁的EXE文件,并運行.
??好了捆綁機的原理就介紹到這,是不是非常簡單?
??附宿主文件匯編源碼:
.
386
.model flat, stdcall
option casemap:noneinclude windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
include shell32.inc
includelib shell32.lib.constszFormat db "%d",
0szErr1 db "打開文件出錯!",
0szErr2 db "讀取文件出錯!",
0szErr3 db "分配內存出錯!",
0szDontRunMe db "此文件是EXE捆綁機的宿主文件,請不要單獨運行!",
0szNameFormat db "c:\windows\temp\temp%d.exe",
0
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_RunProcess procLOCAL @szFileName[MAX_PATH]:byte ;存放文件名LOCAL @hFileHandle ;文件句柄LOCAL @dwFileSize ;文件大小LOCAL @dwNumOfBytes ;實際影響的字節數LOCAL @lpMemAddress ;分配內在基址LOCAL @hFileWriteTo ;要寫入文件句柄LOCAL @si:SYSTEM_INFO ;系統信息結構LOCAL @i ;處理第幾個文件LOCAL @szTempFileName[128]:
byte ;生成的臨時文件名invoke GetSystemInfo, addr @si ;獲取系統信息mov @i, 1;獲得自身文件大小,并判斷是否已經捆綁了其他文件invoke GetModuleFileName, NULL, addr @szFileName, MAX_PATHinvoke CreateFile, addr @szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULLmov @hFileHandle, eax.if eax ==
INVALID_HANDLE_VALUEinvoke MessageBox, NULL, offset szErr1, 0, MB_ICONERRORjmp exit.endifinvoke GetFileSize, @hFileHandle, NULL.if eax ==
3584 ;如果沒捆綁其他文件則退出invoke MessageBox, NULL, offset szDontRunMe, 0, MB_ICONERRORjmp exit.endifinvoke SetFilePointer, @hFileHandle, 8888,
0, FILE_BEGIN ;文件指針移到捆綁文件開始處(具體位置需要在文件捆綁后重新設置);從文件尾部依次獲取文件數據,寫入臨時文件并運行
@@: invoke ReadFile, @hFileHandle, addr @dwFileSize, 4, addr @dwNumOfBytes, NULL.if @dwNumOfBytes ==
0jmp exit ;沒有更多的捆綁文件了.endif;invoke wsprintf, addr @szFileName, offset szFormat, @dwFileSize ;invoke MessageBox, 0, addr @szFileName,
0, MB_OK ;顯示文件大小invoke VirtualAlloc, NULL, @dwFileSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE ;分配內存以存放文件數據mov @lpMemAddress, eax.if eax ==
NULLinvoke MessageBox, NULL, offset szErr3, 0, MB_ICONERRORjmp exit.endifinvoke ReadFile, @hFileHandle, @lpMemAddress, @dwFileSize, addr @dwNumOfBytes, NULL ;讀入EXE文件數據invoke wsprintf, addr @szTempFileName, offset szNameFormat, @i; ;臨時文件名,格式為temp1.exe, temp2.exe ...invoke CreateFile, addr @szTempFileName, GENERIC_WRITE, NULL, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULLmov @hFileWriteTo, eax.if eax ==
INVALID_HANDLE_VALUEinvoke MessageBox, NULL, offset szErr1, 0, MB_ICONERRORjmp exit.endifinvoke WriteFile, @hFileWriteTo, @lpMemAddress, @dwFileSize, addr @dwNumOfBytes, NULL ;寫入文件數據invoke CloseHandle, @hFileWriteToinvoke VirtualFree, @lpMemAddress, 0, MEM_RELEASE ;釋放內存invoke ShellExecute, 0,
0, addr @szTempFileName,
0,
0, SW_SHOWinc @ijmp @b
exit:invoke CloseHandle, @hFileHandle ret_RunProcess endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:call _RunProcessinvoke ExitProcess, NULL
end start要注意其中的一句invoke SetFilePointer, @hFileHandle, 8888,
0, FILE_BEGIN 這里8888是隨意寫的數,當宿主文件被更改圖標后可能造成原始文件大小變化,所以這個位置的具體數值需要在主程序對宿主文件進行圖標更改操作后進行設置.這個數在編譯好的宿文件中可以用W32DASM查到,在49EH處. ?
總結
以上是生活随笔為你收集整理的EXE捆绑机制作原理的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。