基于OD插件的內(nèi)核調(diào)試器的設(shè)計(jì)與實(shí)現(xiàn)_第1頁(yè)
基于OD插件的內(nèi)核調(diào)試器的設(shè)計(jì)與實(shí)現(xiàn)_第2頁(yè)
基于OD插件的內(nèi)核調(diào)試器的設(shè)計(jì)與實(shí)現(xiàn)_第3頁(yè)
基于OD插件的內(nèi)核調(diào)試器的設(shè)計(jì)與實(shí)現(xiàn)_第4頁(yè)
基于OD插件的內(nèi)核調(diào)試器的設(shè)計(jì)與實(shí)現(xiàn)_第5頁(yè)
已閱讀5頁(yè),還剩31頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、目 錄 TOC o 1-3 u 1緒論 PAGEREF _Toc262138811 h 2研究背景 PAGEREF _Toc262138812 h 2本文的主要研究?jī)?nèi)容 PAGEREF _Toc262138813 h 32 Windows系統(tǒng)基礎(chǔ) PAGEREF _Toc262138814 h 42.1 OD插件知識(shí) PAGEREF _Toc262138815 h 42.1.1 OD插件簡(jiǎn)介 PAGEREF _Toc262138816 h 42.1.2 如何編寫(xiě)OD插件 PAGEREF _Toc262138817 h 5Windows系統(tǒng)理論知識(shí) PAGEREF _Toc262138818 h

2、 52.2.1 Windows進(jìn)程虛擬地址空間 PAGEREF _Toc262138819 h 5Windows系統(tǒng)調(diào)用 PAGEREF _Toc262138820 h 6Windows 句柄理解 PAGEREF _Toc262138821 h 7Windows 切換進(jìn)程空間 PAGEREF _Toc262138822 h 8Windows調(diào)試系統(tǒng)原理 PAGEREF _Toc262138823 h 8Windows調(diào)試系統(tǒng)用戶(hù)模塊 PAGEREF _Toc262138824 h 8Windows調(diào)試系統(tǒng)內(nèi)核模塊 PAGEREF _Toc262138825 h 93系統(tǒng)需求分析 PAGEREF

3、 _Toc262138826 h 9存在的主要問(wèn)題 PAGEREF _Toc262138827 h 9解決方案 PAGEREF _Toc262138828 h 10系統(tǒng)需求分析 PAGEREF _Toc262138829 h 10系統(tǒng)流程圖 PAGEREF _Toc262138830 h 124系統(tǒng)概要設(shè)計(jì) PAGEREF _Toc262138831 h 13應(yīng)用程序模塊 PAGEREF _Toc262138832 h 13內(nèi)核驅(qū)動(dòng)模塊 PAGEREF _Toc262138833 h 145系統(tǒng)詳細(xì)設(shè)計(jì) PAGEREF _Toc262138834 h 15的KiFastSystemCall()

4、函數(shù) PAGEREF _Toc262138835 h 15實(shí)現(xiàn)HOOK的HxKiFastSystemCall(),改變系統(tǒng)調(diào)用的流程 PAGEREF _Toc262138836 h 16解析微軟提供的PDB文件得到未導(dǎo)出的內(nèi)核函數(shù)地址 PAGEREF _Toc262138837 h 18向Windows系統(tǒng)內(nèi)核中加入我們自己的系統(tǒng)服務(wù)表 PAGEREF _Toc262138838 h 24實(shí)現(xiàn)我們自己的系統(tǒng)調(diào)用函數(shù) PAGEREF _Toc262138839 h 27移除EPROCESS-DebugPort端口 PAGEREF _Toc262138840 h 31HOOK Windows 內(nèi)核

5、下會(huì)發(fā)送調(diào)試事件的內(nèi)核函數(shù) PAGEREF _Toc262138841 h 32HOOK Windows內(nèi)核異常處理函數(shù) PAGEREF _Toc262138842 h 35系統(tǒng)開(kāi)發(fā)小結(jié) PAGEREF _Toc262138843 h 36參考文獻(xiàn) PAGEREF _Toc262138844 h 36致 謝 PAGEREF _Toc262138845 h 37基于OD插件的內(nèi)核調(diào)試器的設(shè)計(jì)與實(shí)現(xiàn)摘要:隨著計(jì)算機(jī)互聯(lián)網(wǎng)技術(shù)的飛速發(fā)展,網(wǎng)絡(luò)游戲得到了很好的發(fā)展,它的保護(hù)也是日趨完善,幾種常見(jiàn)的保護(hù)有nProtect GameGuard(NP), hackshield(HS),讓OllyDbg調(diào)試器

6、(OD)不能調(diào)試,Cheat Engine(CE)不能搜索游戲內(nèi)存,讓人們沒(méi)法開(kāi)始逆向它們,本文即在這種背景下為了滿足人們的工作需求而設(shè)計(jì)的。系統(tǒng)以VC 應(yīng)用程序編譯器和WIN DDK 驅(qū)動(dòng)編譯器作為開(kāi)發(fā)工具,以O(shè)D調(diào)試器提供的靜態(tài)庫(kù),Window Research Kernel(WRK)的源碼為基礎(chǔ),HOOK KiFastSystemCall()函數(shù),通過(guò)我們自己在Windows內(nèi)核下加的系統(tǒng)服務(wù)表,使其當(dāng)OD調(diào)試器調(diào)用我們感興趣的系統(tǒng)調(diào)用時(shí),跳到我們自己的系統(tǒng)調(diào)用,這樣使其成功調(diào)用,突破游戲的一般保護(hù),本文以C語(yǔ)言為編程語(yǔ)言,本系統(tǒng)是一個(gè)具有實(shí)際應(yīng)用意義的典型系統(tǒng)。關(guān)鍵詞:OD插件;NP;

7、HS;游戲保護(hù);OD plug-in based on the kernel debugger Design and ImplementationAbstract: With the rapid development of Internet technology, computer, online games have been well developed, and its protection is also maturing, several common protect nProtect GameGuard (NP), hackshield (HS), let OllyDbg deb

8、ugger (OD) can notdebugging, Cheat Engine (CE) can not search for games of memory, so that people can not start reverse them, this is in this context in order to meet the needs of people work designed.() function, through our own in the Windows kernel plus the system service table, so that the debug

9、ger is called when the OD system call when we are interested, skip to our own system calls, so call it success, breaking the game in generalprotection of this paper, C language programming language, the system is a typical system, the practical application of significance.Key words: OD Plugins;NP;HS

10、;Game Protect TOC o 1-3 u 1緒論1.1研究背景進(jìn)入二十一世紀(jì)以來(lái),隨著社會(huì)的不斷進(jìn)步和互聯(lián)網(wǎng)產(chǎn)業(yè)技術(shù)的飛速發(fā)展,網(wǎng)絡(luò)游戲得到了空前的流行,研究它的人也越來(lái)越大眾化。因此,因?yàn)榉N種原因,一些游戲和商業(yè)程序就會(huì)防止OD調(diào)試器和CE數(shù)據(jù)搜索器搜索游戲的數(shù)據(jù)防止逆向工作人員逆向這們,一些防調(diào)試方法如下:1, 比如檢測(cè)系統(tǒng)當(dāng)前系統(tǒng)運(yùn)行的進(jìn)程看有沒(méi)有Od和Ce,查找窗口看有沒(méi)有它們,還有就是搜索Od和Ce的特征碼看有沒(méi)有它們,有就退出。2, 調(diào)用IsDebugPresent()函數(shù),檢測(cè)這個(gè)游戲進(jìn)程是不是被調(diào)試。3, Hook DbgUiRemoteBreakIn()函數(shù)防止運(yùn)行

