廣告廣告
  加入我的最愛 設為首頁 風格修改
首頁 首尾
 手機版   訂閱   地圖  簡體 
您是第 1900 個閱讀者
 
發表文章 發表投票 回覆文章
  可列印版   加為IE收藏   收藏主題   上一主題 | 下一主題   
upside 手機 葫蘆墩家族
個人頭像
個人文章 個人相簿 個人日記 個人地圖
特殊貢獻獎 社區建設獎 優秀管理員勳章
頭銜:反病毒 反詐騙 反虐犬   反病毒 反詐騙 反虐犬  
版主
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片
推文 x0
[資訊教學] 內核級Rootkit技術入門
內核級Rootkit技術入門

Rootkit是一種奇特的程序,它具有隱身功能:無論靜止時(作爲文件存在),還是活動時,(作爲進程存在),都不會被察覺。換句話說,這種程序可能一直存在於我們的計算機中,但我們卻渾然不知,這一功能正是許多人夢寐以求的——不論是計算機黑客,還是計算機取證人員。黑客可以在入侵後置入Rootkit,秘密地窺探敏感信息,或等待時機,伺機而動;取證人員也可以利用Rootkit實時監控嫌疑人員的不法行爲,它不僅能搜集證據,還有利於及時采取行動。而本文的目的,就是同讀者一起踏上Windows內核級Rootkit之旅!

一、背景知識

我們通常所說的智能機器,大至超級計算機,中到個人PC,小至智能手機,通常都有兩部分組成:硬件和軟件。並且,設備的智能是通過軟件來實現的。所有軟件中,有一種是必不可少的,那就是操作係統。操作係統可以簡單理解爲一組高度複用的核心程序,一方面,它要管理低層的硬件設備,另一方面,爲上層其它程序提供一個良好的運行環境。真是同人不同命,同爲軟件,操作係統卻享有至高無上的特權:它不僅管理硬件,而且其他所有軟件也都受制於它。

因爲在應用程序和硬件之間隔著操作係統,所以應用程序不能直接訪問硬件,而是通過調用操作係統提供的接口來使用硬件。也就是說,對應用程序而言,硬件是不可見的。當然,凡事是沒有絕對的,應用程序繞過操作係統來直接訪問硬件也不是不可能的,但這樣做會付出高昂的代價。設想一個軟件開發商在開發一款功能豐富的軟件,功能本身就夠他頭痛得了,現在他還得操心某個數據在某個磁道的某個簇上,某個字符在某品牌顯示器上的顔色的二進制代碼等等繁瑣的事情,不用說財力和物力,單說開發周期就是無法容忍的。所以,現在的應用程序都是使用操作係統提供的簡單明了的服務來訪問係統的,因爲畢竟沒有誰願意自討苦吃。

二、內核的主要功能

從上文中我們已經了解,內核在係統中處於核心樞紐的地位,下面我們具體介紹內核中與Rootkit緊密相關的幾個主要功能,更重要的是這些功能對Rootkit的意義所在:

進程管理。進程可以簡單理解爲運行中的程序,它需要占用內存、CPU時間等係統資源。現在的操作係統大多支持多用戶多任務,也就是說係統要並行運行多個程序。爲此,內核不僅要有專門代碼來負責爲進程或線程分配CPU時間,另一方面還要開辟一段內存區域存放用來記錄這些進程詳細情況的數據結構。內核是怎麽知道係統中有多少進程、各進程的狀態等信息的?就是通過這些數據結構,換句話說它們就是內核感知進程存在的依據。因此,只要修改這些數據結構,就能達到隱藏進程的目的。

文件訪問。文件係統是操作係統提供的最爲重要的功能之一。內核中的驅動程序把設備的柱面、扇區等原始結構抽象成爲更加易用的文件係統,並提供一個一致的接口供上層程序調用。也就是說,這部分代碼完全控制著對硬盤的訪問,通過修改內核的這部分代碼,攻擊者能夠隱藏文件和目錄。

安全控制。對大部分操作係統來說,因爲係統中同時存在多個進程,爲了避免各進程之間發生沖突,內核必須對各進程實施有效的隔離措施。比如,在MS-Windows係統中,每個進程都被強制規定了具體的權限和單獨的內存範圍。因此,對攻擊者而言,只要對內核中負責安全事務的代碼稍事修改,整個安全機制就會全線崩潰。

