黑客如何用線程注射技術隱藏自己的病毒

隱藏是病毒的天性,在業界對病毒的定義裏,“隱蔽性”就是病毒的一個最基本特徵,任何病毒都希望在被感染的計算機中隱藏起來不被發現,因爲病毒都只 有在不被發現的情況下,才能實施其破壞行爲。爲了達到這個目的,許多病毒使用了各種不同的技術來躲避反病毒軟件的檢驗,這樣就產生了各種各樣令普通用戶頭 痛的病毒隱藏形式。由於木馬後門的行爲特徵已具備病毒條件,因此這裏把木馬後門也統一歸納爲病毒來描述。

開山鼻祖:隱藏窗口 & 隱藏進程 & 隱藏文件

在計算機流行的早期,計算機病毒和木馬後門等危害程序在普通用戶範圍的普及並不是很廣泛,這個時期的用戶羣對計算機和網絡安全的防範意識可以說 是幾乎沒有的,普通用戶的系統也多爲脆弱的Windows 95/98系列和電話線撥號的慢速網絡,而那一段時間正是外國木馬“bo”和國產木馬雛形“冰河”、“netspy”等在如今看來各方面技術都頗爲簡單的 遠程控制軟件大行其道的黃金時期,很多用戶根本就沒有防火牆和殺毒軟件(即使有,也是以殺cih的爲主),即使遠方的黑客把用戶的計算機翻了個底朝天,用 戶也不會有所察覺,這一時期接觸此類技術的人相對較少,因此並未造成如今這個病毒到處蔓延的局面。

因爲這個階段國內用戶的機器環境仍然以Windows 9x爲主流,所以病毒編寫者們並不需要消耗太多的腦筋就可以做到讓病毒悄無聲息運行的效果,並讓它在alt+del+ctrl呼出的任務管理器中不可見。

我們都知道,在Windows下運行的程序界面都被定義爲“窗口”,程序通過這個途徑與用戶產生交互,每個完整的程序都必須擁有至少一個窗口, 但是如果編寫者將這個窗口在運行期間設置爲“不可見”呢?這樣一來,用戶就不會察覺到這個程序在桌面上運行了,但是如果有一定經驗的用戶打開任務管理器, 他就會因爲發現系統裏多出來的進程而產生懷疑,因此病毒編寫者在這個時期採取了初級形式的隱藏手段:隱藏進程。

其實所謂隱藏進程,是利用微軟未公開的一個api(application programming interface,應用程序接口)函數“registerserviceprocess”將自身註冊爲“服務進程”,而恰巧Windows 9x中的任務管理器是不會顯示此類進程的,結果就被病毒鑽了空子,讓“冰河”等木馬在國內大部分普通用戶的機器上安家落戶。

而早期後門技術裏,還有一個最基本的行爲就是隱藏文件,與今天的各種隱藏手段相比,它可謂是“不入流”級別了——這裏提到的“隱藏”,就是簡單 的將文件屬性設置爲“隱藏”而已,除此之外,再無別的保護手段了,然而,由於系統設計時爲了避免初學者胡亂刪除文件而默認“不顯示系統和隱藏文件”的做法 (到了Windows 2000/xp時代,這個做法更升級到“隱藏受保護的系統文件”了),卻恰好給這些病毒提供了天然的隱身場所——大部分對電腦操作不熟悉的用戶根本不知道 “隱藏文件”的含義,更別提設置爲“顯示所有文件”了,在那個安全軟件廠商剛開始探索市場的時代,用戶更是不會留意太多安全產品及其實際含義,因而這個時 期成了各種初期木馬技術發展的重要階段,利用這種手段製作的木馬被統稱爲“第一代木馬”。

以現在的技術和眼光看來,這些早期技術作品的發現和清理是相對較簡單的了,因爲它們採用的“進程隱藏”技術在NT體系上的Windows2000/xp/2003等操作系統上已經無效了,直接使用系統自帶的任務管理器便能發現和迅速終止進程運行,而後在“控制面板” ——“文件夾選項”裏面設置“顯示所有文件”和取消“隱藏受保護的系統文件”,就能發現那個被隱藏起來的木馬程序了。對於Windows 9x用戶,使用任意一款第三方的進程管理工具如“Windows優化大師”的進程管理組件即可輕鬆發現。