11、int 3斷點(diǎn)中止游戲的程序運(yùn)行,這樣能防止OD調(diào)試器附加游戲進(jìn)程。4, 游戲故意產(chǎn)生異常,然后自己去處理它,如果有調(diào)試的話,異常一般會(huì)先給調(diào)試器,由調(diào)試器處理了,所以游戲就不會(huì)進(jìn)入它自己的異常處理,這樣它就檢測(cè)出了調(diào)試器。5, 還有就是nProtect GameGuard(NP), hackshield(HS),PerfectProtect.sys等等的保護(hù),一般它們都是差不多的,比如系統(tǒng)服務(wù)表(SSDT表)HOOK,內(nèi)核下Inline HOOK,一般HOOK NtOpenProcess()防止打開(kāi)游戲進(jìn)程得到句柄,HOOK NtReadVirtualMemory(),NtWriteVirt

12、ualMemory()防止讀寫(xiě)游戲進(jìn)程空間的內(nèi)存,還有就是HOOK NtDebugActiveProcess(),NtCreateDebugObject(),NtWaitForDebugEvent()等等一系列與調(diào)試有關(guān)的系統(tǒng)調(diào)用防止調(diào)試游戲,還有就是HOOK 每個(gè)CPU的中斷描述符表(IDT)表中的INT 1和INT 3斷點(diǎn),防止對(duì)游戲進(jìn)程下斷產(chǎn)生單步調(diào)試事件和異常調(diào)試事件,還有一種就是內(nèi)核下建立一個(gè)內(nèi)核線程一直對(duì)游戲的進(jìn)程控制塊(EPROCESS)結(jié)構(gòu)體的(調(diào)試端口)DebugPort一直清0,防止游戲被Od調(diào)試收到調(diào)試信息。綜上所述,第5種保護(hù)方法一般是現(xiàn)在最流行的保護(hù),有很多的人們?cè)谘?/p>

13、究它們的保護(hù),他們一般采用的方法是跳過(guò)這些函數(shù)的調(diào)用,比如對(duì)于SSDT HOOK,它們可以在KiFastCallEntry()函數(shù)里進(jìn)行處理,對(duì)于Inline HOOK,我們可以先HOOK SSDT進(jìn)入我們自己的系統(tǒng)調(diào)用,然后才調(diào)用真正的函數(shù),對(duì)于調(diào)試端口端口的內(nèi)核函數(shù),改變這些偏移,使其操作EPROCESS結(jié)構(gòu)中的其它沒(méi)有多大用的結(jié)構(gòu)成員,比如EPROCESS.time。這種方法針對(duì)一般的保護(hù)有效,但是對(duì)于特定的保護(hù),我們可以特別的處理,比如Tessafe.sys你可以把自己加入白名單等等處理方法,還有對(duì)于HS我們可以調(diào)用一個(gè)14號(hào)功能函數(shù)通知HS保護(hù)驅(qū)動(dòng)退出等等許多的方法。本文的主要研究?jī)?nèi)

14、容基于OD插件的內(nèi)核調(diào)試器系統(tǒng)主要是在OD調(diào)試器的基礎(chǔ)上編寫(xiě)OD插件,HOOK OD進(jìn)程空間的的KiFastSystemCall()函數(shù),改變OD進(jìn)程調(diào)用一些關(guān)鍵系統(tǒng)函數(shù)的調(diào)用流程,使其進(jìn)入我們自己在內(nèi)核中的實(shí)現(xiàn)的系統(tǒng)調(diào)用,這樣能夠繞過(guò)一般的保護(hù)驅(qū)動(dòng)的鉤子。本系統(tǒng)是主要分為四個(gè)主要的功能來(lái)實(shí)現(xiàn):1, 編寫(xiě)OD應(yīng)用程序插件,利用OD調(diào)試器提供給我們的靜態(tài)庫(kù)和頭文件來(lái)編寫(xiě)OD插件,在OD調(diào)試器上加個(gè)菜單選項(xiàng)用于控制OD調(diào)試器是不是啟動(dòng)我們的這種程序機(jī)制。比如當(dāng)我們點(diǎn)BeginHook菜單時(shí),我們的程序就開(kāi)始工作,HOOK KiFastSystemCall()函數(shù),Windows提供給程序員的一般的

15、打開(kāi)進(jìn)程O(píng)penProcess(),讀進(jìn)程內(nèi)存ReadVirtualmemory(),寫(xiě)進(jìn)程內(nèi)存WriteVirtualMemory()等等API函數(shù),最終的系統(tǒng)調(diào)用都會(huì)調(diào)用這個(gè)函數(shù),這時(shí)eax是系統(tǒng)調(diào)用ID,堆棧里有調(diào)用這個(gè)系統(tǒng)調(diào)用時(shí)的各個(gè)參數(shù),這樣,我們可以改變這些系統(tǒng)調(diào)用ID,使其調(diào)用我們自己在Windows系統(tǒng)內(nèi)核添加的系統(tǒng)調(diào)用。當(dāng)我們點(diǎn)CancelHook時(shí),我們的程序就停止工作。2, 由于我們內(nèi)核驅(qū)動(dòng)要調(diào)用的很多內(nèi)核函數(shù)是ntkrnelpa.exe內(nèi)核文件未導(dǎo)出的,所以我們要自己獲取內(nèi)核函數(shù)在當(dāng)前系統(tǒng)的地址,很多同學(xué)采用的是暴力搜索內(nèi)存然后匹配方法處理的,這種方法效率欠缺,并且由于

16、好多硬編碼,移值性很差。我是這么做的,在內(nèi)核驅(qū)動(dòng)下,把這些未導(dǎo)出的函數(shù)申明為函數(shù)變量指針,然后用戶(hù)層程序(OD插件)調(diào)用DeviceIoControlFile()函數(shù)和驅(qū)動(dòng)通信取得這些未導(dǎo)出的函數(shù)的名字,然后我們自己解析微軟提供給我們的符號(hào)文件(PDB文件),得到這個(gè)版本系統(tǒng)的未導(dǎo)出的函數(shù)在這個(gè)系統(tǒng)版本的內(nèi)核加載地址。然后再次調(diào)用DeviceIoControlFile()函數(shù)傳給內(nèi)核驅(qū)動(dòng)。3,把微軟提供的Windows Reasarch Kernel(WRK)里的dbgk目錄下的dbgkobj.c,dbgkport.c,dbgkproc.c,dbgkp.h文件移值到我們的內(nèi)核驅(qū)動(dòng)工程里來(lái),這幾

