當前位置:編程學習大全網 - 源碼下載 - 誰知道進程隱藏技術?

誰知道進程隱藏技術?

進程隱藏技術用得最多的地方就是在病毒和木馬中,因為這些不適合出現在陽光下的程序,越隱蔽生存率就越高。在當今Windows環境下,病毒和木馬流傳得越來越廣泛,讓讀者適當了解這方面的技術可以在防治方面起到積極的作用,技術這種東西就是這樣,大家都知道的“秘技”也就不再是“秘技”了,所以,大家都知道了進程隱藏是怎麽壹回事,進程隱藏起來也就不那麽隱蔽了。

13.4.1 在Windows 9x中隱藏進程

在Windows 9x系列操作系統中,可以通過Kernel32.dll中的壹個未公開函數來完成隱藏功能,這個函數就是RegisterServiceProcess,該函數的功能是將壹個進程註冊為系統服務進程,由於Windows的任務管理器並不列出系統服務進程,所以可以用它來隱藏進程,不過該函數在Windows NT系列中並不存在。

RegisterServiceProcess函數的使用方法是:

invoke RegisterServiceProcess,dwProcessID,dwFlag

dwProcessID指明目標進程的進程ID,參數dwFlag指定是註冊還是撤銷,指定TRUE的話,進程被註冊為系統服務進程,如果指定為FALSE,則進程的屬性恢復為普通進程屬性。

Kernel32.lib導入庫中並沒有這個函數的導入信息,如果要使用這個函數,程序需要自己裝入庫文件並使用GetProcAddress函數獲取入口地址後使用(方法請復習第11章)。所附光盤的Chapter13\HideProcess9x目錄中的例子程序演示了該函數的使用方法。

13.4.2 Windows NT中的遠程線程

在Windows 9x中將進程註冊為系統服務進程就能夠從任務管理器中隱形,但在NT下就不同了。首先,NT下不存在RegisterServiceProcess函數;其次,NT的任務管理器會列出所有的進程(包括系統進程),即使壹個進程將自己的可執行文件放在很隱蔽的目錄中,文件名還是會被任務管理器列出來,所以想讓別人看不見進程是不可能的。

當然,如果不用進程也能運行程序的話,那是最好不過的辦法了,但是不用進程是無法執行文件的。

再從另壹個角度考慮,如果進程顯示的不是正確的名稱呢,這也可以起到掩護作用,如果在DLL中執行我們的代碼,系統報告的進程名稱是裝入DLL的進程的名稱,而不是DLL本身的名稱。

在Windows NT中還有另壹種辦法,那就是使用遠程線程,使用它可以在其他進程中創建壹個線程,由於線程是被所屬進程擁有的,所以任務管理器中列出來的還是所屬進程的名稱。

1. Windows NT的遠程操作函數

有兩個函數可以用來實現上述功能:VirtualAllocEx和CreateRemoteThread。這兩個函數都只能在Windows NT下使用。

VirtualAllocEx函數可以用來在其他進程的地址空間內申請內存,當然申請到的內存也是位於目標進程的地址空間內的,將這個函數和WriteProcessMemory函數配合就可以在目標進程的地址空間中“造”出任何東西來。

在10.1.5節中已經介紹過虛擬內存管理函數VirtualAlloc,VirtualAllocEx函數就是這個函數的擴充,相比之下,VirtualAllocEx函數多了壹個參數hProcess,其他參數定義和使用的方法都和VirtualAlloc函數相同,讀者可以回過頭去查看這些參數的用法。新增的hProcess參數用來指定要申請內存的進程句柄,如果需要在目標進程中使用VirtualAllocEx函數,那麽必須對進程擁有PROCESS_VM_OPERATION權限。

如果內存申請成功,函數返回壹個指針,指向申請到的內存塊,當然這個指針是針對目標進程的地址空間的。如果內存申請失敗,函數返回NULL。

CreateRemoteThread函數用來在其他進程內創建壹個線程,當然創建的線程是運行於目標進程的地址空間內的,它和目標進程自己創建的線程並沒有什麽區別。函數的用法是:

該函數是CreateThread函數的擴充,與CreateThread相比,CreateRemoteThread函數多了壹個hProcess參數,其他所有參數的定義和用法都與CreateThread的參數相同。hProcess用來指定要創建線程的目標進程句柄。註意:lpStartAddress指向的線程函數的地址是位於目標進程的地址空間內的。如果需要在目標進程中使用CreateRemoteThread函數,那麽必須對進程擁有PROCESS_CREATE_THREAD權限。

使用VirtualAllocEx和CreateRemoteThread函數,再配合WriteProcessMemory函數,就能夠讓壹段代碼在其他進程中運行,由於遠程線程是屬於目標進程的,所以在任務管理器中不會產生新的進程,事實上,誰也不會發現列出的某個進程中會多了壹個不屬於它自己控制的線程。整個實現的過程歸納如下:

(1)使用VirtualAllocEx函數在目標進程中申請壹塊內存,內存塊的長度必須能夠容納線程使用的代碼和數據,內存塊的屬性應該是PAGE_EXECUTE_READWRITE,這樣拷貝到內存塊中的代碼就可以被執行。

(2)使用WriteProcessMemory函數將需要在遠程線程中執行的代碼(包括它使用的數據)拷貝到第(1)步申請到的內存塊中。

(3)使用CreateRemoteThread函數創建遠程線程。

2. 遠程線程存在的技術問題

實現遠程線程的框架結構已經搭好了,但是在具體的實現中還有壹些技術問題需要解決,歸納起來主要有兩點:代碼的重定位問題和函數的導入問題。