繼續發展:使用線程注射技術的dll木馬

雖然現在使用“線程注射”的木馬病毒和流氓軟件已經遍地開花了,但是從那個混沌時代經歷過來的人都不會忘記首個採用“線程注射”的dll木馬“廣外幽靈”在當時所帶來的恐懼,“線程注射”到底是種什麼東西呢?下面就讓我們來詳細講解一下。

首先,用戶可能不會了解“線程”(thread)的意思,而要講解“線程”,就不能不先提到“進程”(process)的概念。許多剛接觸計算 機的用戶無法理解“進程”是什麼東西:常常聽到高手說打開任務管理器關閉某某進程,但是一看到任務管理器列表裏的一堆東西,頭就大了。許多用戶知道使用任 務管理器關閉一些失去響應的任務,但是如果某個任務沒有在“應用程序”列表裏出現,用戶就不知所措了。到底什麼是“進程”呢?“進程”是指一個可執行文件 在運行期間請求系統在內存裏開闢給它的數據信息塊,系統通過控制這個數據塊爲運行中的程序提供數據交換和決定程序生存期限,任何程序都必須擁有至少一個進 程,否則它不被系統承認。

進程從某一方面而言就是可執行文件把自身從存儲介質複製在內存中的映像,它通常和某個在磁盤上的文件保持着對應關係,一個完整的進程信息包括很 多方面的數據,我們使用進程查看工具看到的“應用程序”選項卡包含的是進程的標題,而“進程”選項卡包含的是進程文件名、進程標識符、佔用內存等,其中 “進程文件名”和“進程標識符”是必須掌握的關鍵,“進程標識符”是系統分配給進程內存空間時指定的唯一數字,進程從載入內存到結束運行的期間裏這個數字 都是保持不變的,而“進程文件名”則是對應着的介質存儲文件名稱,根據“進程文件名”我們就可以找到最初的可執行文件位置。

任務管理器的“應用程序”項裏列出來的“任務”,是指進程在桌面上顯示出來的窗口對象,例如用戶打開word 2003撰寫文檔,它的進程“winword.exe”會創建一個在桌面上顯示的前臺窗口,這個窗口就是任務管理器裏看得見的“任務”了,而實際上真正在 運行的是進程“winword.exe”。並不是所有的進程都會在任務管理器裏留下“任務”的,像QQ、msn 和所有後臺程序,它們並不會在任務列表裏出現,但是你會在進程列表裏找到它們,如果要它們在任務列表裏出現該怎麼辦呢?只要讓它們產生一個在桌面上出現的 窗體就可以了,隨便打開一個好友聊天,就會發現任務列表裏終於出現了qq的任務。因此,真正科學的終止程序執行方案是針對“進程”來結束程序的運行,而不 是在任務列表裏關閉程序,因爲木馬作者們是不會讓自己的木馬在任務列表裏出現的,但是進程列表裏一般人都是逃不過的。

而“線程”,則是在一個進程裏產生的多個執行進度實例,舉個簡單例子,一個網絡文件傳輸程序如果只有一個線程(單線程)運作,那麼它的執行效率 會非常低下,因爲它既需要從網絡上讀取文件數據,又需要把文件保存到磁盤,同時還需要繪製當前傳輸進度條,由於在代碼的角度裏這些操作只能一條條的順序執 行,程序就不能很好的做到在保存數據的同時繪製傳輸進度條,即使程序員將其勉強湊到一塊執行,在用戶方面看來,這個程序的響應會非常緩慢甚至直接崩潰,而 “多線程”技術則是爲了解決這種問題而產生的,採用“多線程”技術編寫的應用程序在運行時可以產生多個同時執行的操作實例,例如一個採用“多線程”技術的 網絡文件傳輸程序就能同時分出三個進度來同時執行網絡數據傳輸、文件保存操作和繪製傳輸進度條的操作,於是在用戶看來,這個程序運行非常流暢,這就是線程 的作用。在程序運行時,只能產生一個進程,但是在這個進程的內存空間(系統爲程序能正常執行而開闢的獨立內存領域)裏,可以產生多個線程,其中至少有一個 默認的線程,被稱爲“主線程”,它是程序主要代碼的運行部分。