17、個(gè).c文件是Windows系統(tǒng)調(diào)試系統(tǒng)機(jī)制的實(shí)現(xiàn),只要我們集成進(jìn)我們的驅(qū)動(dòng)里來(lái)了,以后游戲保護(hù)對(duì)這些調(diào)試機(jī)制的一切HOOK與檢測(cè),我們可以不用去管它了,相當(dāng)于OD插件它們用的是我們自己集成的調(diào)試系統(tǒng)機(jī)制。還有內(nèi)核線程對(duì)EPROCESS結(jié)構(gòu)體的DebugPort清0,我們也可以跳過(guò)它。還有就是增加游戲常HOOK的幾個(gè)關(guān)鍵函數(shù),比如NtOpenProcess(),NtReadVirtualMemory(),NtWriteVirtualMemory()等等,我們自己在Windows內(nèi)核中實(shí)現(xiàn)它,下次OD調(diào)試器調(diào)用這些函數(shù)對(duì)游戲進(jìn)程操作時(shí),都會(huì)進(jìn)入我們自己的這些系統(tǒng)調(diào)用,到時(shí)想實(shí)現(xiàn)什么功能就實(shí)現(xiàn)什么功

18、能。4, Windows系統(tǒng)內(nèi)核下有兩種系統(tǒng)服務(wù)表KeServiceDescriptorTable和KeServiceDescriptorTableShadow,對(duì)于圖形界面(GUI)線程,它引用的是KeServiceDescriptorTableShadow這個(gè)系統(tǒng)服務(wù)表,非GUI線程引用的是KeServiceDescriptorTable系統(tǒng)服務(wù)表。對(duì)于微軟提供的大多數(shù)API,內(nèi)核下都有專(zhuān)門(mén)對(duì)應(yīng)的系統(tǒng)調(diào)用,比如當(dāng)我們調(diào)用OpenProcess() API函數(shù)時(shí),最終會(huì)調(diào)用系統(tǒng)調(diào)用NtOpenProcess()。每一個(gè)系統(tǒng)調(diào)用ID,在Windows內(nèi)核下都會(huì)對(duì)應(yīng)一個(gè)系統(tǒng)調(diào)用函數(shù),比如NtOp

19、enProcess的系統(tǒng)調(diào)用ID,在Windows Xp 3的系統(tǒng)下ID為122。Windows Xp3 系統(tǒng)大概提供了283個(gè)系統(tǒng)調(diào)用。因此我們自己可以在這兩種系統(tǒng)服務(wù)表的后面加上我們自己的系統(tǒng)調(diào)用函數(shù),對(duì)應(yīng)相應(yīng)的系統(tǒng)調(diào)用ID,這樣當(dāng)OD調(diào)試器調(diào)用我們感興趣的系統(tǒng)調(diào)用時(shí),我們可以改變系統(tǒng)調(diào)用ID,這樣就可以進(jìn)入我們自己實(shí)現(xiàn)的系統(tǒng)調(diào)用函數(shù)。2 Windows系統(tǒng)基礎(chǔ) OD插件知識(shí) OD插件簡(jiǎn)介 OllyDbg 簡(jiǎn)稱(chēng)(OD) 是一款優(yōu)秀的用戶(hù)態(tài)調(diào)試工具。它不僅擁有強(qiáng)大的反匯編能力和動(dòng)態(tài)分析力,還具有良好的擴(kuò)展結(jié)構(gòu),允許用戶(hù)自行開(kāi)發(fā)插件完成特定的工作。OD插件也可以有自己的窗口邏輯和功能函數(shù)。事實(shí)

20、上,我們可以將它看成這樣一個(gè)Windows 程序,它擁有自己的消息循環(huán)和窗口過(guò)程,但它的啟動(dòng)是由OllyDbg 發(fā)起的,具體功能的實(shí)現(xiàn)也通過(guò)調(diào)用OllyDbg 提供的函數(shù)來(lái)實(shí)現(xiàn)的。它的啟動(dòng)過(guò)程如下:在OllyDbg 的啟動(dòng)過(guò)程中,有一步是檢查插件路徑下是否存在DLL 文件。如果存在,逐一進(jìn)行如下掃描:1, 加載該DLL 文件,找到其入口點(diǎn)。2, 通過(guò)回調(diào)函數(shù),獲取插件名稱(chēng)、版本等信息。3, 通過(guò)回調(diào)函數(shù),對(duì)插件進(jìn)行初始化,包括申請(qǐng)資源、恢復(fù)全局參數(shù)等。如果某個(gè)DLL 文件無(wú)法順利執(zhí)行這三步,OllyDbg 的啟動(dòng)將失敗、報(bào)錯(cuò)并退出。OllyDbg 啟動(dòng)以后,會(huì)一直維護(hù)插件的隊(duì)列,在特定時(shí)間向該

21、隊(duì)列發(fā)送消息,或者直接調(diào)用插件中定義的函數(shù),用戶(hù)通過(guò)插件菜單或快捷鍵主動(dòng)執(zhí)行插件某功能。最后,當(dāng)OllyDbg 被關(guān)閉時(shí),還會(huì)調(diào)用插件中的回調(diào)函數(shù),釋放插件申請(qǐng)到的資源,并將需要保存的參數(shù)、配置和附加信息分別予以保存。.2 如何編寫(xiě)OD插件 新建立一個(gè)VC 6.0的工程,把頭文件和靜態(tài)庫(kù)文件加進(jìn)工程里面來(lái),還有在工程里加入/J選項(xiàng),使使char 默認(rèn)為unsigned類(lèi)型,這是OllyDbg 中的約定。然后定義兩個(gè)回調(diào)函數(shù),這是OD插件必需的兩個(gè)回調(diào)函數(shù),ODBG_Plugindata()和ODBG_Plugininit()函數(shù),之所以說(shuō)是回調(diào)函數(shù),是因?yàn)檫@是由OD調(diào)試器調(diào)用它們的。比如我們?cè)?/p>

22、ODBG_Plugindata()回調(diào)函數(shù)中傳遞我們插件的名字進(jìn)去;在ODBG_Plugininit()中把OD窗口句柄保存起來(lái);我們還實(shí)現(xiàn)了幾個(gè)回調(diào)函數(shù),ODBG_Pluginmenu(),ODBG_Pluginaction(),ODBG_Plugindestroy()函數(shù)。這些函數(shù)用于在OD插件菜單中加入菜單選項(xiàng)和我們的響應(yīng)函數(shù)。我們可以在OD插件里面調(diào)用OD提供很多的API函數(shù),比如有Breakpoint functions,Memory functions,Thread functions,Module functions等等許多的函數(shù)庫(kù)。之后編譯成功后把它們放在OD調(diào)試器目錄下的Pl

23、ugin文件夾下就行了。 Windows系統(tǒng)理論知識(shí) Windows進(jìn)程虛擬地址空間如上圖4-1-1,在Windows系統(tǒng)中,每一個(gè)進(jìn)程都有4GB的虛擬地址空間。02GB是Windows進(jìn)程的用戶(hù)空間,2GB到4GB是Windows的內(nèi)核空間。物理地址擴(kuò)展(PAE)除外,這時(shí),每個(gè)進(jìn)程的用戶(hù)空間為03GB。每個(gè)進(jìn)程有4GB的虛擬地址空間,并不是指它真正有4GB的物理內(nèi)存,而是指每個(gè)進(jìn)程都有其頁(yè)目錄表和頁(yè)表,通過(guò)它會(huì)把每個(gè)進(jìn)程映射成4GB虛擬內(nèi)存空間。進(jìn)程用戶(hù)空間0-2GB的映射,頁(yè)表一般會(huì)把進(jìn)程的這段虛擬內(nèi)存空間映射到不同的物理內(nèi)存中。但是有例外,就是Windows常見(jiàn)的DLL和可執(zhí)行映象文件

24、,比如kernel32.dll,ntdll.dll和.exe文件運(yùn)行時(shí)的情況。它們有寫(xiě)入時(shí)復(fù)制(Copy On Write)機(jī)制,在沒(méi)有改寫(xiě)這些代碼前,它們?cè)谖锢韮?nèi)存中只有一份內(nèi)存,所有的進(jìn)程都會(huì)根據(jù)頁(yè)目錄和頁(yè)表映射到這份物理內(nèi)存。但是當(dāng)有一個(gè)進(jìn)程改變這些DLL的內(nèi)容時(shí),寫(xiě)入時(shí)復(fù)制就發(fā)生了。Windows這時(shí)會(huì)把這些內(nèi)容在物理內(nèi)存中拷貝一份,改變這個(gè)進(jìn)程的頁(yè)目錄和頁(yè)表,使之指向這份拷貝的物理內(nèi)存,對(duì)其它的進(jìn)程沒(méi)有任何影響,所以這就是用戶(hù)層HOOK 系統(tǒng)DLL時(shí),只對(duì)本進(jìn)程有效,對(duì)其它進(jìn)程無(wú)效的原因。所以當(dāng)我們HOOK 一個(gè)進(jìn)程的ntdll.dll的KiFastSystemCall()時(shí),它只會(huì)

25、對(duì)我們HOOK的這個(gè)進(jìn)程的KiFastSystemCall()函數(shù)起作用。對(duì)別的進(jìn)程沒(méi)有影響。 進(jìn)程內(nèi)核空間24GB空間的映射,通常系統(tǒng)中每個(gè)進(jìn)程的這段虛擬內(nèi)存空間會(huì)根據(jù)頁(yè)目錄表和頁(yè)表映射到相同的物理內(nèi)存中。比如當(dāng)我們改寫(xiě)一處內(nèi)存,此時(shí)對(duì)每個(gè)進(jìn)程都會(huì)有效的,對(duì)整個(gè)系統(tǒng)也都是有效的。 Windows系統(tǒng)調(diào)用下面以Windows XP3系統(tǒng)分析Windows用戶(hù)層API是怎么調(diào)用系統(tǒng)調(diào)用的全過(guò)程。圖4-1-2是Windows系統(tǒng)進(jìn)行系統(tǒng)調(diào)用的全過(guò)程描述:比如當(dāng)我們用戶(hù)層進(jìn)程調(diào)用常見(jiàn)的API比如Win32 API 比如OpenProcess(),ReadVirtualMemory(),WriteVi

26、rtualMemory(),CreateFile()等等函數(shù),它們接著會(huì)依次調(diào)用ntdll.dll的Zw*函數(shù),Zw*函數(shù)會(huì)傳遞系統(tǒng)調(diào)用ID,然后調(diào)用sysenter指令進(jìn)入ring0,在Windows內(nèi)核下首先執(zhí)行的是KiFastCallEntry()函數(shù),它會(huì)根據(jù)系統(tǒng)調(diào)用ID分別從KeServiceDescriptorTable或者KeServiceDescriptorTableShadow這兩種系統(tǒng)調(diào)用表中取得相應(yīng)的系統(tǒng)調(diào)用函數(shù)地址,然后調(diào)用之。對(duì)于GUI線程是從KeServiceDescriptorTableShadow表中取,非GUI線程是從KeServiceDescriptorTa

27、ble表中取的。所以我們可以HOOK KiFastCallEntry()這個(gè)函數(shù),我們就可以攔截一切的系統(tǒng)調(diào)用。360安全衛(wèi)士就是使用這種方法攔截系統(tǒng)調(diào)用的。當(dāng)這個(gè)系統(tǒng)調(diào)用成功返回后,KiFastCallEntry()函數(shù)會(huì)調(diào)用sysexit指令退出本次的系統(tǒng)調(diào)用,然后返回到用戶(hù)進(jìn)程空間,依次返回到調(diào)用用戶(hù)API的地方。 Windows 句柄理解句柄是Windows系統(tǒng)的特性。你可以簡(jiǎn)單理解為通過(guò)它你就可以訪問(wèn)相應(yīng)的內(nèi)核對(duì)象。其實(shí)Windows是這么設(shè)計(jì)的,每個(gè)進(jìn)程的EPROCESS結(jié)構(gòu)體中都有個(gè)ObjectTable 成員指向進(jìn)程句柄表(HANDLE_TABLE),里面每一項(xiàng)都是HANDLE

28、_TABLE_ENTRY句柄表項(xiàng)。里面放著相應(yīng)對(duì)象的地址,句柄只是這些表項(xiàng)的索引。還有一點(diǎn)值的注意的是句柄是進(jìn)程相關(guān)的。你在本進(jìn)程打開(kāi)的進(jìn)程句柄,在別的進(jìn)程當(dāng)中不能引用它的。它們的結(jié)構(gòu)體定義如下:lkd dt _HANDLE_TABLEnt!_HANDLE_TABLE +0 x000 TableCode : Uint4B /指向_HANDLE_TABLE_ENTRY數(shù)組 +0 x004 QuotaProcess : Ptr32 _EPROCESS /這個(gè)句柄表屬于哪個(gè)進(jìn)程 +0 x008 UniqueProcessId : Ptr32 Void +0 x00c HandleTableLock

29、: 4 _EX_PUSH_LOCK +0 x01c HandleTableList : _LIST_ENTRY +0 x024 HandleContentionEvent : _EX_PUSH_LOCK +0 x028 DebugInfo : Ptr32 _HANDLE_TRACE_DEBUG_INFO +0 x02c ExtraInfoPages : Int4B +0 x030 FirstFree : Uint4B +0 x034 LastFree : Uint4B +0 x038 NextHandleNeedingPool : Uint4B +0 x03c HandleCount : In

30、t4B /句柄表的數(shù)量 +0 x040 Flags : Uint4B +0 x040 StrictFIFO : Pos 0, 1 Bitlkd dt _HANDLE_TABLE_ENTRYnt!_HANDLE_TABLE_ENTRY +0 x000 Object : Ptr32 Void /指向內(nèi)核對(duì)象的地址 +0 x004 GrantedAccess : Uint4B比如當(dāng)我們?cè)谟脩?hù)進(jìn)程調(diào)用OpenProcess() 打開(kāi)進(jìn)程時(shí),它先會(huì)調(diào)ntdll.dll的ZwOpenProcess(),接著會(huì)傳遞NtOpenProcess()的系統(tǒng)調(diào)用ID,調(diào)用KiFastSystemCall()函數(shù),這

31、函數(shù)里面會(huì)調(diào)用sysenter指令進(jìn)入Ring0,然后由KiFastCallEntry()根據(jù)系統(tǒng)調(diào)用ID從KeServiceDescriptorTable或者KeServiceDescriptorTableShadow這兩種系統(tǒng)調(diào)用表中找到NtOpenProcess()調(diào)用之。NtOpenProcess()里面會(huì)根據(jù)要打開(kāi)的進(jìn)程ID還是進(jìn)程名字調(diào)用PsLookupProcessByProcessId()這個(gè)函數(shù)得到這個(gè)進(jìn)程對(duì)象EPROCESS的地址,最后調(diào)用ObOpenObjectByPointer()返回進(jìn)程句柄。ObOpenObjectByPointer()函數(shù)大致工作如下:首先會(huì)增加這

32、個(gè)EPROCESS對(duì)象的引用計(jì)數(shù),然后構(gòu)造一個(gè)_HANDLE_TABLE_ENTRY結(jié)構(gòu),填入對(duì)象的地址,然后把它加進(jìn)這個(gè)用戶(hù)進(jìn)程的句柄表(HANDLE_TBALE)中,最后返回句柄(索引)。 Windows 切換進(jìn)程空間一般而言,如果線程T屬于進(jìn)程P,那么當(dāng)這個(gè)線程在內(nèi)核中運(yùn)行時(shí)的用戶(hù)空間應(yīng)該就是進(jìn)程P的用戶(hù)空間。它也沒(méi)有必要訪問(wèn)到別的用戶(hù)進(jìn)程空間去,可是Windows允許一些跨進(jìn)程的操作,特別是跨用戶(hù)進(jìn)程空間的操作。所以有時(shí)候就需要把當(dāng)時(shí)的用戶(hù)空間切換到別的進(jìn)程空間中去。Windows提供的函數(shù)是KeStackAttachProcess()和KiAttachProcess()。它的原理其實(shí)

33、就是改變CPU的CR3寄存器使之指向要切換進(jìn)程的頁(yè)目錄表。因?yàn)镃PU訪問(wèn)進(jìn)程用戶(hù)層空間地址都是通過(guò)CR3找頁(yè)目錄表,然后通過(guò)Windows內(nèi)存管理器把虛擬地址映射成物理地址才去訪問(wèn)的,所以只要我們改變CR3寄存器就行了。Windows有很多這種跨進(jìn)程的操作,例如調(diào)試DbgkpPostFakeProcessCreateMessages()函數(shù)會(huì)調(diào)用KeStackAttachProcess()這個(gè)函數(shù)切換進(jìn)被調(diào)試進(jìn)程的用戶(hù)層空間中,因?yàn)镈bgkpPostFakeModuleMessages()這個(gè)函數(shù)會(huì)訪問(wèn)被調(diào)試進(jìn)程的進(jìn)程環(huán)境塊(PEB),然后遍歷它的用戶(hù)層模塊鏈表。最后會(huì)調(diào)用KeUnstackD

34、etachProcess()這個(gè)函數(shù)回到OD調(diào)試器的進(jìn)程空間來(lái)。 Windows調(diào)試系統(tǒng)原理Windows調(diào)試系統(tǒng)用戶(hù)模塊 Windows系統(tǒng)在用戶(hù)層提供了很多的調(diào)試API供用戶(hù)程序調(diào)用,它們分別在kernel32.dll和ntdll.dll里面。常見(jiàn)的API有DebugActiveProcess(),DebugActiveProcessStop(),DebugSetProcessKillOnExit(),WaitForDebugEvent(),ContinueDebugEvent()。n調(diào)試函數(shù)有DbgUiDebugActiveProcess(),DbgUiIssueRemoteBreakI

35、n(),DbgUiContinue()等等API函數(shù)。 OD調(diào)試器一般會(huì)枚舉當(dāng)系統(tǒng)系統(tǒng)中的所有進(jìn)程,如果我們要要調(diào)試哪個(gè)進(jìn)程,它就會(huì)調(diào)用DebugActiveProcess()DbgUiConnectToDbg(),這個(gè)函數(shù)里面最終會(huì)調(diào)用ntdll.dll的ZwCreateDebugObject()建立一個(gè)調(diào)試對(duì)象用來(lái)接受調(diào)試事件信息,最終依次會(huì)進(jìn)入NtCreateDebugObject()系統(tǒng)調(diào)用函數(shù)。接著它會(huì)調(diào)用ProcessIdToHandle(PID)打開(kāi)進(jìn)程,它里面會(huì)調(diào)用ZwOpenProcess()函數(shù)打開(kāi)進(jìn)程,如果打開(kāi)進(jìn)程成功,則返回進(jìn)程句柄。DbgUiDebugActivePr

36、ocess()函數(shù)進(jìn)行真正的附加調(diào)試。DbgUiDebugActiveProcess()函數(shù)首先會(huì)調(diào)用ZwDebugActiveProcess()函數(shù),這個(gè)函數(shù)會(huì)把這個(gè)被調(diào)試進(jìn)程的線程事件和模塊事件信息插入在先前建立的調(diào)試對(duì)象中。然后會(huì)調(diào)用DbgUiIssueRemoteBreakin()函數(shù)在被調(diào)試的進(jìn)程空間中建立一個(gè)遠(yuǎn)程線程用于執(zhí)行int 3指令斷點(diǎn),目的是為了中斷到調(diào)試器。之后OD調(diào)試器就會(huì)循環(huán)調(diào)用WaitForDebugEvent()和ContinueDebugEvent()等待調(diào)試事件,然后處理調(diào)試事件信息。Windows調(diào)試系統(tǒng)內(nèi)核模塊Windows系統(tǒng)在內(nèi)核層也有很多的系統(tǒng)函數(shù)用

37、來(lái)支持調(diào)試機(jī)制,比如有NtCreateDebugObject(),DbgkpPostFakeProcessCreateMessages(),DbgkpSetProcessDebugObject(),NtWaitForDebugEvent(),NtDebugContinue(),DbgkInitialize(),DbgkpSendApiMessage(),DbgkCreateThread(),DbgkMapViewOfSection()NtDebugActiveProcess()等等函數(shù)。DbgkInitialize()函數(shù)里面會(huì)調(diào)用ObCreateObjectType()函數(shù)建立一個(gè)調(diào)試對(duì)象類(lèi)

38、型。NtCreateDebugObject()函數(shù)里面會(huì)調(diào)用ObCreateObject()建立一個(gè)調(diào)試對(duì)象,然后再調(diào)用ObInsertObject()函數(shù)把這個(gè)對(duì)象插進(jìn)OD進(jìn)程的句柄表中。NtDebugActiveProcess()函數(shù)里面首先會(huì)調(diào)用DbgkpPostFakeProcessCreateMessages()函數(shù),這個(gè)函數(shù)里面會(huì)依次調(diào)用DbgkpPostFakeThreadMessages()和DbgkpPostFakeModuleMessages()函數(shù)向調(diào)試對(duì)象發(fā)送線程和模塊事件信息。最后會(huì)調(diào)用DbgkpSetProcessDebugObject()這個(gè)函數(shù)把被調(diào)試進(jìn)程的EP

