本發(fā)明涉及計算機技術(shù)領(lǐng)域,特別涉及一種攔截動態(tài)庫注入的方法。
背景技術(shù):
動態(tài)庫注入是windows操作系統(tǒng)提供的一種編程機制,允許一個應(yīng)用程序A把一段代碼注入到另外一個應(yīng)用程序B中去執(zhí)行,用來實現(xiàn)一定的功能。但是這樣可能會造成應(yīng)用程序B運行不穩(wěn)定,甚至出現(xiàn)崩潰。例如,一些殺毒軟件程序會向操作系統(tǒng)中其他進程注入動態(tài)庫,執(zhí)行一些代碼,其中就包含kswebshield.dll這個動態(tài)庫,這個庫中包含一些代碼,會導(dǎo)致被注入的應(yīng)用程序程序運行不穩(wěn)定,經(jīng)常崩潰。
攔截動態(tài)庫注入的目的就是為了防止自身程序遭到其它程序的注入而導(dǎo)致的一系列不穩(wěn)定問題。當動態(tài)庫嘗試加載到當前進程的時候,主動取消操作?,F(xiàn)有技術(shù)中并沒有提供一種實現(xiàn)攔截動態(tài)庫注入的方法。
技術(shù)實現(xiàn)要素:
本發(fā)明技術(shù)方案解決的技術(shù)問題為,如何有效攔截動態(tài)庫注入。
為了解決上述技術(shù)問題,本發(fā)明提供了一種實現(xiàn)攔截動態(tài)庫注入的方法,適于防止外部程序?qū)⒑锌蓤?zhí)行代碼的外部動態(tài)庫注入至本程序進程,包括;
監(jiān)測本程序進程中的目標函數(shù);以及,前置處理如下步驟;
若所述目標函數(shù)被系統(tǒng)動態(tài)庫調(diào)用、且傳入外部動態(tài)庫的文件名與預(yù)置文件名匹配,則拒絕調(diào)用所述目標函數(shù)。
優(yōu)選地,還包括對所述目標函數(shù)進行掛鉤,或者,在所述本程序進程中對所述目標函數(shù)進行掛鉤;
所述監(jiān)測本程序進程中的目標函數(shù)包括若所述目標函數(shù)被調(diào)用,則當調(diào)用消息到達后、在調(diào)用所述目標函數(shù)前,優(yōu)先執(zhí)行所述前置處理。
優(yōu)選地,還包括若所述目標函數(shù)的調(diào)用位置位于所述系統(tǒng)動態(tài)庫的地址,則所述目標函數(shù)被系統(tǒng)動態(tài)庫調(diào)用。
優(yōu)選地,還包括獲取所述系統(tǒng)動態(tài)庫在本程序中的地址范圍及所述目標函數(shù)的返回地址。
優(yōu)選地,所述獲取所述系統(tǒng)動態(tài)庫在本程序中的地址范圍包括:使用GetModuleHandle系列函數(shù)獲??;
獲取所述目標函數(shù)的返回地址包括:使用ReturnAddress函數(shù)獲取。
優(yōu)選地,還包括寫入所需要攔截的動態(tài)庫文件名作為所述預(yù)置文件名。
優(yōu)選地,所述目標函數(shù)是在本程序進程中被所述系統(tǒng)動態(tài)庫調(diào)用函數(shù)主動調(diào)用、并適于加載所述外部動態(tài)庫的。
優(yōu)選地,所述調(diào)用函數(shù)為ClientLoadLibrary,所述目標函數(shù)為LoadLibraryExW。
優(yōu)選地,還包括在拒絕調(diào)用所述目標函數(shù)后繼續(xù)運行本程序。
優(yōu)選地,還包括若所述目標函數(shù)并非被系統(tǒng)動態(tài)庫調(diào)用和/或傳入外部動態(tài)庫的文件名與預(yù)置文件名不一致,則將調(diào)用所述目標函數(shù)的請求傳遞至操作系統(tǒng)。
本發(fā)明技術(shù)方案的有益效果至少包括:
本發(fā)明技術(shù)方案通過對目標函數(shù)掛鉤(API Hook技術(shù)),從本程序進程中識別出需要攔截的動態(tài)庫,然后通過拒絕調(diào)用目標函數(shù)來實現(xiàn)對外部動態(tài)庫的攔截。
本發(fā)明通過預(yù)置需要攔截的動態(tài)庫的方式,使攔截方案更有目的性,在有效攔截有害動庫態(tài)的基礎(chǔ)上,并不阻礙對系統(tǒng)正常運行所需的動態(tài)庫的加載,保持本程序的正常運行。
附圖說明
通過閱讀參照以下附圖對非限制性實施例所作的詳細描述,本發(fā)明的其他特征、目的和優(yōu)點將會變得更明顯:
圖1示出根據(jù)本發(fā)明的第一實施例的,一種攔截動態(tài)庫注入的方法流程圖;
圖2示出根據(jù)本發(fā)明的動態(tài)庫注入的流程概要圖;
圖3示出根據(jù)本發(fā)明的第一實施例的一個變化例的,一種攔截動態(tài)庫注入的方法流程圖;
圖4示出根據(jù)本發(fā)明的第二實施例的,一種攔截動態(tài)庫注入的方法流程圖;
圖5示出根據(jù)本發(fā)明的第三實施例的,一種攔截動態(tài)庫注入的方法流程圖;
圖6示出根據(jù)本發(fā)明的第四實施例的,一種攔截動態(tài)庫注入的方法流程圖。
具體實施方式
為了更好的使本發(fā)明的技術(shù)方案清晰的表示出來,下面結(jié)合附圖對本發(fā)明作進一步說明。
圖1示出根據(jù)本發(fā)明的第一實施例的,一種攔截動態(tài)庫注入的方法流程圖。如上所述,本發(fā)明主要應(yīng)用于Windows操作系統(tǒng)上,但不排除適用在其他操作系統(tǒng)上,如Android OS、Mac OS等,本領(lǐng)域技術(shù)人員理解這樣的控制過程具有重要意義,以殺毒軟件和瀏覽器舉例說明,殺毒軟件會向Windows操作系統(tǒng)中其他進程注入動態(tài)庫,執(zhí)行一些代碼。本領(lǐng)域技術(shù)人員理解,這個庫中包含一些代碼,會導(dǎo)致被注入的應(yīng)用程序程序運行不穩(wěn)定,經(jīng)常崩潰。在實際運行過程中,所述殺毒軟件程序向所述瀏覽器注入動態(tài)庫,為了讓描述具有通用性,在下文中我們以程序A.exe代表殺毒軟件(也可代表任意其他程序),動態(tài)庫C.dll代表需要注入的動態(tài)庫(也可以是其他任意.dll文件),函數(shù)xyz()是所述動態(tài)庫C.dll中的一段代碼,程序B.exe代表瀏覽器(也可以是其他任意程序,如瀏覽器、視屏播放器等)。Windows操作系統(tǒng)提供了一種動態(tài)庫注入的機制,使用Windows API:SetWindowsHook或SetWindowsHookEx兩個函數(shù),可以使所述程序A.exe把所述動態(tài)庫C.dll載入到所述程序B.exe中,并且執(zhí)行所述動態(tài)庫C.dll中包含的所述函數(shù)xyz()(這種情況下是被動的,非自愿的),如圖2示出的動態(tài)庫注入的流程概要圖,具體如下:
1.所述程序A.exe提供一個所述動態(tài)庫C.dll,其中所述C.dll中包含一個需要注入的所述函數(shù)xyz();
2.所述程序A.exe獲得所述程序B.exe的一個線程ID(可以理解為所述程序B.exe的一個資源的標識符),然后調(diào)用所述Windows API,并傳入?yún)?shù)線程ID和函數(shù)xyz()的地址;
3.所述程序B.exe執(zhí)行到特定過程時,即需要實現(xiàn)某項功能時,Windows操作系統(tǒng)就會在當前程序中加載所述動態(tài)庫C.dll,并且調(diào)用所述函數(shù)xyz()。
本發(fā)明技術(shù)方案就是為了解決如何阻止所述程序A.exe將所述函數(shù)xyz()注入到需要保護的程序B.exe中的技術(shù)問題。具體地,如圖1示出的具體步驟如下:
首先進入步驟S101,本程序運行,本程序就是本發(fā)明技術(shù)方案所需要保護程序。
然后進入步驟S102,監(jiān)測本程序進程中的目標函數(shù)。所述目標函數(shù)即用來調(diào)取外部動態(tài)庫的函數(shù)。
進一步地,所述目標函數(shù)是在本程序進程中被所述系統(tǒng)動態(tài)庫調(diào)用函數(shù)主動調(diào)用、并適于加載所述外部動態(tài)庫的。在實際操作過程中,當應(yīng)用程序要加載一個動態(tài)庫并使用其中的功能時,首先要把動態(tài)庫加載到程序的內(nèi)存空間中,而完成這一步調(diào)取任務(wù)所使用的工具即為所述目標函數(shù)。例如,本領(lǐng)域技術(shù)人員理解,在Windows操作系統(tǒng)下,所述目標函數(shù)由Kernel32.dll提供的LoadLibraryExW或LoadLibraryExA函數(shù)。
然后執(zhí)行步驟S103,系統(tǒng)動態(tài)庫調(diào)用所述目標函數(shù)。在本程序進程中,當需要加載動態(tài)庫時,所述目標函數(shù)就會被所述系統(tǒng)動態(tài)庫調(diào)用,所述系統(tǒng)動態(tài)庫即為含有調(diào)取所述目標函數(shù)的工具的動態(tài)數(shù)據(jù)庫,例如,本領(lǐng)域技術(shù)人員理解,在Windows操作系統(tǒng)下,所述系統(tǒng)動態(tài)庫即為User32.dll,所述包含一個功能函數(shù)ClientLoadLibrary,所述功能函數(shù)ClientLoadLibrary用來實現(xiàn)Windows本身提供的動態(tài)庫注入機制,但只能由所述User32.dll使用,不提供給外面的第三方動態(tài)庫使用。
然后進入步驟S104,判斷所述外部動態(tài)庫的文件名與所述預(yù)置文件名是否匹配。所述外部動態(tài)庫即為不屬于所述系統(tǒng)提供的動態(tài)庫,所述外部動態(tài)庫是即將為所述目標函數(shù)調(diào)取的目標動態(tài)庫,所述調(diào)取過程如圖2示出的動態(tài)庫注入的流程。所文件名即以.dll為后綴的動態(tài)庫名,所述預(yù)置文件名即預(yù)先寫入的、需要攔截的動態(tài)庫文件名。所述匹配,即檢測所述傳入外部動態(tài)庫的文件名與所述預(yù)置文件名是否相同,若相同,則斷定所述傳入外部動態(tài)庫為需要攔截的動態(tài)庫。需要強調(diào)的是,例如,本領(lǐng)域技術(shù)人員理解,在Windows操作系統(tǒng)下,所述步驟S103的操作原理是:在正常情況下,所述User32.dll是Windows操作系統(tǒng)的組件,絕無可能命令所述目標函數(shù)(LoadLibraryExW或LoadLibraryExA)調(diào)用外部動態(tài)庫中的函數(shù),出現(xiàn)這種情況基本可以斷定外部動態(tài)庫是被注入到本程序中的。
然后執(zhí)行步驟S105,若匹配,則拒絕調(diào)用所述目標函數(shù)。所述匹配,即所述傳入外部動態(tài)庫為需要攔截的動態(tài)庫,這時,所述目標函數(shù)就會拒絕調(diào)用所述外部動態(tài)庫。
進一步地,圖3示出根據(jù)本發(fā)明的第一實施例的一個變化例的,一種攔截動態(tài)庫注入的方法流程圖。圖3基于圖1,在執(zhí)行步驟S304,拒絕調(diào)用所述目標函數(shù)后,繼續(xù)運行本程序。本發(fā)明技術(shù)方案的宗旨是為了保證所述本程序運行穩(wěn)定,從而攔截所述目標函數(shù)調(diào)取預(yù)置的所述外部動態(tài)庫的函數(shù)。因此,在攔截之后,還是要正常運行所述本程序,從而不影響本程序的功能實現(xiàn)。同時,若再次出現(xiàn)調(diào)用目標函數(shù)的指令,本發(fā)明提供的技術(shù)方案仍能夠繼續(xù)保持對本程序的保護。
圖4示出根據(jù)本發(fā)明的第二實施例的,一種攔截動態(tài)庫注入的方法流程圖。圖4基于圖1,區(qū)別之處在于:通過前置步驟S4021對所述目標函數(shù)進行掛鉤,以監(jiān)測所述目標函數(shù),所述掛鉤即使用鉤子改變所述目標函數(shù)的原有功能,具體地,例如,本領(lǐng)域技術(shù)人員理解,在Windows操作系統(tǒng)下,所述鉤子是Windows消息處理機制的一個平臺,應(yīng)用程序可以在所述平臺上面設(shè)置子程以監(jiān)視窗口的目標消息,并且所監(jiān)視的窗口可以是其他進程所創(chuàng)建的。鉤子機制允許應(yīng)用程序截獲Windows消息或特定事件,即當目標消息到達后,在目標窗口處理函數(shù)之前處理它。
結(jié)合第二實施例,使用API Hook技術(shù)進行掛鉤,所述API(Application Programming Interface,應(yīng)用程序編程接口)是一些預(yù)先定義的函數(shù),目的是提供應(yīng)用程序與開發(fā)人員基于某軟件或硬件得以訪問一組例程的能力,而又無需訪問源代碼,或理解內(nèi)部工作機制的細節(jié)。具體地,通過系統(tǒng)調(diào)用,把所述鉤子掛入所述目標函數(shù),每當特定的消息發(fā)出,在沒有到達目的窗口前,所述鉤子程序就先捕獲該消息,亦即所述鉤子函數(shù)先得到控制權(quán)。其中最后裝載的鉤子最先獲得消息。本發(fā)明使用的一種鉤子為INLINE Hook或IAT Hook,所述INLINE Hook即內(nèi)聯(lián)的函數(shù)鉤子,它可以直接修改要掛鉤的目標函數(shù)的代碼,來實現(xiàn)函數(shù)流程的跳轉(zhuǎn)到預(yù)先設(shè)置的一個函數(shù)里,所述預(yù)先設(shè)置的函數(shù)可以執(zhí)行判斷所述傳入外部動態(tài)庫的文件名與所述預(yù)置文件名是否匹配;所述IAT Hook即為導(dǎo)入表函數(shù)鉤子,通過修改X.exe或者X.dll的導(dǎo)入表來實現(xiàn)函數(shù)流程的跳轉(zhuǎn)到預(yù)先設(shè)置的一個函數(shù)里,所述預(yù)先設(shè)置的函數(shù)可以執(zhí)行判斷所述傳入外部動態(tài)庫的文件名與所述預(yù)置文件名是否匹配。
進一步地,第二實施例的一個變化例,與第二實施例的改進之處在于,在所述本程序進程中對所述目標函數(shù)進行掛鉤。即在本程序進中,則對目標函數(shù)進行掛鉤,并不預(yù)先對所述目標函數(shù)進行掛鉤,這樣,根據(jù)本發(fā)明技術(shù)方案的程序更有目的性,靈活執(zhí)行攔截任務(wù),同時又不會給系統(tǒng)運行造成負擔(dān)。。
圖5示出根據(jù)本發(fā)明的第三實施例的,一種攔截動態(tài)庫注入的方法流程圖。圖5基于圖1,區(qū)別在于,包括步驟S503,判斷所述目標函數(shù)的調(diào)用置位是否位于所述系統(tǒng)動態(tài)庫的地址;若是,則執(zhí)行步驟S504,判斷所述傳入外部的文件名與所述預(yù)置文件名是否匹配。具體地,需要強調(diào)的是,本發(fā)明確定的技術(shù)方案通過監(jiān)測目標函數(shù)的行為找出需要攔截的外部動態(tài)庫,在所述外部動態(tài)庫注入到本程序的路徑中設(shè)置攔截。所述目標函數(shù)的調(diào)用位置是指目標函數(shù)調(diào)取外部動態(tài)庫的位置,動態(tài)庫就是一個系列功能的集合。例如,本領(lǐng)技術(shù)人員理解,在Windows操作系統(tǒng)下,要再屏幕上創(chuàng)建一個窗口,那么程序員可以調(diào)用User32.dll中提供的CreateWindow函數(shù)來實現(xiàn),這里的CreateWindow就是User32.dll提供的用于創(chuàng)建窗口的函數(shù)名字。所述本程序需要加載一個動態(tài)庫并使用其中的功能時,首先需要調(diào)用所述目標函數(shù),所述目標函數(shù)是工具函數(shù),實現(xiàn)調(diào)取其他動態(tài)庫中函數(shù)的功能。通常情況下,所述目標函數(shù)在系統(tǒng)動態(tài)庫里面調(diào)取某個函數(shù),所述函數(shù)必然屬于該系統(tǒng)動態(tài)庫,而本發(fā)明的技術(shù)方案是要防止所述目標函數(shù)通過系統(tǒng)動態(tài)庫調(diào)取到外部動態(tài)庫中的函數(shù)。在明確前述思路后,實現(xiàn)攔截之前,首先要判斷所述目標函數(shù)的返回地址是否出自系統(tǒng)動態(tài)庫,如果出自系統(tǒng)動態(tài)庫,則接下來判斷所述被傳入的外部動態(tài)庫的文件名與所述預(yù)置文件名是否匹配,這樣才能明確最終需要攔截的外部動態(tài)庫,防止誤操作。
進一步地,獲取所述系統(tǒng)動態(tài)庫在本程序中的地址范圍及所述目標函數(shù)的返回地址。這一步提供了一種判斷方法,即在步驟S503的基礎(chǔ)上明確如何判斷所述目標函數(shù)的返回地址是否出自所述系統(tǒng)動態(tài)庫。具體地,首先需要獲取所述系統(tǒng)動態(tài)庫在本程序中的地址范圍,然后獲取所述目標函數(shù)的返回地址,所述返回地址即是從子程序返回后,主程序繼續(xù)執(zhí)行的指令地址稱為″返回地址″.返回地址就是主程序中CALL指令后面一條指令的地址。例如,本領(lǐng)域技術(shù)人員理解,在Windows操作系統(tǒng)下,所述系統(tǒng)動態(tài)庫(如User32.d11)在本程序中的地址范圍,如0x600000~0x900000,而所述返回地址的落在了0x600000~0x900000之間時,即證明所述目標函數(shù)將要從所述系統(tǒng)動態(tài)數(shù)據(jù)庫中調(diào)取函數(shù);若所述返回地址落在0x600000~0x900000之外時,則證明所述目標函數(shù)并非將要從所述系統(tǒng)動態(tài)庫中調(diào)取函數(shù)。
進一步地,所述獲取所述系統(tǒng)動態(tài)庫在本程序中的地址范圍包括:使用GetModuleHandle系列函數(shù)獲取,獲取所述目標函數(shù)的返回地址包括:使用ReturnAddress函數(shù)獲取。這一步提供了兩種工具,用于獲取系統(tǒng)動態(tài)庫在本程序中的地址范圍和目標函數(shù)的返回地址。具體地,本領(lǐng)域技術(shù)人員理解,在Windows操作系統(tǒng)下,所述GetModuleHandle系列函數(shù)包括GetModuleHandle和GetModuleHandleEx,這個函數(shù)是由所述Kenerl32.dll提供的函數(shù),用來獲得一個動態(tài)庫的句柄,所述句柄就是編程語言中用來一個物件的標識,要操作一個動態(tài)庫必須先得到庫的所述句柄。_ReturnAddress()是微軟的C++運行時,動態(tài)庫提供的一個編程接口,用來得到當前函數(shù)的返回地址,也就是調(diào)用這個函數(shù)的某個位置。需要說明的是,理論上存在其它的方法去獲得這個返回地址,但是沒有相關(guān)的替換函數(shù)。
結(jié)合上一步,在攔截之前,判斷所述目標函數(shù)是否將要從需要被攔截的外部動態(tài)庫的函數(shù)的方法具體為:例如,本領(lǐng)域技術(shù)人員理解,在Windows操作系統(tǒng)下,首先獲得要判斷的所述系統(tǒng)動態(tài)庫(如user32.dll)在本程序中的地址范圍,如0x600000~0x900000,這可以通過一些Windows API,GetModuleHandle等系列函數(shù)獲得。在當前被調(diào)用的目標函數(shù)中使用windows系統(tǒng)提供的API,_ReturnAddress()獲得當前函數(shù)的返回地址x,判斷x是否在上面的所述系統(tǒng)動態(tài)庫在本程序的范圍之內(nèi),如果是則說明所述目標函數(shù)是被要判斷的所述系統(tǒng)動態(tài)庫(如user32.dll)調(diào)用的,然后進行判斷所述外部動態(tài)庫的文件名與所述預(yù)置文件名是否匹配,如匹配,則拒絕調(diào)用所述目標函數(shù)。
圖6示出根據(jù)本發(fā)明的第四實施例,一種攔截動態(tài)庫注入的方法流程圖。為了進一步保證本程序的運行,在攔截過程中加入如下步驟:
步驟603,若所述目標函數(shù)并非被系統(tǒng)動態(tài)庫調(diào)用,則將調(diào)用所述目標函數(shù)的請求傳遞至操作系統(tǒng),保證所述本程序需要的功能通過所述目標函數(shù)實現(xiàn)。
步驟604,若傳入外部動態(tài)庫的文件與預(yù)置文件名不一致則將調(diào)用所述目標函數(shù)的請求傳遞至操作系統(tǒng),保證所述本程序需要的功能通過所述目標函數(shù)實現(xiàn)。
需要說明的是本發(fā)明提供的技術(shù)方案持續(xù)的為本程序的運行提供保護。所以圖6示出的流程圖為可循環(huán)執(zhí)行,直至本程序停止運行。
以上對本發(fā)明的具體實施例進行了描述。需要理解的是,本發(fā)明并不局限于上述特定實施方式,本領(lǐng)域技術(shù)人員可以在權(quán)利要求的范圍內(nèi)做出各種變形或修改,這并不影響本發(fā)明的實質(zhì)內(nèi)容。