那麼,“線程注射”又是什麼含義呢?其實它的全稱是“遠程線程注射”(remotethread injection),通常情況下,各個進程的內存空間是不可以相互訪問的,這也是爲程序能夠穩定運行打下基礎,這個訪問限制讓所有進程之間互相獨立,這 樣一來,任何一個非系統關鍵進程發生崩潰時都不會影響到其他內存空間裏的進程執行,從而使nt架構的穩定性遠遠高於win9x架構。但是在一些特定的場合 裏,必須讓進程之間可以互相訪問和管理,這就是“遠程線程”技術的初衷,這個技術實現了進程之間的跨內存空間訪問,其核心是產生一個特殊的線程,這個線程 能夠將一段執行代碼連接到另一個進程所處的內存空間裏,作爲另一個進程的其中一個非核心線程來運行,從而達到交換數據的目的,這個連接的過程被稱爲“注 射”(injection)。遠程線程技術好比一棵寄生在大樹上的蔓藤,一旦目標進程被注射,這段新生的線程就成爲目標進程的一部分代碼了,只要目標進程 不被終止,原進程無論是否還在運行都不會再影響到執行結果了。

與“線程注射”離不開的是“hook”技術,這個“hook”,又是什麼呢?其官方定義如下:

鉤子(hook),是Windows消息處理機制的一個平臺,應用程序可以在上面設置子程以監視指定窗口的某種消息,而且所監視的窗口可以是其他進程所創建的。當消息到達後,在目標窗口處理函數之前處理它。鉤子機制允許應用程序截獲處理window消息或特定事件。

鉤子實際上是一個處理消息的程序段,通過系統調用,把它掛入系統。每當特定的消息發出,在沒有到達目的窗口前,鉤子程序就先捕獲該消息,亦即鉤 子函數先得到控制權。這時鉤子函數即可以加工處理(改變)該消息,也可以不作處理而繼續傳遞該消息,還可以強制結束消息的傳遞。

在這裏,木馬編寫者首先把一個實際爲木馬主體的dll文件載入內存,然後通過“線程注射”技術將其注入其他進程的內存空間,最後這個dll裏的 代碼就成爲其他進程的一部分來實現了自身的隱藏執行,通過調用“hook”機制,這個dll木馬便實現了監視用戶的輸入輸出操作,截取有用的資料等操作。 這種木馬的實際執行體是一個dll文件,由於Windows系統自身就包含着大量的dll文件,誰也無法一眼看出哪個dll文件不是系統自帶的,所以這種 木馬的隱蔽性又提高了一級,而且它的執行方式也更加隱蔽,這是由Windows系統自身特性決定的,Windows自身就是大量使用dll的系統,許多 dll文件在啓動時便被相關的應用程序加載進內存裏執行了,可是有誰在進程裏直接看到過某個dll在運行的?因爲系統是把dll視爲一種模塊性質的執行體 來調用的,它內部只包含了一堆以函數形式輸出的模塊,也就是說每個dll都需要由一個用到它的某個函數的exe來加載,當dll裏的函數執行完畢後就會返 回一個運行結果給調用它的exe,然後dll進程退出內存結束這次執行過程,這就是標準的dll運行週期,而採用了“線程注射”技術的dll則不是這樣, 它們自身雖然也是導出函數,但是它們的代碼是具備執行邏輯的,這種模塊就像一個普通exe,只是它不能直接由自身啓動,而是需要有一個特殊作用的程序(稱 爲加載者)產生的進程把這個dll的主體函數載入內存中執行,從而讓它成爲一個運行中的木馬程序。瞭解Windows的用戶都知道,模塊是緊緊依賴於進程的,調用了某個模塊的進程一旦退出執行,其加載的dll模塊也就被迫終止了,但是在 dll木馬裏,這個情況是不會因爲最早啓動的exe被終止而發生的,因爲它使用了“遠程線程注射”技術,所以,在用戶發現異常時,dll木馬早就不知道被 注入哪個正常進程裏了,即使用戶發現了這個木馬dll,也無法把它終止,因爲要關閉它就必須在那麼多的系統進程裏找到被它注射的進程,並將其終止,對一般 用戶來說,這是個不可能完成的任務。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章