Window黑客程式設計之資源釋放技術

雪痕*發表於2021-11-08

前言

今天說一下寫病毒木馬會廣泛使用的一種技術——資源釋放技術。為什麼我們在寫木馬時會使用到資源釋放技術呢?這是因為它可以使我們寫的程式變得簡潔。如果程式需要額外載入一些DLL檔案或者文字檔案,我們可以把它們作為資源插入到程式裡。等程式執行,再把它們釋放到本地。這樣好處是隻有一個.exe檔案,這就降低了被發現的風險。

參考資料《Windows黑客程式設計》

資源插入

說資源釋放前,下面先說一下資源插入,資源插入不需要編寫程式碼,只需要手動設定VS開發環境就可以。首先新建一個檔案,這裡命名為lxf ,然後在裡面寫上內容,內容為my name is lxf,如下圖:

image-20211106212130307

然後在VS2017中新建一個專案,在專案的解決方案裡右鍵=》新增=》資源,如下圖

image-20211106212844487

點選資源後,然後再新彈出來的對話方塊,點選自定義,然後在資源型別框裡填MYRES,最後點選匯入,將剛才新建的檔案匯入到這裡。如下圖:

image-20211106213401609

倒入成功後,插入資源就完成了。

釋放資源

接下來看一下釋放資源的案例程式碼,如下:

// 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。

當過程建立終止時,系統將自動刪除這些資源。但是呼叫相關函式也可以保留記憶體減少過程的工作設定所佔空間。

相關函式說完了,最後再理一下程式碼流程。

  1. 首先通過FindResource函式定位程式裡的資源,主要根據資源型別,和資源名稱定位,獲得資源訊息塊的控制程式碼。
  2. 然後根據獲得的控制程式碼,再通過SizeofResource函式獲取資源的大小。
  3. 然後通過LoadResource函式把資源載入到程式記憶體中。
  4. 再然後通過LockResource函式鎖定載入到記憶體中的資源,防止程式中的其他操作影響這塊記憶體。返回值就是資源在程式記憶體中的起始地址。
  5. 最後資源大小以及程式記憶體的起始地址,可以將資源資料讀出並儲存為本地檔案。

還有最後一點需要注意,在main()函式裡的第一行和第三行需要根據自己的實際情況進行修改。

案例演示

建立新專案,寫入上述程式碼,然後執行程式,檢視視窗,和專案目錄,發現執行成功,資源釋放成功。

image-20211107200132012

小結

關於資源釋放就說到這裡,如有錯誤請斧正。

相關文章