39、ROCESS的DebugPort設(shè)置成NtCreateDebugObject()函數(shù)建立的調(diào)試對(duì)象。當(dāng)建立線程時(shí),Windows系統(tǒng)會(huì)調(diào)用DbgkCreateThread()這個(gè)函數(shù)向這個(gè)調(diào)試對(duì)象發(fā)送建立線程的調(diào)試事件;當(dāng)加載DLL時(shí),Windows系統(tǒng)會(huì)調(diào)用DbgkMapViewOfSection()這個(gè)函數(shù)向這個(gè)調(diào)試對(duì)象發(fā)送加載模塊的調(diào)試事件;當(dāng)被調(diào)試進(jìn)程執(zhí)行用戶(hù)層int 3指令時(shí),Windows系統(tǒng)會(huì)調(diào)用DbgkForwardException()這個(gè)函數(shù)向這個(gè)調(diào)試對(duì)象發(fā)送異常調(diào)試事件。3系統(tǒng)需求分析存在的主要問(wèn)題一般防調(diào)試的程序會(huì)對(duì)NtOpenProcess(),NtReadVirtu

40、alMemory(),NtWriteVirtualMemory(),NtDebugActiveProcess(),NtCreateDebugObject(),NtWaitForDebugEvent()這些函數(shù)進(jìn)行HOOK的,不是SSDT HOOK這些函數(shù),就是Inline HOOK這些函數(shù)。當(dāng)我們用OD調(diào)試器還是CE搜索器,要打開(kāi)它的進(jìn)程并對(duì)其進(jìn)行讀寫(xiě)內(nèi)存時(shí),它都會(huì)禁止操作那進(jìn)程,從而導(dǎo)致我們操作失敗。比如程序?qū)tOpenProcess()函數(shù)HOOK后,防止打開(kāi)進(jìn)程,OD調(diào)試器就看不到那進(jìn)程,對(duì)NtDebugActiveProcess()函數(shù)HOOK后,OD調(diào)試器雖然能看到進(jìn)程,但是不能調(diào)

41、試成功的。他們有可能會(huì)在內(nèi)核下建立系統(tǒng)內(nèi)核線程不停的檢測(cè)它們HOOK代碼的地方會(huì)不會(huì)被恢復(fù)。還有可能會(huì)檢測(cè)他們HOOK的代碼到底有沒(méi)有被調(diào)用。如果沒(méi)有被調(diào)用,則認(rèn)為是我們?cè)谒懊嫣^(guò)去了,這樣它們肯定就檢測(cè)出了異常,他們還有可能會(huì)在內(nèi)核下建立內(nèi)核線程不時(shí)的對(duì)其保護(hù)的進(jìn)程的EPROCESS的DebugPort清0,讓我們的OD調(diào)試器收不到任何調(diào)試事件信息。解決方案基于以上問(wèn)題,我是這么設(shè)計(jì)的,我們的應(yīng)用層OD插件HOOK OD進(jìn)程空間動(dòng)態(tài)庫(kù)的KiFastSystemCall()函數(shù),使其跳到我們自己的HxKiFastSystemCall(),然后對(duì)OD進(jìn)程調(diào)用的相應(yīng)的API函數(shù)進(jìn)行過(guò)濾處理,也就

42、是改變系統(tǒng)調(diào)用ID。然后在Windows系統(tǒng)內(nèi)核下加入我們自己的系統(tǒng)調(diào)用函數(shù)和調(diào)試驅(qū)動(dòng)。當(dāng)OD調(diào)用比較關(guān)鍵的函數(shù),就會(huì)進(jìn)入我們自己的系統(tǒng)調(diào)用。所以對(duì)于別的驅(qū)動(dòng)保護(hù)HOOK的關(guān)鍵函數(shù)就不起用了,對(duì)于一直清除EPROCESS的DebugPort的線程的檢測(cè),我們自己在內(nèi)核下可以不操作要調(diào)試進(jìn)程EPROCESS的Debugport。我們移到另一個(gè)結(jié)構(gòu)體中。這樣也就可以防止它一直對(duì)DebugPort調(diào)試端口清0。系統(tǒng)需求分析根據(jù)以上的分析,為了克服現(xiàn)行OD調(diào)試器存在的不足,得到新系統(tǒng)的功能如下:我們利用OD調(diào)試器插件庫(kù),HOOK OD進(jìn)程空間的ntdll.dll的KiFastSystemCall(),

43、它是一切用戶(hù)層API要進(jìn)行系統(tǒng)調(diào)用的最后入口,然后當(dāng)OD進(jìn)程調(diào)用API函數(shù)時(shí),只要這個(gè)API函數(shù)里會(huì)調(diào)用系統(tǒng)函數(shù)調(diào)用,它都會(huì)跳到我們自己的HxKiFastSystemCall()函數(shù)。在我們自己實(shí)現(xiàn)的HxKiFastSystemCall()函數(shù)中,對(duì)OD進(jìn)程調(diào)用的API函數(shù)進(jìn)行過(guò)濾處理,比如如果是調(diào)用OpenProcess()打開(kāi)進(jìn)程,ReadVirtualMemory()讀進(jìn)程內(nèi)存,WriteVirtualMemory()寫(xiě)進(jìn)程內(nèi)存,DebugActiveProcess()附加進(jìn)程,WaitForDebugEvent()等待調(diào)試事件等等關(guān)鍵函數(shù),我們會(huì)在這里改變它們的系統(tǒng)調(diào)用ID,然后自己調(diào)

44、用sysenter指令進(jìn)入Ring0,sysenter指令是intel CPU公司專(zhuān)門(mén)設(shè)計(jì)的快速系統(tǒng)調(diào)用,它會(huì)改變EIP寄存器,使其指向KiFastCallEntry()函數(shù),因此在當(dāng)前系統(tǒng)中,只要發(fā)生過(guò)系統(tǒng)調(diào)用,不管是哪個(gè)進(jìn)程在要求調(diào)用系統(tǒng)調(diào)用,在Ring0中首先被執(zhí)行的是KiFastCallEntry()函數(shù),然后它會(huì)根據(jù)我們傳來(lái)的系統(tǒng)調(diào)用Id從KeServiceDescriptorTable或者KeServiceDescriptorTableShadow表中去取得相應(yīng)的系統(tǒng)調(diào)用函數(shù)運(yùn)行。由于我們內(nèi)核驅(qū)動(dòng)里面用到的很多內(nèi)核函數(shù)很底層,MS提供的DDK中并沒(méi)有導(dǎo)出這些函數(shù)。比如這些函數(shù)有Nt

45、ReadVirtualMemory(),NtWriteVirtualMemory(),它們都要調(diào)用的MmCopyVirtualMemory()函數(shù),這個(gè)函數(shù)微軟提供的靜態(tài)庫(kù)文件就沒(méi)有導(dǎo)出,還有很多比如MiProtectVirtualMemory(),PsGetNextProcess(),ObDuplicateObject(),等等沒(méi)有導(dǎo)出。我們不能在內(nèi)核驅(qū)動(dòng)中直接調(diào)用,我們可以采用暴力搜索內(nèi)存找特征碼然后得到當(dāng)前系統(tǒng)這些函數(shù)的加載地址,然后加以調(diào)用。這種方法很費(fèi)時(shí)而且通用性不好。我采用另一種方法,我們應(yīng)用程序自己解析微軟提供給我們的PDB符號(hào)文件搜索得到這些未導(dǎo)出函數(shù)的地址,然后傳進(jìn)內(nèi)核驅(qū)動(dòng)這