這時候,A1FC0F4000機器碼還是被解釋為存取00400FFCh地址,而實際的變量地址已經被搬到00800FFCh處了,這就是說,指令存取的是錯誤的地址,所以這段指令要想正常執行,就必須放在00401000h地址開始的地方,如果想搬到別的地方去執行,就必須對訪問全局變量的指令進行修正,這就是重定位的問題

由此可見,如果想把這段指令放到遠程線程中去執行,由於無法保證將代碼放到00401000h處,所以幾乎可以肯定它是不能正常工作的,但是根據代碼最後執行的實際位置來修正某些指令的話,在遠程線程中執行它還是可行的。

對於高級語言來說,重定位問題是個致命的問題,是根本不可能解決的,因為高級語言無法在機器碼級別上進行細微的操作,所以,即使在相對比較低級的C語言中也無法將壹段代碼拷貝到遠程線程中去執行,大部分的教科書和資料在介紹遠程線程的時候,都采用了變通的方法,就是將DLL嵌入到目標進程中去執行。

如Jeffrey Richer的《Windows高級編程指南》中就介紹了使用遠程線程將DLL註入目標進程的方法,其實實現步驟是將需要遠程執行的代碼寫到壹個DLL中,然後在目標進程中申請壹塊內存並將DLL文件名寫入,最後將目標進程地址空間中的LoadLibrary函數當做線程函數來執行,輸入的參數就是前面的DLL文件名,這樣LoadLibrary函數執行到ret的時候,遠程線程結束,但是DLL也被裝入了目標進程中,只要在DLL的入口函數中創建壹個新的線程,就可以執行我們的代碼了,在所附光盤的Chapter13\RemoteThreadDll中的例子演示了這種方法的匯編版本,程序將壹個DLL文件插入到文件管理器Explorer.exe中運行,有興趣的讀者可以自己查看壹下。

雖然DLL文件在目標進程中運行的時候,任務管理器中不會列出DLL文件名,看到的只是目標進程的文件名,但是有壹些工具可以查看壹個進程究竟裝入了哪些DLL文件,通過這些工具還是可以發現進程中的可疑DLL。

要徹底解決這個問題,就必須脫離DLL文件,讓遠程運行的代碼只存在於內存中,這樣就不會有任何的蛛絲馬跡顯示有某個文件被非法裝入,這個問題的關鍵也就是這個重定位問題。但現在Win32匯編程序員可以很驕傲地說“我可以實現它”,因為自定位的代碼正是匯編語言的拿手好戲,在快成為歷史的DOS病毒中,十個病毒中就有九個用到了自定位技術,這些技術完全可以用在這個地方。

自定位技術其實很簡單,觀察下面這段代碼:

在程序開始,首先獲取LoadLibrary,GetProcAddress和GetModuleHandle函數的入口地址,這些地址將在遠程線程中被用來獲取其他API的入口地址。

接下來就是打開Explorer.exe進程的操作,程序通過GetWindowThreadProcessId和OpenProcess函數來完成,函數中使用的窗口句柄是桌面的窗口句柄,因為桌面就是由文件管理器進程創建的,桌面的窗口類是“Progman”,窗口名稱是“Program Manager”,使用FindWindow函數就可以很方便地找到它。在打開進程的時候必須包括對應的權限,PROCESS_CREATE_THREAD權限將允許創建遠程線程,PROCESS_VM_OPERATION權限將允許在目標進程中分配內存並將遠程代碼寫到裏面。

程序使用VirtualAllocEx函數在目標進程中分配內存,在分配內存的時候,內存屬性必須指定為PAGE_EXECUTE_READWRITE,這樣分配到的內存可以有執行和讀寫的權限,分配方式必須指定為MEM_COMMIT,這樣內存才會被提交到物理內存中去。

在分配到內存以後,程序使用WriteProcessMemory將遠程代碼寫入,然後再壹次將LoadLibrary,GetProcAddress和GetModuleHandle函數的地址寫入到遠程代碼的數據段中。並不將這3個函數的地址存放到遠程代碼中壹次性寫入的原因在於:遠程代碼(包括遠程代碼使用的數據)是定義在本地的代碼段中的,而本地的代碼段是只讀的,我們無法在本地對它們進行寫入初始化數據的操作,所以只好采用遠程寫入的方式。

最後,用CreateRemoteThread函數創建遠程線程後就萬事大吉了。編譯鏈接以後運行可執行文件可看到,窗口正常出現了,壹眼看上去,這個窗口和別的窗口沒有任何不同!但是在任務管理器中卻沒有多出任何新的進程。

假如遠程線程不是這樣“招搖過市”地創建了壹個窗口,而是在後臺偷偷地運行的話,大家能不能從各種蛛絲馬跡來發現它的存在呢?反正筆者是找不到它的,因為它僅存在於目標進程的內存中,並不對應任何磁盤文件,當遠程線程被執行的時候,惟壹可以發現的就是Explorer.exe進程中的活動線程多了壹個,使用的內存多了壹點而已,但是活動線程用工具軟件查看也只能看到壹個線程ID,又怎麽知道這個線程不是Explorer.exe進程自己的呢?

以上代碼用在不合適的地方可能產生危害,筆者第壹次公開這段代碼,其目的就是希望能對有害代碼的防治起到積極的作用,請讀者負責任地使用這段代碼。

  • 上一篇:股票神奇九轉是什麽意思神奇九轉準確嗎
  • 下一篇:蘋果筆記本上面安裝雙系統時顯示"需要64為windows8或更高版本iso文件"時怎麽回事
  • copyright 2024編程學習大全網