日本免费全黄少妇一区二区三区-高清无码一区二区三区四区-欧美中文字幕日韩在线观看-国产福利诱惑在线网站-国产中文字幕一区在线-亚洲欧美精品日韩一区-久久国产精品国产精品国产-国产精久久久久久一区二区三区-欧美亚洲国产精品久久久久

1 《Undocumented Windows 2000 Secrets》翻譯 --- 第五章

第五章 監(jiān)控Native API調(diào)用
翻譯:Kendiv( fcczj@263.net )
更新:Tuesday, February 22, 2005
聲明:轉(zhuǎn)載請注明出處,并保證文章的完整性,本人保留譯文的所有權(quán)利 。
攔截系統(tǒng)調(diào)用在任何時候都是程序員們的最愛 。這種大眾化愛好的動機也是多種多樣的:代碼性能測試(Code Profiling)和優(yōu)化,逆向工程,用戶活動記錄等等 。所有這些都有一個共同的目的:將控制傳遞給一塊特殊的代碼,這樣無論一個應(yīng)用程序何時調(diào)用系統(tǒng)服務(wù),都可以發(fā)現(xiàn)哪個服務(wù)被調(diào)用了,接收了什么參數(shù),返回的結(jié)果是什么以及執(zhí)行它花費了多少時間 。根據(jù)最初由Mark Russinovich和Bryce Cogswell提出的技巧,本章將介紹一個可以hook任意Native API函數(shù)的通用框架 。這里使用的方法完全是數(shù)據(jù)驅(qū)動(data-driven)的,因此,它可以很容易被擴展,并能適應(yīng)其他Windows NT/2000版本 。所有進程的API調(diào)用產(chǎn)生的數(shù)據(jù)都被寫入一個環(huán)狀緩沖區(qū)中,客戶端程序可以通過設(shè)備I/O控制來讀取該緩沖區(qū) 。采用的數(shù)據(jù)協(xié)議(protocol data)的格式是以行為導(dǎo)向的ANSI文本流,它符合嚴格的格式化規(guī)則,應(yīng)用程序可以很容易的再次處理它們(postprocessing) 。為了示范此種客戶端程序的基本框架,本章還提供了一個示例性的數(shù)據(jù)協(xié)議察看器,該程序運行于控制臺窗口中 。
譯注:
profiling 一般是指對程序做性能方面的測試, 主要是速度上的 。在翻譯時,可譯為:剖析,最好是根據(jù)上文環(huán)境進行翻譯 。
修改服務(wù)描述符表
對比“原始”的操作系統(tǒng),如Dos或Windows 3.x,它們對程序員在API中加入hook的限制很少,而Win32系統(tǒng),如Windows 2000/NT和Windows 9.x則很難駕馭,因為它們使用了巧妙的保護機制把不相關(guān)的代碼分離出來 。在Win32 API上設(shè)置一個系統(tǒng)范圍的hook絕不是一個小任務(wù) 。幸運的是,我們有像Matt PIEtrek和Jeffery Richter這樣的Win32向?qū)В麄冏隽舜罅康墓ぷ鱽硐蛭覀冋故救绾瓮瓿蛇@一任務(wù),盡管事實上,并沒有簡單和優(yōu)雅的解決方案 。在1997年,Russinovich和Cogswell介紹了一種可在Windows NT上實現(xiàn)系統(tǒng)范圍hook的完全不同的方法,可在更低一層上攔截系統(tǒng)調(diào)用(Russinovich和Cogswell 1997) 。他們提議向Native API Dispatcher中注入日志機制,這僅比用戶模式和內(nèi)核模式之間的邊界低一些,在這個位置上Windows NT暴露出一個“瓶頸”:所有用戶模式的線程必須通過此處,才能使用操作系統(tǒng)內(nèi)核提供的服務(wù) 。
服務(wù)和參數(shù)表
就像在第二章討論過的,發(fā)生在用戶模式下的Native API調(diào)用必須通過INT 2eh接口,該接口提供一個i386的中斷門來改變特權(quán)級別 。你可能還記得所有INT 2eh調(diào)用都是由內(nèi)部函數(shù)KiSystemService()在內(nèi)核模式下處理的,該函數(shù)使用系統(tǒng)服務(wù)描述符表(SDT)來查找Native API處理例程的入口地址 。圖5-1給出了這種分派機制的基本組件之間的相互關(guān)系 。列表5-1再次給出了SERVICE_DESCRIPTOR_TABLE結(jié)構(gòu)及其子結(jié)構(gòu)的正式定義,在第二章中,已經(jīng)給出過它們的定義(列表2-1) 。
調(diào)用KiSystemService()時,需提供兩個參數(shù),由INT 2eh的調(diào)用者通過EAX和EDX寄存器傳入 。EAX包含從0開始的索引,該索引可用于一個API函數(shù)指針的數(shù)組,EDX指向調(diào)用者的參數(shù)堆棧 。KiSystemService()通過讀取ServiceTable的一個成員的值(該成員是ntoskrnl.exe的一個公開數(shù)據(jù)結(jié)構(gòu):KeServiceDescriptorTable,圖5-1的左面列出了該結(jié)構(gòu))來獲取函數(shù)數(shù)組的基地址 。實際上,KeServiceDescriptorTable指向一個包含四個服務(wù)表的結(jié)構(gòu),但默認情況下,僅有第一個服務(wù)表是有效的 。KiSystemService()通過EAX中的索引值進入內(nèi)部結(jié)構(gòu)KiServiceTable,以查找可處理此API調(diào)用的函數(shù)的入口地址 。在調(diào)用目標函數(shù)之前,KiSystemServie()以相同的方式查詢KiArgumentTable結(jié)構(gòu),以找出調(diào)用者在參數(shù)堆棧中傳入了多少字節(jié),然后使用這個值將參數(shù)復(fù)制到當(dāng)前內(nèi)核堆棧中 。此后,就只需要一個簡單的匯編指令:CALL來執(zhí)行API處理例程了 。這里涉及的所有函數(shù)都符合__stdcall標準 。

推薦閱讀