Linu內(nèi)核級(jí)后門的原理和簡(jiǎn)單實(shí)戰(zhàn)_第1頁(yè)
Linu內(nèi)核級(jí)后門的原理和簡(jiǎn)單實(shí)戰(zhàn)_第2頁(yè)
Linu內(nèi)核級(jí)后門的原理和簡(jiǎn)單實(shí)戰(zhàn)_第3頁(yè)
Linu內(nèi)核級(jí)后門的原理和簡(jiǎn)單實(shí)戰(zhàn)_第4頁(yè)
Linu內(nèi)核級(jí)后門的原理和簡(jiǎn)單實(shí)戰(zhàn)_第5頁(yè)
已閱讀5頁(yè),還剩4頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、關(guān)于 Linux 內(nèi)核級(jí)后門的原理和簡(jiǎn)單實(shí)戰(zhàn)_基礎(chǔ)信息化_IT綜合 _4525關(guān)于 Linux 內(nèi)核級(jí)后門的原理和簡(jiǎn)單實(shí)戰(zhàn) _基礎(chǔ)信息化_IT 綜合以下代碼均在linux i86 2.0.x 的內(nèi)核下面測(cè)試通過。它也許可以在之前的版本通過 , 但并沒有被測(cè)試過. 因?yàn)閺?2.1.x 內(nèi)核版本就引入了相當(dāng)大的改變, 顯著地內(nèi)存管理上的差別 , 但這些不是我們現(xiàn)在要討論的內(nèi)容.用戶空間與內(nèi)核空間linux 是一個(gè)具有保護(hù)模式的操作系統(tǒng)。它一直工作在i386 cpu 的保護(hù)模式之下。內(nèi)存被分為兩個(gè)單元 : 內(nèi)核區(qū)域和用戶區(qū)域。 ( 注 : 我覺得還是這樣叫比較順口 )內(nèi)核區(qū)域存放并運(yùn)行著核心代碼,

2、當(dāng)然,顧名思義,用戶區(qū)域也存放并運(yùn)行用戶程序。當(dāng)然,作為用戶進(jìn)程來講它是不能訪問內(nèi)核區(qū)域內(nèi)存空間以及其他用戶進(jìn)程的地址空間的。不幸地是 , 核心進(jìn)程也有同樣的情況。核心代碼也同樣不能訪問用戶區(qū)地地址空間。那么,這樣做到底有什么意義呢 , 好 , 我們假設(shè)當(dāng)一個(gè)硬件驅(qū)動(dòng)試圖去寫數(shù)據(jù)到一個(gè)用戶內(nèi)存空間的程序里的時(shí)候, 它是不可以直接去完成的 , 但是它可以利用一些特殊的核心函數(shù)來間接完成。同樣, 當(dāng)參數(shù)需要傳遞地址到核心函數(shù)中時(shí), 核心函數(shù)也不能直接的來讀取該參數(shù)。同樣的,它可以利用一些特殊的核心函數(shù)來傳遞參數(shù)。這里有一些比較有用的核心函數(shù)用來作為內(nèi)核區(qū)與用戶區(qū)相互傳遞參數(shù)用。#include g

3、et_user(ptr)從用戶內(nèi)存獲取給定的字節(jié), 字, 或者長(zhǎng)整形。這只是一個(gè)宏 (在核心代碼里面有此宏的詳細(xì)定義), 并且它依據(jù)參數(shù)類型來確定傳輸數(shù)量。所以你必須巧 妙地利用它。put_user(ptr) 和 get_user() 非常相似 , 但,它不是從用戶內(nèi)存讀取數(shù)據(jù),而是想用戶內(nèi)存寫數(shù)據(jù)。memcpy_fromfs(void *to, const void *from,unsigned long n)從用戶內(nèi)存中的 *from 拷貝 n 個(gè)字節(jié)到指向核心內(nèi)存的指針*to 。memcpy_tofs(void *to,const *from,unsigned long n)從核心內(nèi)存中

