不僅win32 api可以掛鉤,系統服務也可以掛鉤。開發者為了捕獲各種事件,可以掛鉤檔案建立函式createfile,登錄檔訪問函式regcreatekey。使用掛鉤可以改變作業系統的行為,只要適當地改變掛鉤的資料結構和上下文,足夠引起新的行為。例如,通過掛鉤ntcreatefile系統服務,可以保護敏感檔案不被開啟,儘管ntfs為檔案提供了使用者級的安全,但這些安全措施卻不能用在fat分割槽上。
系統服務就是由作業系統提供的一組函式,類似上層開發的win32 api。
不僅win32 api可以掛鉤,系統服務也可以掛鉤。開發者為了捕獲各種事件,可以掛鉤檔案建立函式createfile,登錄檔訪問函式regcreatekey。使用掛鉤可以改變作業系統的行為,只要適當地改變掛鉤的資料結構和上下文,足夠引起新的行為。例如,通過掛鉤ntcreatefile系統服務,可以保護敏感檔案不被開啟,儘管ntfs為檔案提供了使用者級的安全,但這些安全措施卻不能用在fat分割槽上。
kernel-level hooking
系統級掛鉤要用驅動程式實現,此方法的缺點就是,需要確定傳遞給核心函式的引數,但多數情況下這些服務都是未公開的。所以,這類掛鉤更難實現,但可以產生更好的效果。
user-level hooking
使用者級的掛鉤的優點是這些函式通常都是公開的,可以知道所需的引數。這類掛鉤只能侷限於使用者模式而不能擴充套件到核心模式。
下面主要要討論kernel-level hooking
我這裡主要把重點提一下,以及自已學習過程中理解的東東,和理解後寫出來的原始碼。不少文章有**片段,但很多像我一樣,剛剛接解核心開發,連ddk都沒安裝,看過那些**片段總覺得太空洞。《undocmented windows 2000 secrets》雖然提供**(w2k_spy),但過於複雜,不利於初學者。
關於驅動程式如果編譯安裝,請參考有關資料。如果想要速學,建議看《undocmented windows 2000 secrets》第三章。接下來,假設你已經懂得如何編譯安裝驅動,以及掛鉤系統服務的基本知識了。
系統服務是如何被呼叫的?
系統服務的使用者介面是以包裝函式的形式提供的,這些包裝函式都在ntdll.dll中。這些包裝函式使用int 2e指令來切換到核心模式並執行所需的系統服務:每一種系統服務都用乙個service id的標識,包裝函式將所需的系統服務的service id送入eax暫存器,將指向堆疊幀的指標送入edx暫存器,然後發出int 2e指令。int 2e的處理程式將引數從使用者模式的堆疊拷貝到核心模式的堆疊,這個由ntosknrl.exe提供的int 2e處理程式內部被稱為kisystemservice()。其中有乙個系統服務分派表,表中的每乙個表項都包含service id和其對應的函式位址。每個函式的**都位於核心之中。
掛鉤系統服務最簡單的方法就是修改系統服務分派表中的函式指標,使之指向由開發者插入的某個函式。要做到這點只能通過核心驅動,因為這個系統服務分派表是受作業系統保護的,這錶所在的頁屬性被設定成只有核心程式才能讀寫,使用者級的應用程式不能讀寫這些記憶體單元。
如何訪問系統服務分派表?
在2000/xp中預設存在兩個系統服務分派表(sdt),它們對應了兩類不同的系統服務。這兩個分別是:keservicedescriptortable和keservicedescriptortableshadow,nt下只有前面那個。keservicedescriptortable
定義了在
ntoskrln.exe
中實現的系統服務,通常在
kernel32.dll
和advapi32.dll
中提供的函式介面均是使用
keservicedescriptortable
。同時存在的還有
win32k.sys
中實現的
winuser
和gdi
函式,它們是屬於另一類系統服務呼叫,與之相對應的分派表是
keservicedescriptortableshadow
,它提供了核心模式的user和gdi的服務。由服務keaddsystemservicetable新增的服務會被同時複製到上面兩個分派表中。
系統服務分派表的資料結構(sdt)
typedef struct _service_descriptor_table // sdt
service_descriptor_table ;
typedef ntstatus (ntapi *ntproc)() ;
typedef ntproc *pntproc ;
typedef struct _system_service_table // ssd
system_service_table
訪問keservicedescriptortable很簡單,因為它由ntoskrnl.exe公開匯出。
加上 extern pservice_descriptor_table keservicedescriptortable; 這行就可以直接訪問這個資料結構。但keservicedescriptortableshadow沒有匯出(nt下沒有此表),而且2000和xp下,它的位置不一樣。以後我們要掛鉤的都是ntoskrnl.exe匯出的函式,所以不用訪問keservicedescriptortableshadow。
keservicedescriptortabe只有第1個成員 ntoskrnl 有用到,其它3個成員全部為null 。keservicedescriptortabeshadow前面2個成員都用到,它們的ntoskrnl成員都是相同的,差別在後者多了乙個有效的win32k成員,也就是win32k.sys的系統服務分派表。在2000下 ,keservicedescriptortableshadow=keservicedescriptortable+0xe0;
在xp下,keservicedescriptortableshadow=keservicedescriptortable-0x40。
如何得到要掛鉤服務的id?
ntosknrl.exe的服務都儲存在system_service_table.servicetable中,該成員是個線性陣列,每個項儲存乙個服務的位址指標,只要把這個位址換成我們提供的函式位址指標就ok了。我們怎麼知道要掛鉤那個服務在陣列中的id(索引)呢?
ulong serviceidfromfn (pvoid pfnhandler)
由這個服務函式的位址可以直接轉化成id ,如 serviceidfromfn( zwcreatefile )就是返回 zwcreatefile 的id。而且,從這個id我們就可以判斷這個服務是由ntosknrl.exe,還是win32k.sys提供的。看id二進位制的 13,14位,如果全為0表示由ntosknrl.exe提供,如果13位為1,14位為0表示由win32k.sys提供。
例子:理論看得再多,還不如讀一下**!有的時候我更喜歡直接看**。
我提供的**再簡潔不過,沒有多餘的**,一切都只為了實現 zwcreatefile 的掛鉤。我的zwcreatefile只是把檔名稱列印出來,然後直接呼叫真正的zwcreatefile 。如果你不熟悉驅動安裝,又想檢驗一下實踐的成果,可以:
1.把hooksys.sys檔案複製到 c:/windows/system32/drivers 下
2.在命令提示符下,執行w2k_load c:/windows/system32/drivers/hooksys.sys安裝
3.4.
在命令提示符下,執行net start hooksys 啟動驅動
5.通過dbgview.exe 觀察檔案的建立情況
6.在命令提示符下,執行net stop hooksys 停止驅動
7.刪除 hooksys.sys
系統服務掛鉤 HOOK 2
下面主要以 為主 未經嚴格測試,僅供學習參考 實現了 1 保護檔案 目錄不被刪除 2 隱藏檔案 目錄 3 隱藏程序 4 保護程序不被結束 5 保護登錄檔鍵不被開啟 6 保護登錄檔鍵不被刪除 網上有幾篇文章介紹了部分功能,並提供的原始碼。所以我主要把對原始碼的理解寫下來,並對原始碼做簡化,更利於理解。...
Hook 系統服務隱藏埠
主頁 有時候寫程式,除錯程式真是一件非常有趣的事,就比如這次,蹦蹦跳跳,笑嘻嘻,意猶未盡的就把這個程式搞好了。stat 或者其他各種列舉埠的工具,比如fport,或者 sysinternals 的 tcpview,都是呼叫 iphlpapi.dll 中的 api 來完成埠的列舉。而 iphlpapi...
Hook 系統服務隱藏埠
主頁 http jiurl.yeah.日期 2004 03 30 有時候寫程式,除錯程式真是一件非常有趣的事,就比如這次,蹦蹦跳跳,笑嘻嘻,意猶未盡的就把這個程式搞好了。stat 或者其他各種列舉埠的工具,比如fport,或者 sysinternals 的 tcpview,都是呼叫 iphlpapi...