1. 程式人生 > 其它 >第二章 基礎技術

第二章 基礎技術

一、執行單一例項

通過建立系統命名互斥物件的方式來實現

1、實現原理

通過CreateMutex函式建立一個命名的互斥物件,如果物件建立成功,而且通過呼叫GetLastError函式獲取的返回碼為ERROR_ALREADY_EXISTS,則表示該命名互斥物件存在,即程式重複執行。否則,認為程式首次執行。

2、API

CreateMutex
https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createmutexa

3、實現程式碼如下

#include <windows.h>
#include<tchar.h>
#include<stdio.h>

BOOL IsAlreadyRun()
{
	HANDLE hMutex = NULL;
	hMutex = ::CreateMutex(NULL, FALSE, _T("TEST"));
	if (hMutex)
	{
		if (ERROR_ALREADY_EXISTS == ::GetLastError())
		{
			return true;
		}
	}
	return false;
}

int main()
{
	if (IsAlreadyRun())
	{
		printf("Already RUN");
		system("pause");
	}
	else
	{
		printf("NOT Already Run");
		system("pause");
	}
}

4、小結

這個程式實現起來並不難,關鍵是熟悉CreateMutex函式的呼叫。在呼叫CreateMutex函式來建立命名的互斥物件時,注意互斥物件的名稱不要與現有事件、訊號量或者檔案對映物件等名稱相同,否則建立互斥物件會失敗。
在實現過程中,特別要注意,程式一定不要呼叫CloseHandle函式來關閉由CreateMutex函式創建出來的互斥物件的控制代碼,否則會導致互斥物件判斷失敗。因為CloseHandle函式會關閉互斥物件的控制代碼,釋放資源。這樣,系統上便不會存在對應的命名互斥物件了,通過CreateMutex建立的命名互斥物件都是不會重複的。

5、安全小貼士

使用CreateMutex函式建立的互斥物件,可以通過呼叫CloseHandle函式來關閉互斥物件的控制代碼,從屬於它的所有控制代碼都關閉後,就會刪除該物件。
線上程同步操作中, ReleaseMutex函式可以釋放執行緒對互斥物件的控制權。

二、DLL延遲載入

使用延遲載入方式編譯連結可執行檔案

1、實現原理

本程式以載入第三方庫——skin++庫為例進行講解演示。首先匯入skin++庫檔案,然後編碼,最後對程式編譯連結生成exe可執行檔案。使用PE檢視器PEview.exe檢視可執行檔案的匯入表,便可知道可執行檔案必需的DLL檔案了。
這樣做的好處是可以把必需的DLL檔案以資源形式插入到程式中,並使用DLL延遲載入技術延遲載入。在正式呼叫必需的DLL之前,程式都是可以正常執行的。程式可以在這段時間內,把資源中的DLL釋放到本地,等到正式呼叫DLL的時候釋放的檔案就會正確地載入執行。這樣當使用程式的時候,只需把exe檔案傳送給使用者,而不需要附加DLL檔案了,也不需要擔心程式會丟失DLL檔案。
DLL延遲載入的具體設定步驟為:
屬性-->連結器-->輸入-->延遲載入的DLL-->輸入:SkinPPWTL.dll

2、小結

DLL延遲載入技術不需要編碼來實現,只需對VS開發環境設定連結器即可完成。DLL延遲載入技術,配合資源釋放技術,可以使程式變得更加方便易用。

3、安全小貼士

在PE結構中, DLL延遲載入的資訊儲存在ImgDelayDescr延遲匯入表中,可以通過資料目錄DataDirectory中的IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT項獲取延遲匯入表RVA相對的偏移地址和資料大小。

三、資源釋放

