2010年3月26日 星期五

[知識]惡意程式的隱形斗蓬-rootkit

駭客七號
惡意程式的隱形斗蓬-rootkit
文/圖 吳俊達.責任編輯/陳啟川

「山啊BOT、土地BOT,現在連海阿要BOT」,這是電影「海角七號」裡的對話,意思指地方建設什麼都BOT出去了,利益都被財團瓜分,只剩下一些檢垃圾的差事留下來給地方的一段對話。有時聯想在資安的世界裡不也到處充滿著「BOT」,個人機密資料都讓駭客偷走,而剩下一堆惡意程式在用戶端的電腦中,以下將就入侵攻擊常見的rootkit技術為讀者做一詳盡的介紹。


看不見,可是它依舊存在──這不是在形容七月半的阿飄,而是在說一項你我電腦上隨時都有可能發生的事,rootkit。
2005年包括Celine Dion (席琳狄翁)在內的19張SONY發行的CD因為含有防盜版技術,而意外地造成「買 CD 唱片,送駭客隱形斗蓬」的安全意外。這個始作俑者就是BREPLIBOT特洛伊木馬程式家族,其利用Sony唱片防拷軟體採用的Rootkit工具留下的後門來作自我隱藏,使得病毒不易被追蹤。也使得有些公司頒出禁令:上班時間不準聽CD,免得公司被駭客入侵。
廣義來說,rootkit其實是一項技術,用來隱藏其他行程、檔案或者網路使用者。至於為什麼要隱藏這些玩意,最初的原因其實相當簡單,各位可以想像,如果有天你進行檔案備份,把一些重要的系統資訊存在備份目錄裡,你勢必不想因為哪天手賤就把這些檔案一併刪除了。因此,rootkit出於善意的用途,便能適當的隱藏你要保護的檔案。
然而駭客也可以藉由使用rootkit,隱藏他們在你電腦上的一舉一動,例如隱藏他們產生的惡意行程,進而竊取你電腦的資訊而不被發現;隱藏他們產生的惡意檔案,進而避開防毒軟體掃描而不會被刪除。這種種用途,都說明了rootkit這柄雙面刃給予駭客們的便利性,讓許多Bot蠕蟲、間諜軟體都利用這套工具來打造隱形斗篷。
rootkit的歷史
早在1990年的時候,rootkit的理念就已經被提出來了,但一直到1996年,第一隻Linux rootkit才正式出現下世人面前。當時那只rootkit只是簡單的替換掉Linux上頭的ps,login,跟netstat等執行檔。這些執行檔的功能,多半是用來顯示目前系統中有哪些行程正在執行,或者哪些網路行為正在運作。而這只Linux rootkit替換這些系統執行檔後,就會將它所指定的惡意行程隱藏起來,不被使用者發現。儘管這只rootkit很快就被人們利用檔案驗証碼,檢查該執行檔是否被替換過而解決了,但在這以後,越來越多的rootkit技術以及實作迅速出現。以最為人熟知的作業系統Windows來說,從2002年第一只在Windows 上出現的rootkit「ierk8243.sys」面世以來,每年都有數以百計的rootkit出現。根據2006年微軟惡意程式移除工具提出的報告,570萬台電腦上,就有14%的電腦被安裝過rootkit。
惡名昭彰的Sony事件
當時Sony BMG在他們發行的音樂光碟裡,加入了rootkit的技術。最初的目的只是為了保護他們的音樂不被盜拷,但由於Sony BMG的工程師們小瞧了使用rootkit會帶來的影響,他們把所有名稱前行是「$sys$」的檔案,都進行了隱藏。換句話說,如果你把電腦上的notepad.exe改名為$sys$notepad.exe,那麼在這只rootkit被移除之前,你的notepad將會暫時消失。
這件事曝光之後,不但很快就被駭客們用來隱藏他們的惡意檔案,Sony BMG更因此承受了龐大的商譽損失。只不過,用「從那裡跌倒,就從那裡再跌倒」這句話來形容Sony,恐怕是在適合不過。
2007年8月,Sony在他們發行的Sony’s MicroVault USB drives裡頭,又用上了rootkit的技術。這次主要是因為Sony這款USB提供了指紋辨識能力,為了保護指紋辨識的內容資料,他們將這些資料全放在同一個目錄裡,並將這個目錄進行了隱藏,可惜,駭客們見到了這樣一個大漏洞,哪還有不鑽的道理,於是許多惡意軟體就將他們的檔案放置在這個隱藏目錄,從而躲避過了防毒軟體的掃描。
綜合上面的敘述我們可以得知,rootkit的技術跟觀念已逐漸成為下一波駭客們關注的重點。現下,就讓我們更深一層來探討rootkit的技術以及應用。
rootkit使用的技術
有念過計算機組織的讀者必定知道,CPU在執行指令時有著不同的特權等級 (privilege level)。現代的作業系統也採用了這個理念,在執行較重要的指令 (例如作業系統核心) 或是存取較隱密關鍵的資料,都必須在CPU為高特權等級 (kernel mode) 時才能通行;反之,若是一般的使用者程式及資料則沒此限制 (user mode),以下將就分別對rootkit在user mode和kernel mode使用的技巧一一介紹。
user mode rootkit
user mode rootkit在實作技術上難度不高,不具備系統核心開發理念的程式設計者都可以輕易的達成。user mode rootkit的流程,基本上都是在正常程式呼叫某函式時,先將執行權轉移到rootkit本身,rootkit再去呼叫真正的函式取得執行結果,並對其結果做更改或是取得權限,以達到其目的。
目前有兩種熱門方法能在user mode將程式呼叫時的執行權轉移,一種是IAT (Import Address Table) hook,另一種是Inline Function Patch。