內存管理。現在的硬件平台(比如英特爾的奔騰係列處理器)的內存管理機制已經複雜到可以將一個內存地址轉換成多個物理地址的地步。舉例來說,進程A按照地址0x0030030讀取內存,它得到值的是“飛機”;然而,進程B也是按照同樣的地址0x0030030來讀取內存,但它取得的值卻是“大炮”。像上面這樣,同一個地址指向截然不同的兩個物理內存位置,並且每個位置存放不同的數據這種現象並不足以爲怪——只不過是兩個進程對虛擬地址到物理地址進行了不同的映射而已。如果這一點利用好了,我們可以讓Rootkit躲避調試程序和取證軟件的追蹤。

上面介紹了內核的主要功能,以及它們對Rootkit的重大意義。說到這裏,我們就要切入正題了,即:只要我們顛覆(即修改)了操作係統的核心服務(即內核),那麽整個係統包括各種應用就完全處於我們的掌控之下了。要想顛覆內核,前提條件是能把我們的代碼導入內核。具體請見下文。



爸爸 你一路好走
獻花 x0 回到頂端 [樓 主] From:臺灣和信超媒體寬帶網 | Posted:2007-06-26 03:05 |
upside 手機 葫蘆墩家族
個人頭像
個人文章 個人相簿 個人日記 個人地圖
特殊貢獻獎 社區建設獎 優秀管理員勳章
頭銜:反病毒 反詐騙 反虐犬   反病毒 反詐騙 反虐犬  
版主
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片

三、將代碼導入內核的方法

所有應用程序都是運行在用戶模式下的,而操作係統是運行在內核模式下的,所以應用程序根本沒有機會來修改內核程序。要想顛覆內核,前提是設法讓我們的代碼也運行在內核模式下,即將我們的代碼導入內核。

設想一下當我們的代碼通過驅動程序進入內核後的情形:我們的代碼一旦在內核運行,就能訪問內核的所有特權內存空間和係統進程——有了這樣的內核級訪問特權,我們就能任意修改係統中的任何代碼和數據了!

將代碼導入內核的方法很多,但我們要介紹的是利用設備驅動程序將代碼導入內核的方式。內核驅動程序有多種叫法,有時候又稱爲內核驅動程序,或者可加載模塊。我們之所以利用設備驅動程序將代碼導入到內核,主要考慮到兩點:

1.簡單性。能夠讓我們的代碼運行在內核模式之的方法有多種,例如把我們的代碼做成設備驅動程序、設法修改正在內存運行的內核、覆蓋硬盤中的內核映像等等。其中,利用設備驅動程序是最爲簡單的一種。

2.適用性。現在,絕大多數的操作係統都允許第三方的硬件廠商加載爲其硬件産品制作的內核擴展,從而使得操作係統能夠支持它們的硬件産品。這的確是一個雙贏之舉,只有這樣,操作係統開發商才能不斷鞏固和擴大其用戶群。因此,各個操作係統開發商不僅提供該係統下的開發設備驅動程序的詳盡幫助文檔,而且還提供了相應的開發工具包。

雖然我們已經找到將我們的代碼導入到內核模式的路徑,但還有一個問題需要回答:除了與硬件打交道的代碼外,其它代碼是否也能寫進設備驅動程序?答案是肯定的。盡管這裏的“設備”一詞容易誤導我們,實際上任何代碼都可以寫成設備驅動程序。

迄今爲止,我們已經回答了利用設備驅動程序來打造內核級別的Rootkit可行性問題,也就是說,內核級Rootkit大門已經打開了一扇,爲了打開另一扇,我們要解決的是“how to”的問題。並且,我們第一個必須解決的“how to”問題就是如何編寫Windows設備驅動程序。

四、Windows設備驅動程序

下面我們介紹如何在Windows XP平台上開發一個簡單的設備驅動程序。在此過程中,我們要用到設備驅動程序開發包DDK。需要注意的是,微軟爲不同的Windows版本提供了不同的DDK。就目前來說,我們可以使用Windows 2003 DDK,因爲該版本能夠支持Windows 2000、Windows XP和Windows 2003等三個平台下的設備驅動程序的開發。

1. 驅動程序源文件

首先在C盤根目錄下新建一個目錄,本例爲C:\myrootkit,此後向相應文件都存放在該目錄之下。然後可以在VC++下建立一個C源文件,讓其內容如下所示:



//一個簡單的驅動程序實例

#include "ntddk.h"

NTSTATUS DriverEntry ( IN PDRIVER_OBJECT theDriverObject,

IN PUNICODE_STRING theRegistryPath )

