詳談HOOK API的技術

來源:互聯網
上載者:User

HOOK API是一個永恒的話題,如果沒有HOOK,許多技術將很難實現,也許根本不能實現。這裡所說的API,是廣義上的API,它包括DOS下的中斷,WINDOWS裡的API、中斷服務、IFS和NDIS過濾等。比如大家熟悉的即時翻譯軟體,就是靠HOOK TextOut()或ExtTextOut()這兩個函數實現的,在作業系統用這兩個函數輸出文本之前,就把相應的英文替換成中文而達到即時翻譯;IFS和NDIS過濾也是如此,在讀寫磁碟和收發資料之前,系統會調用第三方提供的回呼函數來判斷操作是否可以允許存取,它與普通HOOK不同,它是作業系統允許的,由作業系統提供介面來安裝回呼函數。

    甚至如果沒有HOOK,就沒有病毒,因為不管是DOS下的病毒或WINDOWS裡的病毒,都是靠HOOK系統服務來實現自己的功能的:DOS下的病毒靠HOOK INT 21來感染檔案(檔案型病毒),靠HOOK INT 13來感染開機磁區(引導型病毒);WINDOWS下的病毒靠HOOK系統API(包括RING0層的和RING3層的),或者安裝IFS(CIH病毒所用的方法)來感染檔案。因此可以說“沒有HOOK,就沒有今天多姿多彩的軟體世界”。

    由於涉及到專利和智慧財產權,或者是商業機密,微軟一直不提倡大家HOOK它的系統API,提供IFS和NDIS等其他過濾介面,也是為了適應殺毒軟體和防火牆的需要才開放的。所以在大多數時候,HOOK API要靠自己的力量來完成。

    HOOK API有一個原則,這個原則就是:被HOOK的API的原有功能不能受到任何影響。就象醫生救人,如果把病人身體裡的病毒殺死了,病人也死了,那麼這個“救人”就沒有任何意義了。如果你HOOK API之後,你的目的達到了,但API的原有功能失效了,這樣不是HOOK,而是REPLACE,作業系統的正常功能就會受到影響,甚至會崩潰。

    HOOK API的技術,說起來也不複雜,就是改變程式流程的技術。在CPU的指令裡,有幾條指令可以改變程式的流程:JMP,CALL,INT,RET,RETF,IRET等指令。理論上只要改變API入口和出口的任何機器碼,都可以HOOK,但是實際實現起來要複雜很多,因為要處理好以下問題:

    1,CPU指令長度問題,在32位系統裡,一條JMP/CALL指令的長度是5個位元組,因此你只有替換API裡超過5個位元組長度的機器碼(或者替換幾條指令長度加起來是5位元組的指令),否則會影響被更改的小於5個位元組的機器碼後面的數條指令,甚至程式流程會被打亂,產生不可預料的後果;

    2,參數問題,為了訪問原API的參數,你要通過EBP或ESP來引用參數,因此你要非常清楚你的HOOK代碼裡此時的EBP/ESP的值是多少;

    3,時機的問題,有些HOOK必須在API的開頭,有些必須在API的尾部,比如HOOK CreateFilaA(),如果你在API尾部HOOK API,那麼此時你就不能寫檔案,甚至不能訪問檔案;HOOK RECV(),如果你在API頭HOOK,此時還沒有收到資料,你就去查看RECV()的接收緩衝區,裡面當然沒有你想要的資料,必須等RECV()正常執行後,在RECV()的尾部HOOK,此時去查看RECV()的緩衝區,裡面才有想要的資料;

    4,內容相關的問題,有些HOOK代碼不能執行某些操作,否則會破壞原API的上下文,原API就失效了;

    5,同步問題,在HOOK代碼裡盡量不使用全域變數,而使用局部變數,這樣也是模組化程式的需要;

    6,最後要注意的是,被替換的CPU指令的原有功能一定要在HOOK代碼的某個地方類比實現。

    下面以ws2_32.dll裡的send()為例子來說明如何HOOK這個函數:

    Exported fn(): send - Ord:0013h

    地址     機器碼             彙編代碼

    :71A21AF4 55               push ebp //將被HOOK的機器碼(第1種方法)

    :71A21AF5 8BEC             mov ebp, esp //將被HOOK的機器碼(第2種方法)

    :71A21AF7 83EC10             sub esp, 00000010

    :71A21AFA 56               push esi

    :71A21AFB 57               push edi

    :71A21AFC 33FF             xor edi, edi

    :71A21AFE 813D1C20A371931CA271   cmp dword ptr [71A3201C], 71A21C93 //將被HOOK的機器碼(第4種方法)

    :71A21B08 0F84853D0000         je 71A25893

    :71A21B0E 8D45F8             lea eax, dword ptr [ebp-08]

    :71A21B11 50               push eax

    :71A21B12 E869F7FFFF         call 71A21280

    :71A21B17 3BC7             cmp eax, edi

    :71A21B19 8945FC             mov dword ptr [ebp-04], eax

    :71A21B1C 0F85C4940000         jne 71A2AFE6

    :71A21B22 FF7508             push [ebp+08]

    :71A21B25 E826F7FFFF         call 71A21250

    :71A21B2A 8BF0             mov esi, eax

    :71A21B2C 3BF7             cmp esi, edi

    :71A21B2E 0F84AB940000         je 71A2AFDF

    :71A21B34 8B4510             mov eax, dword ptr [ebp+10]

    :71A21B37 53               push ebx

    :71A21B38 8D4DFC             lea ecx, dword ptr [ebp-04]

    :71A21B3B 51               push ecx

    :71A21B3C FF75F8             push [ebp-08]

    :71A21B3F 8D4D08             lea ecx, dword ptr [ebp+08]

    :71A21B42 57               push edi

    :71A21B43 57               push edi

    :71A21B44 FF7514             push [ebp+14]

    :71A21B47 8945F0             mov dword ptr [ebp-10], eax

    :71A21B4A 8B450C             mov eax, dword ptr [ebp+0C]

    :71A21B4D 51               push ecx

    :71A21B4E 6A01             push 00000001

    :71A21B50 8D4DF0             lea ecx, dword ptr [ebp-10]

    :71A21B53 51               push ecx

    :71A21B54 FF7508             push [ebp+08]

    :71A21B57 8945F4             mov dword ptr [ebp-0C], eax

    :71A21B5A 8B460C             mov eax, dword ptr [esi+0C]

    :71A21B5D FF5064             call [eax+64]

    :71A21B60 8BCE             mov ecx, esi

    :71A21B62 8BD8             mov ebx, eax

    :71A21B64 E8C7F6FFFF         call 71A21230 //將被HOOK的機器碼(第3種方法)

    :71A21B69 3BDF             cmp ebx, edi

    :71A21B6B 5B               pop ebx

    :71A21B6C 0F855F940000         jne 71A2AFD1

    :71A21B72 8B4508             mov eax, dword ptr [ebp+08]

    :71A21B75 5F               pop edi

    :71A21B76 5E               pop esi

    :71A21B77 C9               leave

    :71A21B78 C21000             ret 0010

    下面用4種方法來HOOK這個API:

    1,把API入口的第一條指令是PUSH EBP指令(機器碼0x55)替換成INT 3(機器碼0xcc),然後用WINDOWS提供的調試函數來執行自己的代碼,這中方法被SOFT ICE等DEBUGER廣泛採用,它就是通過BPX在相應的地方設一條INT 3指令來下斷點的。但是不提倡用這種方法,因為它會與WINDOWS或調試工具產生衝突,而彙編代碼基本都要調試;

    2,把第二條mov ebp,esp指令(機器碼8BEC,2位元組)替換為INT F0指令(機器碼CDF0),然後在IDT裡設定一個中斷門,指向我們的代碼。我這裡給出一個HOOK代碼:

    lea ebp,[esp+12] //類比原指令mov ebp,esp的功能

    pushfd         //儲存現場

    pushad         //儲存現場

    //在這裡做你想做的事情

    popad         //恢複現場

    popfd         //恢複現場

    iretd         //返回原指令的下一條指令繼續執行原函數(71A21AF7地址處)

    這種方法很好,但缺點是要在IDT設定一個中斷門,也就是要進RING0.

    3,更改CALL指令的相對位址(CALL分別在71A21B12、71A21B25、71A21B64,但前面2條CALL之前有一個條件跳轉指令,有可能不被執行到,因此我們要HOOK 71A21B64處的CALL指令)。為什麼要找CALL指令下手?因為它們都是5位元組的指令,而且都是CALL指令,只要保持作業碼0xE8不變,改變後面的相對位址就可以轉到我們的HOOK代碼去執行了,在我們的HOOK代碼後面再轉到目標地址去執行。

    假設我們的HOOK代碼在71A20400處,那麼我們把71A21B64處的CALL指令改為CALL 71A20400(原指令是這樣的:CALL 71A21230)

    而71A20400處的HOOK代碼是這樣的:

    71A20400:

    pushad

    //在這裡做你想做的事情

    popad

    jmp 71A21230   //跳轉到原CALL指令的目標地址,原指令是這樣的:call 71A21230

    這種方法隱蔽性很好,但是比較難找這條5位元組的CALL指令,計算相對位址也複雜。

    4,替換71A21AFE地址上的cmp dword ptr [71A3201C], 71A21C93指令(機器碼:813D1C20A371931CA271,10位元組)成為 call 71A20400

    nop

    nop

    nop

    nop

    nop

    (機器碼:E8 XX XX XX XX 90 90 90 90 90,10位元組)

    在71A20400的HOOK代碼是: pushad

    mov edx,71A3201Ch           //類比原指令cmp dword ptr [71A3201C], 71A21C93

    cmp dword ptr [edx],71A21C93h   //類比原指令cmp dword ptr [71A3201C], 71A21C93

    pushfd //在這裡做你想做的事

    popfd

    popad

    ret

    這種方法隱蔽性最好,但不是每個API都有這樣的指令,要具體情況具體操作。

    以上幾種方法是常用的方法,值得一提的是很多人都是改API開頭的5個位元組,但是現在很多殺毒軟體用這樣的方法檢查API是否被HOOK,或其他病毒木馬在你之後又改了前5個位元組,這樣就會互相覆蓋,最後一個HOOK API的操作才是有效,所以提倡用第3和第4種方法。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.