46、些內(nèi)核函數(shù)的地址,我們內(nèi)核驅(qū)動(dòng)才可以加以調(diào)用這些未導(dǎo)出的函數(shù)。我們要在Windows內(nèi)核下加入我們自己的系統(tǒng)調(diào)用表,Windows內(nèi)核下有兩種系統(tǒng)調(diào)用表,KeServiceDescriptorTable和KeServiceDescriptorTableShadow表。我們自己在非分頁(yè)內(nèi)存中分配一個(gè)服務(wù)表, 先拷貝KeServiceDescriptorTable和KeServiceDescriptorTableShadow兩個(gè)表,然后把我們要加上的系統(tǒng)調(diào)用函數(shù)地址加進(jìn)去,然后寫(xiě)進(jìn)KeServiceDescriptorTable和KeServiceDescriptorTableShadow表中,下

47、次如果OD進(jìn)程調(diào)用我們感興趣的系統(tǒng)調(diào)用的話,KiFastCallEntry()函數(shù)就會(huì)根據(jù)服務(wù)Id從這兩個(gè)表中找到我們的系統(tǒng)調(diào)用,然后調(diào)用之。我們自己的系統(tǒng)調(diào)用很多地方可以參考WRK。WRK是Windows Server 2003系統(tǒng)的內(nèi)核。跟XP還是有點(diǎn)區(qū)別的。對(duì)于很重要的內(nèi)核函數(shù)KeStackAttachProcess()和KiAttachProcess (),這兩個(gè)是Windows系統(tǒng)內(nèi)核切換到別的進(jìn)程空間中的關(guān)鍵函數(shù)。由于有的游戲也有HOOK,我們要自己實(shí)現(xiàn)之用來(lái)跳過(guò)HOOK,功能基本已實(shí)現(xiàn)。有的保護(hù)驅(qū)動(dòng)會(huì)在內(nèi)核下建立內(nèi)核線程一直對(duì)它要保護(hù)的進(jìn)程的EPROCESS的DebugPort端

48、口一直清0,這樣會(huì)導(dǎo)致OD調(diào)試器收不到任何調(diào)試事件信息。我是這么做的,因?yàn)槲覀僌D調(diào)試器調(diào)用的API與調(diào)試有關(guān)的系統(tǒng)內(nèi)核函數(shù)幾乎都是我們自己在內(nèi)核驅(qū)動(dòng)中實(shí)現(xiàn)的函數(shù),所以打算把操作EPROCESS的DebugPort的代碼地方都改下。改成操作另一個(gè)結(jié)構(gòu)體,里面專(zhuān)門(mén)對(duì)應(yīng)要調(diào)試的進(jìn)程的EPROCESS進(jìn)程環(huán)境塊和調(diào)試對(duì)象(DebugObject)。比如NtDebugActiveProcess-DbgkpSetProcessDebugObject()里面會(huì)對(duì)要調(diào)試進(jìn)程的EPROCESS的DebugPort設(shè)置成NtCreateDebugObject()的調(diào)試對(duì)象。這里不們不把被調(diào)試進(jìn)程的EPROCES

49、S的DebugPort設(shè)置成指向那調(diào)試對(duì)象,而是移到上面說(shuō)的結(jié)構(gòu)中去。我們此時(shí)還要HOOK 一些常見(jiàn)的Windows內(nèi)核函數(shù),比如建立線程時(shí),結(jié)束線程時(shí),加載DLL時(shí),怎么會(huì)把調(diào)試事件信息通知到我們建立的這種對(duì)應(yīng)的結(jié)構(gòu)體中。我們要Hook 這些常見(jiàn)的函數(shù)像建立線程時(shí)的PspUserThreadStartup(),它里面會(huì)調(diào)用DbgkCreateThread()向被調(diào)試進(jìn)程EPROCESS的DebugPort發(fā)消息,我們?cè)谶@里要處理,還有就是PspExitThread(),NtMapViewOfSection()等等很多函數(shù)都要處理的。我們還要Hook Windows的內(nèi)核異常處理機(jī)制,比如我們

50、用OD調(diào)試器經(jīng)常F2下的斷點(diǎn),都是int 3斷點(diǎn),我們要這CPU 執(zhí)行Int 3這個(gè)指令時(shí)向相應(yīng)的EPROCESS的DebugPort發(fā)送調(diào)試事件信息,我們就要HOOK Windows的異常處理函數(shù)。系統(tǒng)流程圖如下圖 3-3為整個(gè)系統(tǒng)整體流程圖:4系統(tǒng)概要設(shè)計(jì) 應(yīng)用程序模塊當(dāng)我們把我們寫(xiě)的OD插件放入OD調(diào)試器目錄下的Plugin文件夾中后,OD調(diào)試器啟動(dòng)時(shí)就會(huì)調(diào)用ODBG_Plugindata()這個(gè)回調(diào)函數(shù),我們?cè)谶@里調(diào)用HxLoadKrnl()函數(shù)負(fù)責(zé)加載我們的內(nèi)核驅(qū)動(dòng),我們的插件在OD調(diào)試器插件菜單中加入了以下兩個(gè)菜單選項(xiàng),BeginHook和CacelHook,當(dāng)用戶(hù)點(diǎn)擊BeginH

51、ook后,會(huì)調(diào)用HxKrnl_Init()這個(gè)函數(shù),這個(gè)函數(shù)里面主要是調(diào)用DeviceIoControl()這個(gè)函數(shù)向我們的內(nèi)核驅(qū)動(dòng)依次發(fā)送相關(guān)命令。先是發(fā)送HXIOCTL_INIT這個(gè)命令,要求我們的內(nèi)核驅(qū)動(dòng)從Windows內(nèi)核下得到ntkrnlpa.exe,hal.dll內(nèi)核模塊的加載地址,然后返回給我們的OD應(yīng)用層插件;接著發(fā)送HXIOCTL_GET_FNNUMBERLIST命令,會(huì)取得內(nèi)核國(guó)未導(dǎo)出函數(shù)的個(gè)數(shù),然后發(fā)送HXIOCTL_GET_FNLIST命令,會(huì)取得這些內(nèi)核未導(dǎo)出函數(shù)的名字,之后我們OD插件解析內(nèi)核PDB文件得到這些未導(dǎo)出函數(shù)的地址,然后再次向我們的驅(qū)動(dòng)發(fā)送HXIOCTL

52、_SET_DRIVER命令,通知驅(qū)動(dòng)開(kāi)啟把這些函數(shù)地址設(shè)置到函數(shù)指針變量中。接著OD插件會(huì)發(fā)送HXIOCTL_BEGIN_ADDSERVICE命令,要求驅(qū)動(dòng)在Windows系統(tǒng)內(nèi)核下加入我們自己的系統(tǒng)調(diào)用表。最后OD插件會(huì)調(diào)用Hook()函數(shù)HOOK OD進(jìn)程空間ntdll.dll的KiFastSystemCall()函數(shù),之后當(dāng)OD進(jìn)程再次調(diào)用API時(shí)就會(huì)進(jìn)入我們的函數(shù),我們HxKiFastSystemCall()函數(shù)里面會(huì)對(duì)其系統(tǒng)調(diào)用ID進(jìn)行判斷,如果是我們感興趣的系統(tǒng)調(diào)用ID,我們?cè)谶@里把它改變成我們?cè)趦?nèi)核添加的對(duì)應(yīng)的系統(tǒng)調(diào)用ID,然后調(diào)用sysenter指令一樣的進(jìn)入Ring0,Rin