Import Address Table Hooking (IAT Hooking)

當一個應用程式使用Win32 API時,會需要知道這些API的address,很多應用程式把這些address紀錄在IAT內。當這些應用程式需要使用Win32 API時就去IAT內查詢這些Win32 API的address然後再執行。

IAT Hooking流程圖。


IAT Hooking很容易實作,OS也時常使用這樣的模式,但其缺點是容易被偵測到。不過,雖然容易偵測,卻不容易判斷是否真的為惡意軟體利用rootkit進行IAT Hook。此外若應用程式內部使用Win32 API時是使用late binding的話 (使用 LoadLibrary & GetProcAddress),此時IAT Hooking也會失效。

Inline Function Patch

這個模式比IAT Hooking應用更廣泛,不會被late binding影響,因為它是直接去修改目標程式在RAM中的byte code。因此不管應用程式怎么取得Win32 API的address,Inline Function Patch的機制始終有效。下圖2為Inline Function Patch簡單的示意圖。
Inline Function Patch流程圖。


Caller function呼叫被Patch的Function (FindFirstFile)。因Function的第一個instruction被rootkit替換成jmp 0x2c3d,所以程式接著執行到0x2c3d。Address 0x2c3d就是rootkit想要使用者執行的程式碼。待rootkit執行完後再回到原先的Function繼續執行下去。最後由Function將rootkit篩選過的結果回傳給Caller Function。
DLL植入 (DLL injection)
至此,聰明的讀者一定發現到了,user mode rootkit最主要的精神便是透過修改正常Process呼叫API的順序,將自己的惡意程式碼插入到呼叫順序的中間,去影響正常Process的運作或更改API的結果;或是直接給函式打「patch」以得到類似的結果。但事實上如何對其它Process進行修改?
若你曾在Windows下開發過程式,必然知道所有的Process都有自己的memory address space。例如0x12345在Process A中可能是存放字串"Foo",但同樣的位址在Process B裡卻是字串"Bar",此乃因為Windows的虛擬記憶體 (Virtual memory) 機制,讓每個Process都認為自己是系統上唯一的一個Process。所以Process之間是兩條平行線,沒有交集 (不考慮Process溝通機制及系統核心部份)
所以若我們想系統上其他Process做修改,一定得進入它們的memory address space。一般利用的手法便是DLL injection,而幾個常用的技巧介紹如下︰

AppInit_DLLs registry