4、的 *from 拷貝 n 個(gè)字節(jié)數(shù)據(jù)到用戶內(nèi)存中的 *to 。/* 注: 這四個(gè)函數(shù)足以在2.0.x 中解決內(nèi)核和用戶區(qū)的參數(shù)傳遞問題,在2.0.x以上的版本有新的實(shí)現(xiàn),即copy_user_to(.)以及copy_user_from(.)根據(jù)內(nèi)核版本這些特殊函數(shù)會(huì)有不同,請(qǐng)關(guān)注核心代碼的實(shí)現(xiàn)方法。 */系統(tǒng)調(diào)用大部分的 c 函數(shù)庫(kù)的調(diào)用都依賴于系統(tǒng)調(diào)用 , 就是一些使用戶程序可以調(diào)用的簡(jiǎn)單核心包裝函數(shù)。 這些系統(tǒng)調(diào)用運(yùn)行在內(nèi)核本身或者在可加載內(nèi)核模塊中 , 就是一些可動(dòng)態(tài)的加載卸載的核心代碼。就象MS-DOS口其他許多系統(tǒng)一樣,linux中的系統(tǒng)調(diào)用依賴一個(gè)給定的中斷來調(diào)用多個(gè)系統(tǒng)調(diào)用。 l

5、inux 系統(tǒng)中 , 這個(gè)中斷就是int 0 x80 。當(dāng)調(diào)用 int 0 x80 中斷的時(shí)候 , 控制權(quán)就轉(zhuǎn)交給了內(nèi)核( 或者,我們確切點(diǎn)地說, 交給 _system_call() 這個(gè)函數(shù) ), 并且實(shí)際上是一個(gè)正在進(jìn)行的單處理過程。* _system_call() 是如何工作的 ?首先,所有的寄存器被保存并且eax寄存器全面檢查系統(tǒng)調(diào)用表,這張表列舉了所有的系統(tǒng)調(diào)用和他們的地址信息。它可以通過extern void*sys_call_table口來被訪問到。該表中的每個(gè)定義的數(shù)值和內(nèi)存地址都對(duì)應(yīng)每個(gè)系統(tǒng)調(diào)用。大家可以在/usr/include/sys/syscall.h這個(gè)頭中找到系統(tǒng)調(diào)

6、用的標(biāo)示數(shù)。他們對(duì)應(yīng)相應(yīng)的SYS_systemcall名。假如一個(gè)系統(tǒng)調(diào)用不存在,那么它在 sys_call_table中相應(yīng)的標(biāo)示就為0,并且返回一個(gè)出錯(cuò)信息。否則,系統(tǒng)調(diào)用存在并在表里相應(yīng)的入口為系統(tǒng)調(diào)用代碼的內(nèi)存地址。這兒是一個(gè)有問題的系統(tǒng)調(diào)用例程:系統(tǒng)控制權(quán)就會(huì)轉(zhuǎn)向真正的系統(tǒng)調(diào)用,用來完成你的請(qǐng)求并返回。然后 _system_call()調(diào)用_ret_from_sys_call()來檢查不同的返回值,并且最后返回到用戶內(nèi)存。libc這int $0 x80 并不是直接被用作系統(tǒng)調(diào)用;更確切地是,libc 函數(shù),經(jīng)常用來 包裝0 x80中斷,這樣使用的。libc通常利用_syscallX(

7、)宏來描述系統(tǒng)調(diào)用,X是系統(tǒng)調(diào)用的總參數(shù)個(gè)數(shù)。舉個(gè)例子吧,libc 中的write(2)就是利用_syscall3這個(gè)系統(tǒng)調(diào)用宏來實(shí)現(xiàn)的 因?yàn)閷?shí)際的write(2)原型需要3個(gè)參數(shù)。在調(diào)用0 x80中斷之前,這個(gè)_syscallX 宏假定系統(tǒng)調(diào)用的堆棧結(jié)構(gòu)和要求的參數(shù)列表,最后,當(dāng) _system_call()(通過 int &0 x80來引發(fā))返回的時(shí)候,_syscallX()宏將會(huì)查出錯(cuò)誤的返回值(在eax講 且為其設(shè)置errno。讓我們看一下另一個(gè)write(2)例程并看看它是如何進(jìn)行預(yù)處理的?;刈⒁饽莻€(gè)write()里的0這個(gè)參數(shù)匹配SYS_write ,在/usr/include/s

8、ys/syscall.h中 定義。構(gòu)建你自己的系統(tǒng)調(diào)用。這里給出了幾個(gè)構(gòu)建你自己的系統(tǒng)調(diào)用的方法。舉個(gè)例子 ,你可以修改內(nèi)核代 碼并且加入你自己的代碼。一個(gè)比較簡(jiǎn)單可行的方法 ,不過,一定要被寫成可加載 內(nèi)核模塊。沒有一個(gè)代碼可以象可加載內(nèi)核模塊那樣可以當(dāng)內(nèi)核需要的時(shí)候被隨時(shí)加載的。我們的主要意圖是需要一個(gè)很小的內(nèi)核,當(dāng)我們需要的時(shí)候運(yùn)行insmod命令, 給定的驅(qū)動(dòng)就可以被自動(dòng)加載。這樣卸除來的 lkm程序一定比在內(nèi)核代碼樹里寫代 碼要簡(jiǎn)單易行多了。寫lkm程序一個(gè)lkm程序可以用c來很容易編寫出來。它包含了大量的 #defines, 一些 函數(shù),一個(gè)初始化模塊的函數(shù),叫做init_modu

9、le(),和一個(gè)卸載函數(shù):cleanup_module()。這里有一個(gè)經(jīng)典的lkm代碼結(jié)構(gòu):回檢查代碼中的 #defines (#define MODULE, #define _KERNEL_) 和#includes (#include )一定要注意的是我們的lkm講要被運(yùn)行在內(nèi)核狀態(tài),我們就不能用libc包裝的 函數(shù)了,但是我們可以通過前面所討論的_syscallX()宏來構(gòu)建系統(tǒng)調(diào)用。你可以這樣編譯你的模塊gcc -c -O3 module.c并且利用insmodmodule.o來加載。提一個(gè)建議,lkm也可以用來在不完全重建核心代碼的情況下來修改內(nèi)核代 碼。舉個(gè)例子,你可以修改write

10、系統(tǒng)調(diào)用讓它隱藏一部分給定的文件,就象我們 把我們的backdoors放到一個(gè)非常好的地方:當(dāng)你無法再信任你的系統(tǒng)內(nèi)核的時(shí)候 會(huì)怎么樣呢,內(nèi)核和系統(tǒng)調(diào)用后門在簡(jiǎn)單介紹了上述理論,我們主要可以用來做什么呢。我們可以利于 lkm這樣可以強(qiáng)制內(nèi)核按照我們的方式運(yùn)行。例截獲一些對(duì)我們有影響的系統(tǒng)調(diào)用 ,如:我們可以利用ioctl系統(tǒng)調(diào)用來隱藏sniffer 所造成白網(wǎng)卡PROMISE式的顯示。非常有效。去改變一個(gè)給定的系統(tǒng)調(diào)用 , 只需要在你的 lkm 程序中增加一個(gè)定義externvoid *sys_call_table, 并且利用 init_module() 函數(shù)來改變sys_call_table

11、 里的入口來指向我們自己的代碼。改變后的調(diào)用可以做我們希望它做的一切事情, 利用改變 sys_call_table 來導(dǎo)出更多的原系統(tǒng)調(diào)用,并且。以下代碼均在linux i86 2.0.x 的內(nèi)核下面測(cè)試通過。它也許可以在之前的版本通過 , 但并沒有被測(cè)試過. 因?yàn)閺?2.1.x 內(nèi)核版本就引入了相當(dāng)大的改變, 顯著地內(nèi)存管理上的差別 , 但這些不是我們現(xiàn)在要討論的內(nèi)容.用戶空間與內(nèi)核空間linux 是一個(gè)具有保護(hù)模式的操作系統(tǒng)。它一直工作在i386 cpu 的保護(hù)模式之下。內(nèi)存被分為兩個(gè)單元 : 內(nèi)核區(qū)域和用戶區(qū)域。 ( 注 : 我覺得還是這樣叫比較順口 )內(nèi)核區(qū)域存放并運(yùn)行著核心代碼, 當(dāng)

12、然,顧名思義,用戶區(qū)域也存放并運(yùn)行用戶程序。當(dāng)然,作為用戶進(jìn)程來講它是不能訪問內(nèi)核區(qū)域內(nèi)存空間以及其他用戶進(jìn)程的地址空間的。不幸地是 , 核心進(jìn)程也有同樣的情況。核心代碼也同樣不能訪問用戶區(qū)地地址空間。那么,這樣做到底有什么意義呢 , 好 , 我們假設(shè)當(dāng)一個(gè)硬件驅(qū)動(dòng)試圖去寫數(shù)據(jù)到一個(gè)用戶內(nèi)存空間的程序里的時(shí)候, 它是不可以直接去完成的 , 但是它可以利用一些特殊的核心函數(shù)來間接完成。同樣, 當(dāng)參數(shù)需要傳遞地址到核心函數(shù)中時(shí), 核心函數(shù)也不能直接的來讀取該參數(shù)。同樣的,它可以利用一些特殊的核心函數(shù)來傳遞參數(shù)。這里有一些比較有用的核心函數(shù)用來作為內(nèi)核區(qū)與用戶區(qū)相互傳遞參數(shù)用。#include ge

13、t_user(ptr)從用戶內(nèi)存獲取給定的字節(jié), 字, 或者長(zhǎng)整形。這只是一個(gè)宏 (在核心代碼里面有此宏的詳細(xì)定義), 并且它依據(jù)參數(shù)類型來確定傳輸數(shù)量。所以你必須巧妙地利用它。put_user(ptr) 和 get_user() 非常相似 , 但,它不是從用戶內(nèi)存讀取數(shù)據(jù),而是想用戶內(nèi)存寫數(shù)據(jù)。memcpy_fromfs(void *to, const void *from,unsigned long n)從用戶內(nèi)存中的 *from 拷貝 n 個(gè)字節(jié)到指向核心內(nèi)存的指針*to 。memcpy_tofs(void *to,const *from,unsigned long n)從核心內(nèi)存中的

14、*from 拷貝 n 個(gè)字節(jié)數(shù)據(jù)到用戶內(nèi)存中的 *to 。/* 注: 這四個(gè)函數(shù)足以在2.0.x 中解決內(nèi)核和用戶區(qū)的參數(shù)傳遞問題,在2.0.x以上的版本有新的實(shí)現(xiàn),即copy_user_to(.)以及copy_user_from(.)根據(jù)內(nèi)核版本這些特殊函數(shù)會(huì)有不同,請(qǐng)關(guān)注核心代碼的實(shí)現(xiàn)方法。 */系統(tǒng)調(diào)用大部分的 c 函數(shù)庫(kù)的調(diào)用都依賴于系統(tǒng)調(diào)用 , 就是一些使用戶程序可以調(diào)用的簡(jiǎn)單核心包裝函數(shù)。 這些系統(tǒng)調(diào)用運(yùn)行在內(nèi)核本身或者在可加載內(nèi)核模塊中 , 就是一些可動(dòng)態(tài)的加載卸載的核心代碼。就象MS-DOS其他許多系統(tǒng)一樣,linux 中的系統(tǒng)調(diào)用依賴一個(gè)給定的中斷來調(diào)用多個(gè)系統(tǒng)調(diào)用。 linux 系統(tǒng)中 , 這個(gè)中斷就是int 0 x80 。當(dāng)調(diào)用 int 0 x80 中斷的時(shí)候,控制權(quán)就轉(zhuǎn)交給了內(nèi)核(或者,我們確切點(diǎn)地說,交給_system_call()這 個(gè)函數(shù)),并且實(shí)際上是一個(gè)正在進(jìn)行的單處理過程。* _system_call()是如何工作的?首先,所有的寄存器被保存并且eax寄存器全面檢查系統(tǒng)調(diào)用表,這張表列舉 了所有的系統(tǒng)調(diào)用和他們的地址信息。它可以通過 extern void*sys_call_table口來被訪問到。該表中的每個(gè)定義的數(shù)值和內(nèi)存地址都對(duì)應(yīng)每個(gè)系統(tǒng)調(diào)用。大家可以在/usr/include/sys/sys

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論