轉帖:淺析鉤子技術

來源:互聯網
上載者:User

From:http://hi.baidu.com/oder/blog/item/12cd0e5559a547c1b645aedb.html

 

鉤子:(Hook)是Windows中提供的一種用以替換DOS下“中斷”的系統機制,中文譯為“掛鈎”或“鉤子”。

         鉤子在軟體中的應用可以說是很廣泛了,想當年學習鉤子那會兒,什麼IAT鉤子,INLINE鉤子......真是有點老牛啃南瓜......

            看多了網上的其他一些關於此話題的文章,感覺對於剛接觸的人不適用,所以今天把經驗與大家分享(高手就不用看了......呵呵.)

           WINDOWS HOOK有什麼用呢?說的明白點就是給特定的某一個事件,說的具體點是給一個函數掛上一個鉤子(我們自己的函數),讓它在執行前先執行我們掛的鉤子(我們掛接的函數),從而達到攔截事件和函數調用等的目的.
          IAT鉤子:IAT(Import Address Table)意思是匯入地址表,有的朋友看不懂了,!什麼是匯入地址表.你可以去下載一個exescope,然後用它開啟一個EXE檔案看看匯入欄,一個 程式在執行時,它所(靜態調用,即不用loadlibrary法)調用的函數,在它被編譯成為一個可執行檔時,這些模組的函數的地址就會被寫入匯入 表,IAT鉤子即是替換IAT表中的這些地址為自己的函數地址,那麼當程式調用到這個地址的時候就會跳到我們的函數裡面來,在這裡替換並不是說我們要去替 換檔案中的IAT表,而是要去替換記憶體中的IAT表,一個可執行檔運行之後,它的程式主體會做為一個模組被載入到記憶體裡,在需要調用函數的時候它會去 IAT表中查詢所調用的函數地址,我們只需修改記憶體中IAT表地址即可,具體修改方法很簡單,這裡不作介紹,那麼怎麼樣去修改呢,換句話說,我們怎麼知道 什麼時候去修改?這個時候就需要用到一個windows系統函數SetWindowsHookEx(方法當然不只這一種,比如用遠程注入也可以,有興趣可 以去網上查詢),這個函數會在運行時負責把我們的DLL檔案帶到與我們所註冊的鉤子有關的所有程式中(注意進程的使用者權限),這就是為什麼使用者態的全域鉤 要做成DLL(動態連結程式庫的原因).

         比如,我們用SetWindowsHookEx註冊一個滑鼠鉤子,並用一個A.DLL的模組與之掛鈎,那麼在WINDOWS系統中響應滑鼠事件的所有程式 會先載入A.DLL,在載入DLL初始化時(執行DLLMAIN函數)我們就可以先在記憶體中找出IAT中的函數地址,再用 WriteProcessMemory或memcpy修改為A.DLL模組內的某個函數(我們掛鈎的函數),那麼這個程式在響應滑鼠事件時會先執行我們掛 好的那個在A.DLL的某個函數,這個時候大權就在我們手裡了,我們可以讓它繼續執行,也可以讓它立即返回無效.同理我們可以掛鈎所有響應鍵盤事件的程式 載入我們的模組以達到監視鍵盤記錄的作用,也可以掛鈎所有響應訊息的程式來掛鈎NtopenProcess和NtTerminateProcess來防止 我們的程式被其他程式結束.也可以掛鈎諸多的API函數來監視系統API的調用,不過在這裡有個誤區,SetWindowsHookEx只會負責把你的 DLL載入到其他的執行程式(不會執行),所以我們的替換動作必須在DLLMAIN函數中(或調用)完成.還有一點要注意IAT HOOK修改的只是IAT表而已,並不是函數本身,而下面這中方法就是直接修改函數本身實現HOOK,同理,都可以用SetWindowsHookEx注 冊一個鉤子把我們的鉤子模組帶到其他進程。那麼它是怎麼實現HOOK的呢?我們需要準備一個5個位元組的BYTE(或CHAR)變數,然後把它的第一個位元組 設為0xE9(16進位),然後把(我們的函數地址-原函數地址-5)(long類型)寫入從第2個位元組開始後的4個位元組,我們都知道LONG類型所佔的 空間剛好為4個位元組(在這眾多類型裡面,不管它的類型怎麼變,它都有以位元組為單位的大小,在我看來,把一個變數叫做int 也好 long 也好,純粹是為了編寫程式方便和好記,因為我們完全可以把int x 定義為 BYTE x[2]),再把這5個位元組複製到記憶體中以原函數(要掛鈎的那個函數)地址為起始點的5個位元組,這麼做的意義是什麼呢?可能有的人不知道0xE9 相當於彙編裡的Jmp指令,(當然有點反組譯碼基礎的人都知道如0xC3 = ret, 0xE9=Jmp,、、很多)在彙編裡jmp是一個跳轉指令,在這裡就是讓它跳轉至後面的4個位元組指示的位置(我們的函數地址),從而達到HOOK的目 的,這就是為什麼叫INLINE HOOK為5位元組跳轉法,同樣的這種方法不僅僅適用於使用者態,它還適用於核心態,這就是SDT INLINE HOOK。
         在系統核心有一個核心檔案的載入的鏡像(核心模組),NTOSKRNL或ntkrnlpa及ntkrnlmp、ntkrnlup、ntkrpamp都是 OS核心檔案,它提供了一整套核心態函數,供使用者態和核心態調用,我們在使用者態調用的函數大多數在最後都進入了核心態如kernel32.dll的 OpenProcess,在調用OpenProcess,以後會進入Ntdll.dll中的NtOpenProcess然後調用系統函數調用號進入核心態 的NtOpenProcess,所以核心態的鉤子才是王道,核心態的鉤子有SSDT HOOK和SDT INLINE HOOK,上面說了,核心匯出了一系列的函數供使用者態調用,那麼匯出的這個函數表就是SSDT(系統服務描述表),它的地址可由核心匯出的一個變數 KeServiceDescriptorTable 查詢,每4個位元組(long 大小)為一個地址,在SSDT HOOK時我們只需要修改SSDT表中的地址為我們的地址即可,相當簡單.

         例:修改NtOpenProcess:
*(ULONG*)(KeServiceDescriptorTable+(0x7A*4))=(ULONG)MyOpenProcess
0x7A為NtOpenProcess的系統調用號,每個調用號佔4個位元組,KeServiceDescriptorTable+(0x7A*4)就代表 了NtOpenProcess地址的存放位置,MyOpenProcess為我們自訂的函數,這樣系統在執行NtOpenProcess的時候就會跳到 MyOpenProcess裡。還有一種就是Inline Hook它和使用者態的一樣直接修改函數前5個位元組即可,這裡不再贅述。但是在核心態的inline hook比較危險,這涉及到多線程調用,有興趣的朋友可以去查閱該方面資料。
          已經講了這幾種HOOK 的實現原理,那麼我們怎麼來預防Hook呢。在使用者態我們可以掛接(inlinehook)LoadLibraryExW來判斷,這個資料在網上很多,朋 友們可以自己去找,還有一點就是,網上的方法不能防止遠程注入HOOK,在LoadLibrary的時候加上判斷TED或PEB就可以防止了。上述原理有 不懂的或具體實現方法可聯絡我QQ:233276111。轉載請保持文章完整性.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.