{

DbgPrint("I am a driver!");

return STATUS_SUCCESS;

}

之後,將其保存在我們的C:\myrootkit目錄下,並且該文件命名爲mydriver.c。下面對上面的代碼作簡要的解釋:

DriverEntry是該驅動程序的入口點,即當該驅動程序啓動時,操作係統會首先調用該函數。它相當於一般C/C++程序中的main或Winmain函數。另外,我們看到DriverEntry的兩個參數中都含有一個關鍵詞IN,說明這兩個參數只能用於輸入。第一個參數指向應被初始化的當前驅動程序的驅動對象;第二個參數是設備服務鍵的鍵名。

該驅動程序實在太簡單了,它只是在內核運行時,利用調試語句給出一則消息:“I am a driver!”。不過,和一般程序不同,該消息不會顯示在標準輸出設備上,也就是說,我們在屏幕上看不到這則消失,關於調試輸出的處理我們會在後文中加以詳細介紹。

有一點需要指出,那就是上面的驅動程序沒有設置卸載例程。盡管卸載例程不是必需的,但有時它卻非常有用:啓動驅動程序時,係統會將參數theDriverObject傳遞給該驅動程序的主函數,這個參數指向的數據結構含有許多函數指針,其中一個指針稱爲“unload routine”。如果我們設置該指針,就能從內存中卸載驅動程序;如果不設置該指針的話,除非重新啓動機器,否則無法將載入內存的驅動程序卸載掉。同時,驅動程序在開發過程中,會不斷添加或改變功能,所以要經常裝載以及卸載它們。爲了避免每次測試新版本的驅動程序時都必須重啓係統,我們應當設置“unload routine”指針。事實上,設置該指針並不是什麽難事:先建立一個卸載例程,就可以設置該卸載指針了。

現在以前面的驅動程序爲例,介紹如何爲其添加卸載例程:

//一個簡單的驅動程序實例

#include "ntddk.h"

// 這裏是我們的卸載函數

VOID MyUnload( IN PDRIVER_OBJECT DriverObject )

{

DbgPrint("MyUnload called\n");

}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,

IN PUNICODE_STRING theRegistryPath)

{

DbgPrint("I am a driver and I loaded!");

// 初始化DriverObject對象中指向卸載函數的指針

theDriverObject->DriverUnload = MyUnload;

return STATUS_SUCCESS;

}

這樣一來,我們用重啓係統就能方便地裝載和卸載驅動程序了。


爸爸 你一路好走
獻花 x0 回到頂端 [1 樓] From:臺灣和信超媒體寬帶網 | Posted:2007-06-26 03:06 |
upside 手機 葫蘆墩家族
個人頭像
個人文章 個人相簿 個人日記 個人地圖
特殊貢獻獎 社區建設獎 優秀管理員勳章
頭銜:反病毒 反詐騙 反虐犬   反病毒 反詐騙 反虐犬  
版主
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片

2. SOURCES文件

要想構建設備驅動程序,僅有驅動程序源文件還是不夠的,我們還需另外兩個文件:SOURCES和MAKEFILE文件。

我們先來介紹SOURCES文件,此文件的名稱必須使用大寫字母,並且不帶任何擴展名,它的內容應當包含:

TARGETNAME=MYDRIVER

TARGETPATH=OBJ

TARGETTYPE=DRIVER

SOURCES=mydriver.c




其中,第一個變量TARGETNAME的作用是爲我們的驅動程序命名。在本例中,我們的設備驅動程序在編譯後被命名爲MYDRIVER。需要注意的是,變量TARGETNAME指定的名稱會被嵌入到二進制代碼之中,所以在寫Rootkit時,千萬不要用該變量爲其指定容易被人猜中的名稱。即使把二進制文件本身改名,但其內部的名字是無法改變的。最好用一些迷惑性較強的名稱來爲這些Rootkit命名,方法是根據係統中已有的驅動程序名,在此基礎上少做手腳,一個上佳的Rootkit名便誕生了。

第二個變量TARGETPATH的作用是指定驅動程序編譯後的存放位置,該變量通常設爲OBJ。一般來說,驅動程序文件被放在目錄objchk_xxx/i386下面,例如本文驅動程序,作者在Windows XP下構建後的文件將位於C:\myrootkit\objchk_wxp_x86\i386。

第三個變量TARGETTYPE用來指定要編譯的文件類型。對於設備驅動程序,該變量設爲DRIVER。

第四個變量SOURCES用來指定源文件。該變量可以指定多個源文件,這時每行一個文件,並且除最後一行外,在每行末尾都要放上一個反斜杠,如下例所示:

