Windows黑客編程技術詳解 --2.3 病毒木馬資源釋放技術(內含贈書福利)
本文經原作者授權,節選自《Windows黑客編程技術詳解》一書。文末有福利哦!!
-----------------------------------------------------------------
病毒木馬之所以會廣泛使用資源釋放技術,是因爲它可以使程序變得更簡潔。如果程序額外需要加載一些DLL文件、文本文件、圖片文件,或者其他的音/視頻文件等,則可以把它們作爲資源插入到程序裏,等到程序運行後,再把它們釋放到本地上。這樣做的好處是編譯出來的程序只有一個exe文件,而不需要附帶其他文件,因而程序變得很簡潔。只需把exe植入到用戶計算機上,而不需要連同其他文件一起植入,這降低了被發現的風險。
2.3.1 資源插入的步驟
在介紹資源釋放技術之前,先介紹如何向程序中插入資源。資源插入不需要編碼操作,只需手動設置VS開發環境即可完成。
本節以“520”這個沒有文件類型的文件作爲演示實例,向大家介紹文件作爲資源插入到程序中的步驟,其他類型的插入也是類似的。其中,“520”的文件內容如圖2-5所示。
打開項目工程之後,在解決方案中,選擇“添加”,選中“資源”。本節演示的是插入自定義資源,所以單擊“自定義(C)...”按鈕。資源添加對話框,如圖2-6所示。
然後,在“新建自定義資源”對話框中,輸入“資源類型”,如“MYRES”,然後單擊“確定”。新建自定義資源對話框,如圖2-7所示。
在設置好自定義資源的類型之後,接着回到“添加資源”對話框。選中剛新建的“MYRES”資源類型,然後單擊右側的“導入(M)...”按鈕來選擇導入文件。
經過上述步驟後便完成了插入資源的操作。
2.3.2 函數介紹 1.FindResource函數
確定模塊中指定類型和名稱的資源所在位置。
函數聲明
HRSRC FindResource(
HMODULE hModule,
LPCWSTR lpName,
LPCWSTR lpType)
參數
hModule[in]
處理包含資源的可執行文件模塊。若hModule爲NULL,則系統從當前進程的模塊中裝載資源。
lpName[in]
指定資源名稱。
lpType[in]
指定資源類型。
返回值
如果函數運行成功,那麼返回值爲指定資源信息塊的句柄。可將這個句柄傳遞給LoadResource函數來獲得這些資源。如果函數運行失敗,則返回值爲NULL。
2.SizeofResource函數
獲取指定資源的字節數。
函數聲明
DWORD SizeofResource(
HMODULE hModule,
HRSRC hResInfo)
參數
hModule[in]
包含資源的可執行文件模塊的句柄。若hModule爲NULL,則系統從當前進程的模塊中裝載資源。
hResInfo[in]
資源句柄。此句柄必須由函數FindResource或FindResourceEx來創建。
返回值
如果函數運行成功,則返回值爲資源的字節數;如果函數運行失敗,則返回值爲零。
3.LoadResource函數
裝載指定資源到全局存儲器。
函數聲明
HGLOBAL LoadResource(
HMODULE hModule,
HRSRC hResInfo)
參數
hModule[in]
處理資源可執行文件的模塊句柄。若hModule爲NULL,則系統從當前進程的模塊中裝載資源。
hResInfo[in]
資源句柄。此句柄必須由函數FindResource或FindResourceEx來創建。
返回值
如果函數運行成功,則返回值爲相關資源數據的句柄。如果函數運行失敗,則返回值爲NULL。
4.LockResource函數
鎖定資源並得到資源在內存中第一個字節的指針。
函數聲明
LPVOID LockResource(
HGLOBAL hResData)
參數
hResData[in]
裝載資源的句柄。函數LoadResource可以返回這個句柄。
返回值
如果裝載資源被鎖住了,則返回值是資源第一個字節的指針;反之則爲NULL。
2.3.3 實現原理
爲方便開發人員獲取程序裏的資源,Windows提供了一系列帶有操作資源的WIN32 API函數。所以,程序實現也是基於這些WIN32 API函數進行操作的。
首先,通過FindResource定位程序裏的資源,主要是根據“資源類型”和“資源名稱”進行定位,從而獲取資源信息塊的句柄。
其次,根據上面獲取的資源信息塊的句柄,利用SizeofResource獲取資源的大小之後,再通過LoadResource把資源加載到程序內存中。
接着,通過LockResource鎖定加載到內存中的資源,防止程序中的其他操作影響這塊內存。其中,返回值就是資源在進程內存中的起始地址。
最後,根據資源大小以及進程內存的起始地址,可將資源數據讀取出來並保存爲本地文件。
經過上述4個步驟,便可以定位出資源,並將其釋放到本地磁盤。它的原理就是通過PE文件結構,確定資源在PE文件中的偏移和大小。
在資源釋放過程中,要特別注意一點就是,必須明確資源所在的模塊,要指明所在模塊句柄並且統一。因爲文件可以以資源的形式插入到DLL文件中,所以當DLL加載到其他進程時,資源所在模塊仍是該DLL模塊。要想成功釋放資源,則需要先通過GetModuleHandle函數獲取該DLL模塊的句柄。否則,資源釋放會因爲指定了錯誤模塊而失敗。
2.3.4 編程實現
BOOL FreeMyResource(UINT uiResouceName, char *lpszResourceType, char *lpszSaveFileName)
{
// 獲取指定模塊裏的資源
HRSRC hRsrc = ::FindResource(NULL, MAKEINTRESOURCE(uiResouceName), lpszResourceType);
if (NULL == hRsrc)
{
ShowError("FindResource");
return FALSE;
}
// 獲取資源的大小
DWORD dwSize = ::SizeofResource(NULL, hRsrc);
if (0 >= dwSize)
{
ShowError("SizeofResource");
return FALSE;
}
// 將資源加載到內存裏
HGLOBAL hGlobal = ::LoadResource(NULL, hRsrc);
if (NULL == hGlobal)
{
ShowError("LoadResource");
return FALSE;
}
// 鎖定資源
LPVOID lpVoid = ::LockResource(hGlobal);
if (NULL == lpVoid)
{
ShowError("LockResource");
return FALSE;
}
// 保存資源爲文件
FILE *fp = NULL;
fopen_s(&fp, lpszSaveFileName, "wb+");
if (NULL == fp)
{
ShowError("LockResource");
return FALSE;
}
fwrite(lpVoid, sizeof(char), dwSize, fp);
fclose(fp);
return TRUE;
}
2.3.5 測試
本節創建一個MFC工程項目,按照上述步驟插入資源,並按照上述的實現原理來編碼實現,調用封裝好的資源釋放函數進行資源釋放的測試。資源釋放的時候,將其保存爲txt格式文件。
單擊對話框中“釋放”按鈕後,提示資源釋放成功,如圖2-8所示。然後查看目錄,本地成功地生成“520.txt”文件,打開文件查看內容,它與之前插入的“520”文件中的內容相同,如圖2-9所示。資源釋放成功。
2.3.6 小結
資源釋放技術的實現原理並不是很複雜,只需理清WIN32 API函數的調用關係以及函數作用即可。要特別注意一點,明確資源所在的模塊,如果資源包含在DLL文件中,則可以在DllMain中或是通過GetModuleHandle函數獲取DLL模塊的句柄。
安全小貼士
可以根據PE結構中的資源表IMAGE_RESOURCE_DIRECTORY來解析PE文件中包含的所有資源,並且獲取資源的偏移地址及數據大小。例如,常用的資源編輯工具eXeScope就是根據資源表來枚舉PE文件中的資源的。
-------------------------------------------
福利時間到了
說明:
在),第一章送出三本書。同時第二章(,,2.3節),我們每一節仍然會送出一本書,也就是參與本節的活動,會增加你的中獎概率。在前四章更新完畢之後,會統一公佈中獎名單,並組織線上答疑活動,和本書作者親密交流。
本篇文章 會送出一本書,參與辦法如下(微信訂閱號打開請忽略1,2,3步驟):
- 找到本篇文章並打開
- 點擊文章下的“在看”按鈕。
- 文章下留言,談體會
- 拉你的朋友過來爲你的留言點贊 ------------------------------------------------------ 明天我們繼續推送2.3節《資源釋放技術》
覺得很贊請掃碼讚賞
(內含送書福利)
滲透測試入門指南與路線規劃(全文版)