Windows黑客編程技術詳解 --2.1 運行單一實例
本文經原作者授權,節選自《Windows黑客編程技術詳解》一書。文末有福利哦!!
-----------------------------------------------------------------
第二章:基礎技術
本章內容是在病毒木馬中最爲常用、最爲基礎的技術,技術變化不大,所以不對每個技術單獨歸類,而是統一劃分到本章。作爲本書病毒木馬技術詳解的開篇,本章的目的是引領讀者由淺入深、循序漸進地瞭解病毒木馬的各類實現技術。
大多數的病毒木馬在成功植入用戶計算機之後,在執行核心惡意代碼之前,會先進行初始化操作。這些操作對應本章的3個基礎技術點:運行單一實例、DLL延遲加載以及資源釋放。
2.1 運行單一實例
在使用各種手段將病毒木馬植入到用戶計算機後,它也會使用渾身解數來使用戶激活它。但是,如果病毒木馬被多次重複運行,系統中會存在多份病毒木馬的進程,那麼,這就有可能增加暴露的風險。所以,要想解決上述問題,就要確保系統上只運行一個病毒木馬的進程實例。
確保運行一個進程實例的實現方法有很多,它可以通過掃描進程列表來實現,可以通過枚舉程序窗口的方式來實現,也可以通過共享全局變量來實現。下面介紹一種使用廣泛而且簡單的方法,即通過創建系統命名互斥對象的方式來實現。
2.1.1 函數介紹 CreateMutex函數
創建或打開一個已命名或未命名的互斥對象。
函數聲明
HANDLE WINAPI CreateMutex(
_In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes,
_In_ BOOL bInitialOwner,
_In_opt_LPCTSTR lpName)
參數
lpMutexAttributes [in, optional]
指向SECURITY_ATTRIBUTES結構的指針。如果此參數爲NULL,則該句柄不能由子進程繼承。
bInitialOwner [in]
如果此值爲TRUE並且調用者創建了互斥鎖,則調用線程將獲得互斥鎖對象的初始所有權。否則,調用線程不會獲得互斥鎖的所有權。
lpName [in, optional]
互斥對象的名稱。該名稱僅限於MAX_PATH字符,名稱區分大小寫。如果lpName爲NULL,則會創建不帶名稱的互斥對象。
如果lpName與現有事件、信號量、等待定時器、作業或文件映射對象的名稱匹配,且這些對象共享相同的名稱空間,則該函數將失敗,並且GetLastError函數返回ERROR_INVALID_ HANDLE。
返回值
如果函數成功,則返回值是新創建的互斥對象的句柄。
如果函數失敗,則返回值爲NULL。要獲得擴展的錯誤信息,請調用GetLastError。
如果互斥鎖是一個已命名的互斥鎖,並且該對象在此函數調用之前就存在,則返回值是現有對象的句柄,GetLastError返回ERROR_ALREADY_EXISTS。
2.1.2 實現原理
通常情況下,系統中的進程是相互獨立的,每個進程都擁有自己的獨立資源和地址空間,進程間互不影響。所以,同一個程序可以重複運行,但系統上的進程互不影響。但是,在一些特殊情況下,程序在系統上需要只保存一份進程實例,這就引出了進程互斥的問題。
微軟提供了CreateMutex函數來創建或者打開一個已命名或未命名的互斥對象,程序在每次運行的時候,通過判斷系統中是否存在相同命名的互斥對象來確定程序是否重複運行。
CreateMutex函數一共有3個參數,第一個參數表示互斥對象的安全設置,是一個指向SECURITY_ATTRIBUTES結構的指針,在該程序中直接設置爲NULL即可。第二個參數表示線程是否獲得互斥鎖對象的初始所有權,在該程序中,無論該參數爲TRUE還是FALSE,均不影響程序的正常運行。第三個參數表示互斥對象的名稱,對於通過互斥對象來判斷進程實例是否重複運行的程序來說,該參數一定要設置,而且要保證設置名稱的唯一性。
程序的判斷原理是通過CreateMutex函數創建一個命名的互斥對象,如果對象創建成功,而且通過調用GetLastError函數獲取的返回碼爲ERROR_ALREADY_EXISTS,則表示該命名互斥對象存在,即程序重複運行。否則,認爲程序是首次運行。
2.1.3 編碼實現
// 判斷是否重複運行
BOOL IsAlreadyRun()
{
HANDLE hMutex = NULL;
hMutex = ::CreateMutex( NULL, FALSE, "TEST");
if(hMutex)
{
if(ERROR_ALREADY_EXISTS == ::GetLastError())
{
returnTRUE;
}
}
returnFALSE;
}
2.1.4 測試
直接運行上面的程序。第一次運行的時候,程序提示“NOT Already Run!”,如圖2-1所示,意思是系統中沒有運行該實例。繼續雙擊執行程序,這次程序提示“Already Run!!!!”,如圖2-2所示,意思是系統上已經存在該實例且正在運行。所以,程序成功地判斷出程序是否重複運行。
2.1.5 小結
這個程序實現起來並不難,關鍵是熟悉CreateMutex函數的調用。在調用CreateMutex函數來創建命名的互斥對象時,注意互斥對象的名稱不要與現有事件、信號量或者文件映射對象等名稱相同,否則創建互斥對象會失敗。
在實現過程中,特別要注意,程序一定不要調用CloseHandle函數來關閉由CreateMutex函數創建出來的互斥對象的句柄,否則會導致互斥對象判斷失敗。因爲CloseHandle函數會關閉互斥對象的句柄,釋放資源。這樣,系統上便不會存在對應的命名互斥對象了,通過CreateMutex創建的命名互斥對象都是不會重複的。
安全小貼士
使用CreateMutex函數創建的互斥對象,可以通過調用CloseHandle函數來關閉互斥對象的句柄,從屬於它的所有句柄都關閉後,就會刪除該對象。
在線程同步操作中,ReleaseMutex函數可以釋放線程對互斥對象的控制權。
-------------------------------------------
福利時間到了
說明:
在上一篇文章中我們發佈了這本書的第一章(Windows黑客編程技術詳解 --第一章:開發環境(內含送書福利)),第一章送出三本書。同時第二章(2.1到2.3節),我們每一節仍然會送出一本書,也就是參與本節的活動,會增加你的中獎概率。
本篇文章 會送出一本書,參與辦法如下(微信訂閱號打開請忽略1,2,3步驟):
- 找到本篇文章並打開
- 點擊文章下的“在看”按鈕。
- 文章下留言,談體會
- 拉你的朋友過來爲你的留言點贊 ------------------------------------------------------ 明天我們繼續推送本書第二章相關內容