朋友,你用過Native API函數(shù)嗎?如果你接觸過,也許你知道一個事實:NativeAPI函數(shù)名在兩個不同的模塊里存在重名現(xiàn)象。形象地來說,在Ring3層有一個名字叫NtOpenFile的函數(shù),在Ring0層,也有一個名字叫做NtOpenFile的函數(shù)。他們說處的地方不一樣,而且實現(xiàn)也不一樣。不僅僅是NtOpenFile,所有的NativeAPI函數(shù)都是如此。眾所周知重名有可能引起混亂,就像一個家里的雙胞胎,本來就難分你我,如果連名字也一樣,豈不是神仙也分不清了?但幸運的是,這兄弟兩個從小就被分開來了,而且有專門的法律規(guī)定,他們永遠不可以在同一個地方相見。這真是妙哉,妙哉!所以即使他們重名的話,也不會有錯誤發(fā)生了。其中哥哥永遠只能呆在Ring0的地方,弟弟永遠只能呆在Ring3的地方。有時為了方便,人們也會討巧地把他們叫成:Ring0的某某,Ring3的某某。
上面只是一個簡單的故事,讓我們回到Native API上來。Native API往往功能強大,常常在我們使用了一大堆Win32API的時候,用一個合適的NativeAPI就能把問題輕松解決。而且更有些時候,在使用Win32函數(shù),永遠不能得到合適結果的時候,忽然有好心人告訴你:某一個叫做NativeAPI的地方,有一個函數(shù)名叫×××,它能幫你解決問題。哈哈,愁苦頓解!
如果可能的話,人人都想取得權力,甚至控制權力。NativeAPI也不例外,別人都想擁有它的力量為己所用。在眾多的Hook技術中,被嘗試得最多的,或許就是NativeAPI吧!比如以前寫過進程隱藏的程序,用的方法就是hook函數(shù)NtQuerySystemInformation。NativeAPI的功能所以這么強大,究其原因吧,在Ring3的人們眼里,Native API就是Ring3層的底層!
許多人喜歡舉CreateFile的函數(shù),我們也用它來說話,耳熟能詳嘛!用戶調(diào)用Win32函數(shù)CreateFile,CreateFile做了一點點的處理后,最根本的實現(xiàn)卻并不親自做而是調(diào)用ZwCreateFile函數(shù),ZwCreateFile也是一樣,做了一些處理,最根本的實現(xiàn)也不親自做而是繼續(xù)委托給了NtCreateFile函數(shù)。而接力棒到了NtCreateFile之后,在Ring3層它就再也沒有后繼者了。不想進入煩人的Ring0層的程序員,這里就已經(jīng)到達終點了。
我們試著來分析hook人員的戰(zhàn)斗歷程吧。最原始的時候,所有的人都很老實,有一些人因為技高一籌發(fā)明了Hook技術,世界從此不太平。起先他們只對CreateFile進行自己的處理,加入自己的一些小聰明并且得意洋洋。很久之后有人不滿起來,怒聲怒氣地罵道:你什么東西,我每秒鐘都要用CreateFile無數(shù)次,每次都被你這么搗亂,氣死我也!我難道非用CreateFile不可嗎?Ring3層里面,我還有ZwCreateFile可用呢!于是就有人從此用起了ZwCreateFile來,并且也用得很開心。Hook者見此情況非常不爽,心想你以為這樣就能逃開我的魔掌了嗎?ZwCreateFile我照樣Hook不誤!他這么說著,很快就把ZwCreateFile也Hook掉了。過了不久被Hook者發(fā)現(xiàn)了此情況又極其不爽起來了,他們百般尋找,找到了NtCreateFile,發(fā)現(xiàn)他更加底層,于是就用起來NtCreateFile來。Hook者緊跟其后,發(fā)現(xiàn)NtCreateFile是ntdll.dll中的函數(shù),就對她研究再三并最終把他也Hook掉了。至此,被Hook者在Ring3層雖掘地三尺,卻再也找不到更底層的函數(shù)可以讓他們來逃避那把陰險的鉤子了。
對!Ring3層的NativeAPI存在于ntdll.dll模塊之中。對它的Hook有好幾種成熟的技術,流布于網(wǎng)絡之中。我所熟知的一種是遍歷所有模塊的ITA表,把對應的函數(shù)入口地址該掉。用這種方法的時候,同時要借助Windows消息鉤子,因為系統(tǒng)中的模塊進進出出的,你要對每一個新加載的模塊進行Hook,更改其中的ITA入口地址。另一種是分析ntdll.dll的PE結構,找到你要Hook的函數(shù)的地址,在他的入口處加上你的JMP代碼。
Ring3層這塊地方,我們暫時到此一游結束。在進入Ring0層之前,我們回顧一下NativeAPI兄弟倆。我們已經(jīng)知道他們是永遠不能相見的了,但其實他們有聯(lián)系的途徑。要知道他們畢竟是兄弟倆,他們攜手完成了一連串艱巨的任務。弟弟在Ring3層監(jiān)視一切,然后把消息傳入Ring0層的哥哥那里,讓他處理。那個在中間傳消息的人,叫做SSDT!
Ring0層中的NativeAPI在哪里呢?在模塊ntoskrn.exe(根據(jù)OS版本不同,這個名字會不一樣)中。SSDT是Ring0層中的一個共有數(shù)據(jù)結構,ntoskrn.exe導出了一個變量:KeServiceDescriptorTable,通過這個變量誰都能找到SSDT。SSDT的任務就是負責Native API哥倆的聯(lián)絡工作——中間人。傳遞的消息(Native API函數(shù))數(shù)量是一定的,大概一百多種。Ring0層中的NativeAPI在之家的門口為這百來種消息分別設置了一個處理機并編了號,SSDT有一張信箱地址表能查到消息對應的號碼。如果不出問題的話,一切都能運行得很好,有條不紊。
在這一片和諧之中,不和諧的Hook者出現(xiàn)了。正常的秩序注定要被打亂!Hook者是高明的竊賊。他有兩種方案實施他的hook。
第一種是改變SSDT消息地址表。SSDT不是一個很負責人的人,平時就把那張表放在自家門口,誰都可以來參觀。參觀當然沒有問題,可要是遇到Hook者這樣的人,可就慘了。Hook者隨身攜帶著紙筆和橡皮,他首先在消息表上找到自己要動手腳的消息地址(即NativeAPI函數(shù)地址),把它用紙筆抄寫下來,然后用橡皮把消息表中原來的地址擦掉,寫上自己的新的地址。Hook者瞄著四周無人,得心應手地干完一切,然后吹著口哨走掉了。世界靜悄悄,沒有人發(fā)現(xiàn)發(fā)生了什么變化。當SSDT回來的時候,他也無知無覺,他依舊刻板地照著消息表上的地址發(fā)送著消息,其中一些,就被錯發(fā)進了hook者那里去了,他也放好了自己的處理機在那里等待著。
第二種更絕,改變Native API函數(shù),也就是改變了Native API放在家門口的處理機的構造。一般的做法是,Hook著在函數(shù)的一開始,放置一條JMP指令,讓他跳到自己的處理流程中去,然后再回過來執(zhí)行原函數(shù)中的處理。
這兩種方案,到目前位置,都已經(jīng)變得非常成熟了。反Hook者為此也做了一些措施。比如對第一種改變SSDT地址的下三濫手法,反Hook者往往會預先保存好一個正確的地址表,每隔一段時間,就從頭到尾檢查一下SSDT中的地址表是否被篡改了,如果篡改了就改回來。
本站僅提供存儲服務,所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內(nèi)容,請
點擊舉報。