SOURCES= myfile1.c \

myfile2.c \

myfile3.c   /*注意,最後一行沒有反斜杠*/


除了上面幾個必選的變量外,還有一些可選變量。變量INCLUDES便是可選變量之一,它用以規定尋找包含文件的目錄。現舉例說明: NCLUDES = c:\my_includes \

..\..\inc \

c:\other_includes


如果需要鏈接庫的話,我們還需要變量TARGETLIBS。例如,有時我們要用到NDIS庫,這時在SOURCES文件就應當包含如下一行: TARGETLIBS=$(BASEDIR)\lib\w2k\i386\ndis.lib
或者: TARGETLIBS=$(DDK_LIB_PATH)\ndis.lib
當然,ndis.lib在你自己係統上的位置可能有所不同,你可以根據實際情況將上面的路徑加以調整。其中,變量$(BASEDIR)規定DDK的安裝目錄$(DDK_LIB_PATH);變量$(DDK_LIB_PATH)則規定了庫文件的默認安裝位置。


爸爸 你一路好走
獻花 x0 回到頂端 [2 樓] From:臺灣和信超媒體寬帶網 | Posted:2007-06-26 03:06 |
upside 手機 葫蘆墩家族
個人頭像
個人文章 個人相簿 個人日記 個人地圖
特殊貢獻獎 社區建設獎 優秀管理員勳章
頭銜:反病毒 反詐騙 反虐犬   反病毒 反詐騙 反虐犬  
版主
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片

3. MAKEFILE文件

和SOURCES文件一樣,MAKEFILE文件的名稱也必須使用大寫字母,同時也不能帶任何擴展名,它的內容一般爲:

!INCLUDE $(NTMAKEENV)\makefile.def
注意的是,要在Windows中建立不帶擴展名的文件,可以利用dos命令行下的EDIT命令或copy con命令。此外,SOURCES和MAKEFILE文件必須與驅動程序的源代碼位於同一個目錄下。

4. 構建過程

準備好SOURCES、MAKEFILE以及C源代碼文件後,我們就可以構建驅動程序了。在此之前,我們先說明一下DDK的兩種構建環境:checked和free構建環境。其中前者一般在開發過程中使用,爲了便於調試,它會在生成的驅動程序中添加一些調試信息,這會使得驅動程序體積較大。開發測試完成後,當我們需要發布産品級的驅動程序時,就可以利用free構建環境來生成驅動程序。

從DDK中單擊checked-build environment,打開命令窗口;

然後,利用cd命令將工作目錄切換到C:\myrootkit目錄下面:

cd C:\myrootkit

接著在命令提示符下輸入命令build開始構建;

如果沒有收到任何錯誤消息,而是類似下圖所示的提示,則說明我們的第一個設備驅動程序已經大功告成了!


五、小結

到目前爲止,本文介紹了Windows下的內核級Rootkit的最基礎性的東西,以及利用驅動程序將代碼導入到內核的方法。雖然我們還沒有涉及到真正的Rootkit,但這些內容是我們掌握Rootkit的必經之路,就像我們要建一座6層的樓房,卻不能撇開基礎和低層而直接蓋第六層一樣!更多的內容,會在後續的文章中陸續介紹。


爸爸 你一路好走
獻花 x0 回到頂端 [3 樓] From:臺灣和信超媒體寬帶網 | Posted:2007-06-26 03:07 |
jack1984yw
數位造型
個人文章 個人相簿 個人日記 個人地圖
初露鋒芒
級別: 初露鋒芒 該用戶目前不上站
推文 x95 鮮花 x150
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片

謝謝大大提供知識


獻花 x0 回到頂端 [4 樓] From:臺灣 | Posted:2007-12-24 17:45 |
yuan2626
個人文章 個人相簿 個人日記 個人地圖
小人物
級別: 小人物 該用戶目前不上站
推文 x0 鮮花 x18
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片

感謝
收到
知識是無價的


獻花 x0 回到頂端 [5 樓] From:臺灣 | Posted:2007-12-25 00:20 |

首頁  發表文章 發表投票 回覆文章
Powered by PHPWind v1.3.6
Copyright © 2003-04 PHPWind
Processed in 0.072801 second(s),query:16 Gzip disabled
本站由 瀛睿律師事務所 擔任常年法律顧問 | 免責聲明 | 本網站已依台灣網站內容分級規定處理 | 連絡我們 | 訪客留言