python dll注入监听_DLL注入和API拦截
讀《Windows核心編程》筆記一?DLL注入和API攔截
在Windows中,每個進程相互獨立,都有自己的私有的地址空間,程序中使用的指針都是進程自己地址空間的一個內(nèi)存地址,無法創(chuàng)建也沒法使用其他進程的指針。這種機制使得各個進程之間不會相互影響,萬一自己出現(xiàn)了問題,也不會影響到其他的進程。對用戶來說,系統(tǒng)更加的穩(wěn)定了,但是對于開發(fā)人員來說,會使我們很難編寫能夠與其他進程通信的應(yīng)用程序或?qū)ζ渌M程進行操控的引用程序。
程序運行是由dll/exe等文件加載并執(zhí)行的,運行過程中也可以動態(tài)的加載其他的DLL。假如,我們可以使應(yīng)用程序在加載dll時加載我們自己寫的DLL,那么我們就可以在我們的DLL中做任何我們想做的事情,可以訪問進程的任何私有地址空間。下面就來介紹如何讓程序加載我們自己的DLL:
1.使用注冊表
2.使用Windows掛鉤
3.使用遠程線程
4.使用木馬DLL,即讓程序加載我們偽裝的DLL
5.通過修改線程內(nèi)存地址的機器指令
1.使用注冊表
這是最簡單的方法,通過系統(tǒng)注冊表來達到注入DLL的目的,系統(tǒng)注冊表中有個AppInit_DLLs鍵值,在如下路徑:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
AppInit_DLLs有可能包含一個或多個DLL的文件名(通過空格或逗號分隔),第一個DLL的文件名可以包含路徑,但其他DLL包含的路徑將被忽略。所以我們最好是將自己的DLL放在系統(tǒng)目錄,然后在注冊表中直接指定文件名即可。添加好DLL后,把鍵值LoadAppInit_DLLs也改為1.這樣就大功告成了,每當新的進程啟動的時候,會去加載系統(tǒng)的User32.dll,User32.dll在處理DLL_PROCESS_DETACH通知時,就會調(diào)用LoadLibrary來載入我們之前填寫在AppInit_DLLs中的所有DLL,并調(diào)用每一個DLL的DllMain函數(shù)。
不過這樣的注入方式只適用于那些GUI程序,因為需要依賴程序是否映射User32.dll,對于那些終端CUI應(yīng)用程序則沒法使用。
2.使用Windows掛鉤
Windows提供的一種機制可以讓我們的一個DLL注入到另一個進程的地址空間,那就是安裝WH_GETMESSAGE掛鉤,例如:
HHOOK hHook = SetWindowsHookEx(WH_GETMESSAGE, MyMsgProc, hInstDll, 0);
MyMsgProc是我們自己的消息處理過程,hInstDll的值是進程地址空間中DLL被映射后的虛擬內(nèi)存地址,最后一個參數(shù)0表示給所有的GUI線程安裝掛鉤。假設(shè)有一個線程給某個窗口發(fā)一條消息,系統(tǒng)會先檢查你有沒有安裝WH_GETMESSAGE掛鉤,然后把MyMsgProc所在的DLL映射至進程空間,并調(diào)用MyMsyProc函數(shù)。由于系統(tǒng)將掛鉤函數(shù)所在DLL映射到進程地址空間時,會映射整個DLL,而不僅僅只是MyMsgProc,這就意味著DLL內(nèi)的所有函數(shù)都存在于進程B中。這時我們可以用SetWindowLongPtr去派生一個子類窗口,這樣就可以截獲窗口的處理過程。
3.使用遠程線程來注入DLL
DLL注入技術(shù)唯一的目標就是讓別的程序加載我們的DLL,這樣我們就可以在我們自己的DLL中做任何我們想做的事情。但是我們無法輕易的控制別人進程的線程,因此就要求我們在目標進程中創(chuàng)建一個新的線程。幸運的是,微軟直接給我們提供了這樣的API,那就是CreateRemoteThread函數(shù),它使得我們可以在別的程序中創(chuàng)建一個新的線程,函數(shù)原型如下:
HANDLE WINAPI CreateRemoteThread(
__in HANDLE hProcess,
__in LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in?SIZE_T?dwStackSize,
__in LPVOID lpParameter,
__in DWORD dwCreationFlags,
__out LPDWORD lpThreadId
);
其實這個函數(shù)與CreateThread函數(shù)是一樣的,只不過多了一個hProcess參數(shù)。lpStartAddress這個函數(shù)的內(nèi)存地址應(yīng)該存在于遠程進程空間中,因為線程函數(shù)不可能在別的進程的地址空間中。
好了,現(xiàn)在我們實現(xiàn)了在別的進程中創(chuàng)建一個線程,那么怎么讓線程去執(zhí)行LoadLibrary函數(shù),又怎么加載我們自己的DLL呢?實際上我們可以讓lpStartAddress參數(shù)直接就是LoadLibrary函數(shù)的地址,這樣就不用擔心線程怎么去執(zhí)行了。
由于每一個進程在加載Kernel32.dll時,基本上都被映射到了同一個地址。這樣我們可以使用GetProcAddress來獲取LoadLibrary在Kernel32中的偏移地址,再加上kernel32在自己進程的base地址:
PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(_T("Kernel32")), "LoadLibraryW");
HANDLE hThread = CreateRemoteThread(hProcessRemote, NULL, 0, pfnThreadRtn, "MyLib.Dll", 0, NULL);
"MyLib.Dll"這串字符串需要通過VirtualAlloEx在遠程進程中分配一塊內(nèi)存,然后通過WriteProcessMemory寫入那塊新申請的內(nèi)存,然后把參數(shù)"MyLib.Dll"替換掉,這樣就可以了,現(xiàn)在我們的DLL就已經(jīng)進入到了遠程的進程中,可以隨心所欲了。
4.使用木馬DLL,即讓程序加載我們偽裝的DLL
5.通過修改線程內(nèi)存地址的機器指令
這兩種方式下回分解
總結(jié)
以上是生活随笔為你收集整理的python dll注入监听_DLL注入和API拦截的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vsftpd配置详解
- 下一篇: Oracle RMAN备份与还原