病毒木馬之所以會廣泛使用資源釋放技術,是因為它可以使程式變得更簡潔。如果程式額外需要載入一些DLL檔案、文字檔案、圖片檔案,或者其他的音/視訊檔案等,則可以把它們作為資源插入到程式裡,等到程式執行後,再把它們釋放到本地上。這樣做的好處是編譯出來的程式只有一個exe檔案,而不需要附帶其他檔案,因而程式變得很簡潔。只需把exe植入到使用者計算機上,而不需要連同其他檔案一起植入,這降低了被發現的風險。

1、資源插入步驟

首先新建一個資源520.txt

再自定義新增對話方塊

最後,匯入該對話方塊

2、API

FindResource 確定模組中指定型別和名稱的資源所在位置
https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-findresourcea
sizeofResource 獲取指定資源的位元組數
https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-sizeofresource
LoadResource 裝載指定資源到全域性儲存器
https://docs.microsoft.com/en-us/previous-versions/ms915421(v=msdn.10)
LockResource 鎖定資源並得到資源在記憶體中第一個位元組的指標
https://docs.microsoft.com/en-us/previous-versions/aa932898(v=msdn.10)

3、實現原理

首先,通過FindResource定位程式裡的資源,主要是根據"資源型別"和"資源名稱"進行定位,從而獲取資源資訊塊的控制代碼.
其次,根據上面獲取的資源資訊塊的控制代碼,利用sizeofResource獲取資源的大小之後,再通過LoadResource把資源載入程式記憶體中.
接著,通過LockResource鎖定載入到記憶體中的資源,防止程式中的其他操作影響這塊記憶體。其中,返回值就是資源在程序記憶體中的起始地址。
最後,根據資源大小以及程序記憶體的起始地址,可將資源資料讀取出來並儲存為本地檔案。
注意:要必須明確資源所在的模組,要指明所在模組控制代碼並且統一。

4、實現程式碼如下

#include <windows.h>
#include <stdio.h>
#include "resource.h"

void FreeRes_ShowError(char* pszText)
{
	char szErr[MAX_PATH] = { 0 };
	wsprintf(szErr, "%s Error[%d]\n", pszText, ::GetLastError());
}

BOOL FreeMyResource(UINT uiResourceName, char* lpszResourceType, char *lpszSaveFileName)
{
	//獲取指定模組裡的資源
	HRSRC hRsrc = ::FindResource(NULL, MAKEINTRESOURCE(uiResourceName), lpszResourceType);
	if (NULL == hRsrc)
	{
		FreeRes_ShowError("FindResource");
		return FALSE;
	}
	// 獲取資源的大小
	DWORD dwSize = ::SizeofResource(NULL, hRsrc);
	if (0 >= dwSize)
	{
		FreeRes_ShowError("SizeofResource");
		return FALSE;
	}
	// 將資源載入到記憶體裡
	HGLOBAL hGlobal = ::LoadResource(NULL, hRsrc);
	if (NULL == hGlobal)
	{
		FreeRes_ShowError("LoadResource");
		return FALSE;
	}
	// 鎖定資源
	LPVOID lpVoid = ::LockResource(hGlobal);
	if (NULL == lpVoid)
	{
		FreeRes_ShowError("LockResource");
		return FALSE;
	}
	// 儲存資源為檔案
	FILE* fp = NULL;
	fopen_s(&fp, lpszSaveFileName, "wb+");
	if (NULL == fp)
	{
		FreeRes_ShowError("LockResource");
		return FALSE;
	}
	fwrite(lpVoid, sizeof(char), dwSize, fp);
	fclose(fp);

	return TRUE;
}

int main(){
	char szSaveName[MAX_PATH] = "520.txt";
	// 釋放資源
	BOOL bRet = FreeMyResource(IDR_MYRES2, "MYRES", szSaveName);
	if (FALSE == bRet)
	{
		MessageBox(NULL, "Free Resource Error!", "ERROR", MB_OK);
	}
	else
	{
		MessageBox(NULL, "Free Resource OK!", "OK", MB_OK);
	}

	return 0;
   
}
一隻小the bug