Windows作業系統使用登錄(Registry)來做記錄系統設定及組態,在登錄中有一個特別的機碼(Key)可以讓使用者輕易的達到DLL植入。這個機碼的路徑是HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows,在此機碼下有一特別的值(Value)名稱叫做AppInit_DLLs,它的資料型態為一字串值(REG_SZ),系統預設值是長度為零的空字串。使用者可以指定任意DLL的路徑於此機碼的值內,舉例來說︰C:\Windows\System32\MyDll.dll。你一定會很好奇,當此機碼及值被設定之後,Windows作業系統會有什麼改變呢?
當此機碼及值被設定之後,只要有任何的Process載入User32.dll,首先User32.dll會被映射到該Process的記憶體空間裡,接著User32.dll會收到DLL_PROCESS_ATTACH的系統通知,此時User32.dll會去讀取本節前面所提到的機碼及值,並且呼叫LoadLibrary系統函式來一並載入指定的DLL,此時DLL植入的目的也就達到了。用此方法來達到DLL植入是很容易的一件事,但這種方法也有一些缺點。
1. PInit_DLLs值被設定之後,之後載入User32.dll的Process才會被DLL植入,也就是說,既有已執行的Process並不會受影響。同樣的,若已經被DLL植入的Process,就算APPInit_DLLs值被刪除,也不會受到影響。
2. 此種方法只能用來植入使用User32.dll的Process,所有的圖形化使用者介面 (GUI) 程式都會使用到User32.dll,但是console程式就不一定會使用到User32.dll。
系統中通常有多個Process存在,但用此種方法無法指定DLL植入的對象。所以用這種模式做DLL植入要很小心,因為會影響到所有的圖形化使用者介面程式。

indowsHookEx

Windows中的程式是透過資訊(message)來互相溝通的,例如鍵盤或滑鼠的事件,或是視窗間主動傳遞資訊。而Windows本身亦提供了一個正式的方法讓程式設定自己的Hook,以下程式1是SetWindowsHookEx的函式宣告︰

可以看到此函式有四個參數,第一個參數是指定Hook的類別,例如,若指定為WH_KEYBOARD,代表想監聽鍵盤的message。
當idHook所指定的事件發生時,則第二個參數lpfn所指向的函式將會被呼叫,若dwThreadId為0或是自己本身以外的Process,則lpfn必須指向一個DLL所匯出 (export) 的某個函式。
第三個參數為包含lpfn的DLL handle,若dwThreadId為自己本身Process所包含的Thread,則此參數必須為NULL。
第四個參數可指定任一Thread (Thread) 的識別(ID),則Hook只會作用在該Thread上,若其值為0,代表Hook會作用系統中所有Thread上。 
以下程式2是一段使用SetWindowsHookEx的範例程式︰

在此時DLL植入的目的也就達成了。使用SetWindowsHookEx有幾個優點︰
1. 可以指定要hook的Thread。

2. 可以呼叫系統函式UnhookWindowsHookEx將hook移除。
3. 在自訂的hook函式中(也就是範例的SysMessageProc),可以用CallNextHookEx函式將執行權交給下一個設定hook的函式。

CreateRemoteThread

Windows有一個函式可以讓某一Process在本身以外的Process中啟始一條Thread,這個函式叫做CreateRemoteThread。以下程式3是它的函式宣告︰


這個函式看起來參數很多,但只有幾個是比較重要的,若讀者有興趣,可參閱MSDN得到完整的資訊。第一個參數hProcess是由OpenProcess或是CreateProcess所得到,其可以指定要在那一個Process啟始新的Thread。第四個參數lpStartAddress指定了要被啟始Thread的起始函式位址,此函式必須存在於hProcess所指定的Process中。第五個參數則是當新Thread開始lpStartAddress函式時,會一並傳入的參數。
若A Process要用CreateRemoteThread對B執行序達成DLL植入的目的,則要利用B執行序當中Loadlibrary函式來載入指定的DLL,詳細的範例程式如下程式4︰


此時DLL植入的目的已達到。
user mode rootkit小結
介紹到這裡,讀者應已對user mode rootkit使用的技巧有初步了解 。總結一下,惡意程式先使用DLL injection技巧 (AppInit_DLL registry、SetWindowsHookEx函式,及CreateRemoteThread函式),將自己的DLL植入到別的Process,再利用IAT hooking或Inline Function Path的模式,影響正常Process執行的順序,來達到目的。要實作user mode rootkit的技術門檻不高,所需撰寫的程式碼並不會很多。雖然user mode rootkit簡單好作,但它也有先天上致命的缺陷,那就是容易被偵測出來,市面上大多數的Anti-rootkit軟體都具有核心驅動程式 (Kernel Driver),可以輕易的偵測出user mode rootkit的存在。而下期我們將就kernel mode使用的技巧繼續介紹。



【原文刊載於RUN!PC雜誌:2008年11月號】

原文網址:http://www.runpc.com.tw/content/main_content.aspx?mgo=178&fid=G03

相關文章 :

0 意見: