前言
今天說一下寫病毒木馬會廣泛使用的一種技術——資源釋放技術。為什么我們在寫木馬時會使用到資源釋放技術呢?這是因為它可以使我們寫的程序變得簡潔。如果程序需要額外加載一些DLL文件或者文本文件,我們可以把它們作為資源插入到程序里。等程序運行,再把它們釋放到本地。這樣好處是只有一個.exe文件,這就降低了被發現的風險。
參考資料《Windows黑客編程》
資源插入
說資源釋放前,下面先說一下資源插入,資源插入不需要編寫代碼,只需要手動設置VS開發環境就可以。首先新建一個文件,這里命名為lxf ,然后在里面寫上內容,內容為my name is lxf,如下圖:
然后在VS2017中新建一個項目,在項目的解決方案里右鍵=》添加=》資源,如下圖
點擊資源后,然后再新彈出來的對話框,點擊自定義,然后在資源類型框里填MYRES,最后點擊導入,將剛才新建的文件導入到這里。如下圖:
倒入成功后,插入資源就完成了。
釋放資源
接下來看一下釋放資源的案例代碼,如下:
// test.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
//
#undef UNICODE
#include <Windows.h>
#include <stdio.h>
#include "resource.h"
// 提取資源
BOOL FreeMyResourse(UINT uiResouceName, char *lpszResourceType, char *lpszSaveFileName)
{
//獲取指定模塊的資源
HRSRC hRsrc = FindResource(NULL, MAKEINTRESOURCE(uiResouceName), lpszResourceType);
if (hRsrc == NULL)
{
printf("can't find the resource!\n");
return FALSE;
}
//獲取資源的大小
DWORD dwSize = SizeofResource(NULL, hRsrc);
if (dwSize <= 0)
{
printf("the resource's size is error!\n");
return FALSE;
}
//將資源加載到內存里
HGLOBAL hGlobal = LoadResource(NULL, hRsrc);
if(hGlobal == NULL)
{
printf("load resource error!\n");
return FALSE;
}
//鎖定資源
LPVOID lpVoid = LockResource(hGlobal);
if (lpVoid == NULL)
{
printf("lock resource error!\n");
return FALSE;
}
//保存資源為文件
FILE* fp = NULL;
fopen_s(&fp, lpszSaveFileName, "wb+");
if (fp == NULL)
{
printf("open file error!\n");
return FALSE;
}
fwrite(lpVoid, sizeof(char), dwSize, fp);
fclose(fp);
return TRUE;
}
int main()
{
char lpszResourceType[20] = "MYRES";
char szSaveFileName[20] = "lxf.txt";
BOOL flag = FreeMyResourse(IDR_MYRES4,lpszResourceType, szSaveFileName);
if (flag == TRUE)
{
printf("釋放成功\n");
}
return 0;
}
上面寫了釋放資源的案例代碼,這里講解一下吧,首先是FindResource函數,這個函數的作用就是確定模塊中指定類型和名稱的資源所在位置。
函數原型:
HRSRC FindResource(HMODULE hModule,LPCTSTR lpName,LPCTSTR lpType)
參數:
- hModule:處理包含資源的可執行文件的模塊。NULL值則指定模塊句柄指向操作系統通常情況下創建最近過程的相關位圖文件。
- lpName:指定資源名稱。
- lpType:指定資源類型。
返回值:
如果函數成功運行,那么返回值為指定資源信息塊的句柄。可將句柄傳遞給LoadResource函數來獲得這些資源。如果失敗,返回NULL。
接下來是SizeofResource函數。這個函數的作用是獲取指定資源的字節數。
函數原型:
DWORD SizeofResource(HMODULE hModule,HRSRC hReslnfo);
參數:
- hModule:包合資源的可執行文件模塊的句柄。
- hReslnfo:資源句柄。此句柄必須由函數FindResource或FindResourceEx來創建。
返回值:
如果函數運行成功,返回值資源的字節數。如果函數運行失敗,返回值為零。若想獲得更多的錯誤信息,請調用GetLastError函數。
接着是LoadResource函數。這個函數的作用是裝載指定資源到全局存儲器。
函數原型:
HGLOBAL LoadResource(HMODULE hModule,HRSRC hReslnfo);
參數:
- hModule:處理包合資源的可執行文件的模塊句柄。若hModule為NULL,系統從當前過程中的模塊中裝載資源。
- hReslnfo:將被裝載資源的句柄。它必須由函數FindResource或FindResourceEx創建。
返回值:如果函數運行成功,返回值是相關資源的數據的句柄。如果函數運行失敗,返回值為NULL。若想獲得更多的錯誤信息,請調用GetLastError函數。
最后一個是LockResource函數,這個函數作用是鎖定資源,並得到資源在內存中第一個字節的指針。
函數原型:
LPVOID LockResource(HGLOBAL hResDate);
參數:
- hResDate:被裝載的資源的句柄。函數LosdResource可以返回這個句柄。
返回值:
如果被裝載的資源被所住了,返回值是資源第一個字節的指針;否則為NULL。
注意:通過使用函數FindResource或FindResourceEx返回句柄試圖所住資源,不再工作。可以返回一個錯誤的數據和任意數據的指針。
當使用完資源后,必須通過調用函數以釋放加速器表、位圖、光標、目標以及某單所占的內存資源:加速器表:DestroyAcceleratorTable;位圖:DeleteObject;光標:DestroyCursor;圖標:Destroylcon;菜單:DestroyMenu。
當過程創建終止時,系統將自動刪除這些資源。但是調用相關函數也可以保留內存減少過程的工作設置所占空間。
相關函數說完了,最后再理一下代碼流程。
- 首先通過FindResource函數定位程序里的資源,主要根據資源類型,和資源名稱定位,獲得資源消息塊的句柄。
- 然后根據獲得的句柄,再通過SizeofResource函數獲取資源的大小。
- 然后通過LoadResource函數把資源加載到程序內存中。
- 再然后通過LockResource函數鎖定加載到內存中的資源,防止程序中的其他操作影響這塊內存。返回值就是資源在進程內存中的起始地址。
- 最后資源大小以及進程內存的起始地址,可以將資源數據讀出並保存為本地文件。
還有最后一點需要注意,在main()函數里的第一行和第三行需要根據自己的實際情況進行修改。
案例演示
創建新項目,寫入上述代碼,然后運行程序,查看窗口,和項目目錄,發現運行成功,資源釋放成功。
小結
關於資源釋放就說到這里,如有錯誤請斧正。