53、g0的響應(yīng)函數(shù)KiFastCallEntry()會(huì)根據(jù)我們傳進(jìn)來(lái)的系統(tǒng)調(diào)用ID找到我們對(duì)應(yīng)的系統(tǒng)調(diào)用然后調(diào)用之。 內(nèi)核驅(qū)動(dòng)模塊 內(nèi)核驅(qū)動(dòng)模塊有一部分是專(zhuān)門(mén)和我們的OD應(yīng)用層插件通訊用的,當(dāng)我們的OD插件調(diào)用DeviceIoControl()函數(shù)向我們驅(qū)動(dòng)發(fā)送相關(guān)命令時(shí),我們會(huì)在HxCtrl()這個(gè)函數(shù)中做相關(guān)處理,對(duì)于HXIOCTL_INIT命令,我們會(huì)調(diào)用HxGetKenelNameAndLoadAddr()這個(gè)函數(shù)遍歷系統(tǒng)當(dāng)前所有加載的內(nèi)核列表中找到ntkrnlpa.exe和hal.dll,然后返回當(dāng)前的加載地址,返回給我們的應(yīng)用層OD插件,對(duì)于HXIOCTL_GET_FNNUMBERLI

54、ST命令,我們返回內(nèi)核未導(dǎo)出函數(shù)的個(gè)數(shù),對(duì)于HXIOCTL_GET_FNLIST命令,我們返回這些未導(dǎo)出函數(shù)的名字,對(duì)于HXIOCTL_SET_DRIVER命令,我們把OD插件得到的內(nèi)核未導(dǎo)出的函數(shù)地址設(shè)置到函數(shù)指針變量中來(lái),對(duì)于HXIOCTL_BEGIN_ADDSERVICE命令,我們?cè)赪indows內(nèi)核下加入我們自己的系統(tǒng)調(diào)用表,對(duì)于HXIOCTL_FREE這個(gè)命令,我們做好一些卸載善后操作,因?yàn)镺D插件通知我們的內(nèi)核驅(qū)動(dòng)要退出了。內(nèi)核驅(qū)動(dòng)還有一部分就是實(shí)現(xiàn)的這些系統(tǒng)調(diào)用函數(shù)和調(diào)試模塊。5系統(tǒng)詳細(xì)設(shè)計(jì)KiFastSystemCall()函數(shù)下面這是用Windbg看的KiFastSystem

55、Call函數(shù),如下,它只有四個(gè)字節(jié),一般的HOOK至少要5個(gè)字節(jié)以上。所以我們要采用另一種方式HOOK,在ntdll.dll里找到一片沒(méi)有用的內(nèi)存,正好KiFastSystemCall上面10個(gè)字節(jié)就沒(méi)有用到。所以我們可以在這10個(gè)字節(jié)里填入我們最終要跳轉(zhuǎn)到的地址,然后從KiFastSystemCall函數(shù)開(kāi)頭處改寫(xiě)代碼使其跳到KiFastSystemCall-10字節(jié)處就行了,具體的HOOK代碼和UnHook代碼如下:0:001 u KiFastSystemCallntdll!KiFastSystemCall:7c92e4f0 8bd4 mov edx,esp7c92e4f2 0f34 sy

56、senter BOOL HOOK()PCHAR fun;UCHAR HookCode5=0;UCHAR Hook2=0;fun = (PCHAR)GetProcAddress(GetModuleHandle(ntdll.dll),KiFastSystemCall);/得到KiFastSystemCall函數(shù)映射的地址if (fun!= NULL)DWORD lOldProtect;DWORD oldprotect;fun-=10;if(VirtualProtect(PVOID)(DWORD)fun),14,PAGE_EXECUTE_READWRITE,&lOldProtect)/改寫(xiě)代碼段內(nèi)存

57、為可讀寫(xiě)和執(zhí)行的權(quán)限,方便我們能改寫(xiě)代碼段fun0=0 xE9;*(DWORD*)(fun+1)=(DWORD)HxKiFastSystemCall - (DWORD)fun-5);fun+=10;fun0=0 xEB;fun1=0 xF4;VirtualProtect(PVOID)(DWORD)fun-10),14,lOldProtect,&oldprotect);hookFunctionAddr=fun;return TRUE;return FALSE; BOOL UNHOOK()if (hookFunctionAddr!= NULL)DWORD lOldProtect;PCHAR fun

58、 = hookFunctionAddr;if(VirtualProtect(PVOID)(DWORD)fun),4,PAGE_EXECUTE_READWRITE,&lOldProtect)fun0=0 x8b;fun1=0 xd4;VirtualProtect(PVOID)(DWORD)fun),4,lOldProtect,NULL);return TRUE;實(shí)現(xiàn)HOOK的HxKiFastSystemCall(),改變系統(tǒng)調(diào)用的流程當(dāng)OD調(diào)試器調(diào)用一般的API時(shí)比如OpenProcess(),ReadVirtualMemory(),WriteVirtualMemory()函數(shù)時(shí),最終會(huì)進(jìn)入Ki

59、FastSystemCall()這個(gè)函數(shù),從而進(jìn)入我們自己實(shí)現(xiàn)的HxKiFastSystemCall()函數(shù),在進(jìn)入HxKiFastSystemCall函數(shù)的環(huán)境下,eax指向調(diào)用此API對(duì)應(yīng)的系統(tǒng)調(diào)用ID,esp指向堆棧,里面放著用戶(hù)層傳來(lái)的參數(shù)。在這里我們把此函數(shù)定義成_declspec( naked ),這么定義是為了防止編譯器額外的加上優(yōu)化和自動(dòng)保護(hù)堆棧代碼。在此之前我們先要把esp壓棧,保存上下文。然后傳進(jìn)系統(tǒng)調(diào)用ID,然后調(diào)用FilterServiceFun()函數(shù)對(duì)我們感興趣的服務(wù)ID進(jìn)行過(guò)濾改變,然后eax返回的是我們改寫(xiě)過(guò)的系統(tǒng)調(diào)用ID,之后再次調(diào)用sysenter真正的進(jìn)行

60、系統(tǒng)調(diào)用,實(shí)現(xiàn)Ring3進(jìn)入Ring0層,這里沒(méi)用sysenter指令,因?yàn)榫幾g器不識(shí)別它,我用的是二進(jìn)制代碼,具體實(shí)現(xiàn)代碼如下:_declspec( naked ) HxKiFastSystemCall() _asm push esp; /保存堆棧 push eax; /服務(wù)Id call FilterServiceFun; pop esp; mov edx,esp _asm _emit 0 x0F /sysenter指令進(jìn)入ring0 _asm _emit 0 x34extern DWORD MyServiceStartID;int WINAPI FilterServiceFun(DWOR

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論