HOOK汇总
HOOK技術主要分為兩大類,一是內核層HOOK,一是用戶層HOOK. 用戶層HOOK也就是在ring3環境下hook kenerl32.dll、User3.dll、Gui32.dll、Advapi.dll等導出的函數。而內核層HOOK就是HOOK只有ring0級別環境下才能操作寫入改變的內核對象,例如SSDT系統服務描述符表等。綜合而言,主要有以下9種HOOK技術。
(1)消息鉤子
消息鉤子是最常見的鉤子之一,例如常見的鍵盤鼠標鉤子,很多木馬就是通過消息鉤子獲取密碼的。消息鉤子是由Win32子系統提供,用戶通過它注冊全局鉤子。當系統獲取某些事件,比如用戶按鍵,鍵盤driver將掃描碼等傳入win32k的KeyEvent處理函數,處理函數判斷有無相應hook,有則通過回調函數處理。此時,系統取得Hook對象信息,若目標進程沒有裝載對應的Dll,則裝載之。
(2)IAT HOOK
IAT HOOK[4]是最常見和普遍的HOOK之一。IAT表示導入地址表(Import Address Table),導入函數就是被程序調用但其執行代碼又不在程序中的函數,當PE 文件被裝入內存的時候,Windows 裝載器才將DLL 裝入,并將調用導入函數的指令和函數實際所處的地址聯系起來(動態連接),這種操作就需要導入表完成。其中導入地址表就指示函數實際地址。程序每個調用的 API 函數地址都保存在 IAT 表中,而每個調用 API 函數的 CALL 指令所使用的地址都是相應函數登記在 IAT 表的地址。IATHOOK原理是在將 IAT 表中的地址換成用戶自己的 函數地址,這樣每個 API 調用都是先調用用戶自己的 函數。在這個函數中我們可以完成函數名稱的記錄、參數的記錄、調用原來的過程,并在返回時記錄結果。
(3)EAT HOOK
EAT HOOK的原理是根據替換 PE 格式導出表中的相應函數來實現的。EAT表示導出地址表(Export Address Table),EAT存在于PE文件中的edata節,保存了可執行文件(如DLL 文件)的導出的可供其他模塊來調用的函數和公共變量,包括函數名稱和地址等。通過替換Windows 系統某些重要DLL中的輸出函數地址,即可實現目標函數的掛接。EAT記錄DLL中可供其他程序使用的函數,可執行文件裝載時會使用相應DLL的EAT表來初始化IAT表。EAT HOOK原理是通過替換EAT表中的函數地址,使依賴于本DLL的程序得到一個假的地址。
(4)SSDT HOOK
SSDT是最常見的內核層 HOOK。SSDT的全稱是系統服務描述符表(System Services Descriptor Table)。SSDT是關聯ring3的Win32 API和ring0的內核API的重要數據結構,它存儲著Windows把需要調用的所有內核API地址。SSDT HOOK原理是將內核層 API地址修改為指向其位于Ring0層的驅動入口,這樣每次系統執行到這個函數時,都會通過SSDT表將原始調用引向修改后的模塊中。
(5)IDT HOOK
IDT HOOK是Win2000操作系統上常用的一種HOOK。IDT是中斷描述表,可以替換其中的中斷處理程序。這種方法對于跟蹤、分析系統調用來說用的比較多。IDT HOOK的原理是通過替換 IDT表中的 INT 2E 中斷,使之指向新的中斷服務處理例程來實現的。它首先保存出特定的中斷向量中斷服務程序(ISR), 然后直接修改該中斷向量的ISR為自定義的函數,每當這個中斷向量對應的中斷產生時,就會調用自定義的函數。由于我們自定義的函數里面執行完我們的功能后再跳轉到原ISR處執行。
(6)SYSENTRY HOOK
SYSENTRY是Windows XP之后的操作系統進入ring0的函數。Win2000中通過 int2e系統調用機制,涉及到的Interrupt/Exception Handler的調用都是通過 call/trap/task這一類的gate來實現的,這種方式會進行棧切換,并且系統棧的地址等信息由TSS提供,可能會引起多次內存訪問 (來獲取這些切換信息),系統開銷較大。SYSENTER通過匯編指令實現快速系統調用機制。SYSENTER HOOK的原理是首先Ntdll 加載相應的請求服務號到EAX 寄存器中,同時EDX 寄存器存貯當前的棧指針ESP,然后Ntdll發出SYSENTER 指令,該指令轉移控制權到寄存器IA32_SYSENTER_EIP 存貯的地址中[21],通過修改這個地址,可實現相應的掛接。
(7)Inline HOOK
inline hook是直接在以前的函數體內修改指令,用一個跳轉或者其他指令來實現掛鉤的目的。 而普通的hook只是修改函數的調用地址,而不是在原來的函數體里面做修改。
Inline hook原理是解析函數開頭的幾條指令,把他們Copy到數組保存起來,然后用一個調用我們的函數的幾條指令來替換,如果要執行原函數,則在我們函數處理完畢,再執行我們保存起來的開頭幾條指令,然后調回我們取指令之后的地址執行。它需要在程序中嵌入匯編代碼(Inline Assembly)以操作堆棧和執行內核API對應的部分匯編指令。
(7)OBJECT HOOK
OBJECT HOOK是相對于IAT HOOK之類的 API HOOK而言,API HOOK是掛鉤應用層函數,而OBJECT HOOK是掛鉤內核層函數。其原理與API HOOK類似。
(9)IRP HOOK
IRP是 I/O request packets,在Windows中幾乎所有的I/O都是通過包(packet)驅動的,每個單獨的I/O由一個工作命令描述,此命令將會告訴驅動程序需要一些什么操作,并通過I/O子系統跟蹤處理過程。這些工作命令就表現為一個個被稱為IRP的數據結構。IRP HOOK原理是攔截管理器發向文件或網絡系統等驅動程序的IRP。一般通過創建一個上層過濾器設備對象并將之加入系統設備所在的設備堆棧中。也有部分IRP HOOK通過攔截傳遞IRP請求包的函數IofCallDriver或MajorFunction函數表來實現的。
(1)消息鉤子
消息鉤子是最常見的鉤子之一,例如常見的鍵盤鼠標鉤子,很多木馬就是通過消息鉤子獲取密碼的。消息鉤子是由Win32子系統提供,用戶通過它注冊全局鉤子。當系統獲取某些事件,比如用戶按鍵,鍵盤driver將掃描碼等傳入win32k的KeyEvent處理函數,處理函數判斷有無相應hook,有則通過回調函數處理。此時,系統取得Hook對象信息,若目標進程沒有裝載對應的Dll,則裝載之。
(2)IAT HOOK
IAT HOOK[4]是最常見和普遍的HOOK之一。IAT表示導入地址表(Import Address Table),導入函數就是被程序調用但其執行代碼又不在程序中的函數,當PE 文件被裝入內存的時候,Windows 裝載器才將DLL 裝入,并將調用導入函數的指令和函數實際所處的地址聯系起來(動態連接),這種操作就需要導入表完成。其中導入地址表就指示函數實際地址。程序每個調用的 API 函數地址都保存在 IAT 表中,而每個調用 API 函數的 CALL 指令所使用的地址都是相應函數登記在 IAT 表的地址。IATHOOK原理是在將 IAT 表中的地址換成用戶自己的 函數地址,這樣每個 API 調用都是先調用用戶自己的 函數。在這個函數中我們可以完成函數名稱的記錄、參數的記錄、調用原來的過程,并在返回時記錄結果。
(3)EAT HOOK
EAT HOOK的原理是根據替換 PE 格式導出表中的相應函數來實現的。EAT表示導出地址表(Export Address Table),EAT存在于PE文件中的edata節,保存了可執行文件(如DLL 文件)的導出的可供其他模塊來調用的函數和公共變量,包括函數名稱和地址等。通過替換Windows 系統某些重要DLL中的輸出函數地址,即可實現目標函數的掛接。EAT記錄DLL中可供其他程序使用的函數,可執行文件裝載時會使用相應DLL的EAT表來初始化IAT表。EAT HOOK原理是通過替換EAT表中的函數地址,使依賴于本DLL的程序得到一個假的地址。
(4)SSDT HOOK
SSDT是最常見的內核層 HOOK。SSDT的全稱是系統服務描述符表(System Services Descriptor Table)。SSDT是關聯ring3的Win32 API和ring0的內核API的重要數據結構,它存儲著Windows把需要調用的所有內核API地址。SSDT HOOK原理是將內核層 API地址修改為指向其位于Ring0層的驅動入口,這樣每次系統執行到這個函數時,都會通過SSDT表將原始調用引向修改后的模塊中。
(5)IDT HOOK
IDT HOOK是Win2000操作系統上常用的一種HOOK。IDT是中斷描述表,可以替換其中的中斷處理程序。這種方法對于跟蹤、分析系統調用來說用的比較多。IDT HOOK的原理是通過替換 IDT表中的 INT 2E 中斷,使之指向新的中斷服務處理例程來實現的。它首先保存出特定的中斷向量中斷服務程序(ISR), 然后直接修改該中斷向量的ISR為自定義的函數,每當這個中斷向量對應的中斷產生時,就會調用自定義的函數。由于我們自定義的函數里面執行完我們的功能后再跳轉到原ISR處執行。
(6)SYSENTRY HOOK
SYSENTRY是Windows XP之后的操作系統進入ring0的函數。Win2000中通過 int2e系統調用機制,涉及到的Interrupt/Exception Handler的調用都是通過 call/trap/task這一類的gate來實現的,這種方式會進行棧切換,并且系統棧的地址等信息由TSS提供,可能會引起多次內存訪問 (來獲取這些切換信息),系統開銷較大。SYSENTER通過匯編指令實現快速系統調用機制。SYSENTER HOOK的原理是首先Ntdll 加載相應的請求服務號到EAX 寄存器中,同時EDX 寄存器存貯當前的棧指針ESP,然后Ntdll發出SYSENTER 指令,該指令轉移控制權到寄存器IA32_SYSENTER_EIP 存貯的地址中[21],通過修改這個地址,可實現相應的掛接。
(7)Inline HOOK
inline hook是直接在以前的函數體內修改指令,用一個跳轉或者其他指令來實現掛鉤的目的。 而普通的hook只是修改函數的調用地址,而不是在原來的函數體里面做修改。
Inline hook原理是解析函數開頭的幾條指令,把他們Copy到數組保存起來,然后用一個調用我們的函數的幾條指令來替換,如果要執行原函數,則在我們函數處理完畢,再執行我們保存起來的開頭幾條指令,然后調回我們取指令之后的地址執行。它需要在程序中嵌入匯編代碼(Inline Assembly)以操作堆棧和執行內核API對應的部分匯編指令。
(7)OBJECT HOOK
OBJECT HOOK是相對于IAT HOOK之類的 API HOOK而言,API HOOK是掛鉤應用層函數,而OBJECT HOOK是掛鉤內核層函數。其原理與API HOOK類似。
(9)IRP HOOK
IRP是 I/O request packets,在Windows中幾乎所有的I/O都是通過包(packet)驅動的,每個單獨的I/O由一個工作命令描述,此命令將會告訴驅動程序需要一些什么操作,并通過I/O子系統跟蹤處理過程。這些工作命令就表現為一個個被稱為IRP的數據結構。IRP HOOK原理是攔截管理器發向文件或網絡系統等驅動程序的IRP。一般通過創建一個上層過濾器設備對象并將之加入系統設備所在的設備堆棧中。也有部分IRP HOOK通過攔截傳遞IRP請求包的函數IofCallDriver或MajorFunction函數表來實現的。
總結
- 上一篇: IDT系列:(二)中断处理过程,使用bo
- 下一篇: STL中的find_if函数