DLL注入的多种方式
DLL注入的多種方式
注冊表注入
在Windows NT/2000/XP/2003操作系統中,當需要加載user32.dll的程序啟動時,user32.dll會加載注冊表鍵HLM\Software\Microsoft\WindowsNT\CurrentVersion\Windows\AppInit_DIls下面列出的所有模塊。
因此,可以將要注入的模塊所在的路徑寫到AppInit_DIls 鍵下,待游戲進程啟動并將外掛模塊帶入之后,再刪除AppInit_DIls 鍵的值以清除痕跡,其核心函數如下:
//定義鍵值
#define DSTKEY "SOFTWARE\\\Microsoft\\\Windows NT\\\CurrentVersion\\\Windows" //打開主鍵 RegOpenKeyEx (HKEY LOCAL_ MACHINE,DSTKEY,0,KEY_ ALL_ ACCESS,&hKey) ;//設置AppInit_DLLS 鍵的值,其中“cDllPath" 為待注人DLL的路徑 RegSetValueEx (hKey,"AppInit_DLLs",0,REG SZ,cD11Path,strlen( (char*) cDl1Path) +1) ;優點:簡單,易于實現。
缺點:第一,系統重啟后才能實現注入,且對DLL的穩定性要求比較高。建議在虛擬機里使用,如果DLL有問題就會藍屏。第二,易于被ProcessMonitor之類的用于監測注冊表操作的軟件發現。
遠線程注入
遠線程注入的核心思想是利用Windows提供的遠線程機制,在目標進程中開啟一個加載模塊的遠線程,使模塊被該遠線程加載到游戲的地址空間。
遠線程使用的關鍵API有VirtualAllocEx、WriteProcessMemory、CreateRemoteThread和LoadLibrary,它們的聲明如下。
LPVOID WINAPI VirtualAllocEx( HANDLE hProcess, //遠進程句柄 LPVOID lpAddress, //保留頁面的內存地址;一般用NULL自動分配 SIZE_T dwSize, //分配內存的大小 DWORD flAllocationType, DWORD flProtect );BOOL WriteProcessMemory ( HANDLE hProcess, //遠進程句柄 LPVOID lpBaseAddress, //遠進程待寫入的地址 LPVOID lpBuffer, //本進程空間需要寫入到遠進程的地址 DWORD nSize, //lpBuffer所指空間的大小 LPDWORD lpNumberOfBytesWritten //返回實際寫入遠進程的字節數 ) ;HANDLE CreateRemoteThread ( HANDLE hProcess, //遠程句柄 LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, //指向在遠程進程中執行的函數地址 LPVOID lpParameter, //傳入參數 DWORD dwCreationFlags, //創建線程的其他標志 LPDWORD lpThreadId //線程ID。如果為NULL,則不返回 );HMODULE WINAPI LoadLibrary ( _in LPCTSTR lpFileName //待加模塊的文件路徑 );遠線程加載流程,步驟如下:
(1)調用VirtualAllocEx函數在遠進程空間中分配內存
(2)調用WriteProcessMemory函數將模塊的文件路徑寫入遠進程空間。
(3)調用CreateRemoteThread函數開啟遠進程的LoadLibrary遠線程,以加載外掛模塊。
該方式比較古老,基本的保護都已防御此法,就不再過多闡述
優點:簡單,易實現。
缺點:容易被檢測。只要監控本進程對LoadLibrary函數的調用,就可以很好地防御遠線程加載。
依賴可信進程注入
為了躲避反外掛系統的掃描或者分析人員的分析,有時候依賴可信任的第三方進程所進行的轉注入,可能會取得比較好的效果。因services.exe不易調試、權限高、隱蔽性好,所以通過木馬和外掛找services.exe進程是一個明智的選擇。
假設本進程為Main.exe, 待注入模塊為ZRT.dl, 待注入進程為ZRP.exe,經過以下。
(1) Main.exe調用WriteProcessMemory和CreateRemoteThread函數將ZRT.dll注入services.exe中,然后Main.exe調用Sleep函數等待注入完成
(2)service.exe中的ZRT.dllCreateToolhelp32Sanpshot和Process32Next來遍歷進程,如果發現ZRP.exe,就采用遠線程或其他方式將ZRT.dll 注人ZRP.exe進程
(3)Main.exe進程睡眠結束
(4) Main.exe調用CreateToolhelp32Sanpshot和Process32Next遍歷進程,尋找services.exe進程。找到該進程后,遍歷模塊,找到ZRT.dll。
(5)Main.exe 調用CreateRemoteThread遠線程來調用FreeLibrary,將services.exe中的ZRT.dll從services.exe進程中卸載。
優點:隱蔽性好,不易被分析和發現。
缺點:遍歷進程的方法需要改進,可能被假進程欺騙;直接調用API也不好。
APC注入
APC ( Asynchronous Procedure Call,異步過程調用)是在一個特定線程環境下被異步執行的函數,分為用戶模式APC和內核模式APC。每個線程都有一個APC隊列。在用戶模式下,當線程調用SleepEx、WaitForSingleObjectEx等進人“Alterable WaitStatus"狀態(可警告的等待狀態)的時候,系統就會遍歷該線程的APC隊列,然后按照先進先出的順序來執行這些APC。
在用戶模式下,微軟提供了QueueUserAPC這個API來向-一個線程插入APC。下面是QueueUserAPC的聲明。
DWORD WINAPI QueueUserAPC ( _in PAPCFUNC pfnAPC, //指向一個APC函數 in HANDLE hThread, //將要插入APC的線程句柄 in ULONG PTR dwData //APC函數的參數 );下面為APC注入的代碼
// 1.以suspend方式創建待加載的目標進程 if (CreateProcess (sProcName, NULL, NULL, NULL, FALSE, CREATE_ SUSPENDED, NULL, NULL, &st, &pi) ) { // 2.目標進程地址空間分配待加載的DLL路徑空間 lpDllName = VirtualAllocEx (pi.hProcess,NULL, (strlen (sDllName) +1),MEM COMMIT,PAGE READWRITE) ; // 3.把待加載的DLL路徑寫人目標進程空間 if (WriteProcessMemory (pi .hProcess,lpD11Name,sD11Name, strlen(sD11Name),NULL) ) {// 4.獲取LoadLibrary的地址LPVOID nLoadLibrary= (LPVOID) GetProcAddress (GetModuleHandle ("kerne132.d1l"),"LoadLibraryA") ;// 5.調用QueueUserAPC向遠線程插入一個APC,這個APC就是LoadLibraryif (! QueueUserAPC( (PAPCFUNC) nLoadLibrary, pi. hThread, (ULONG_PTR) 1pD1 1Name) ){OutputDebugString("APCInject QueueUserAPC call error!") ;dRet=-6;} } }除了可以通過VirtualAllocEx和WriteProcessMemory函數在目標進程地址空間存放待加載DLL的路徑,還可以通過CreateFileMapping、MapViewOfFile和NtMapViewOfSection函數的組合來映射路徑
優點:比較隱蔽,簡單。
缺點:實現的條件比較苛刻,必須等待進程進入“Alterable WaitStatus"狀態。
消息鉤子注入
SetW indowsHookEx函數是微軟提供給程序開發人員進行消息攔截的一個API。不過,它的功能不僅可以用作消息攔截,還可以進行DLL注入。
SetWindwosHookEx的原型聲明如下。
HHOOK Se tWi ndowsHookEx ( Int idHook, //指示將要安裝的掛鉤處理過程的類型。例如,idHook為“WH_CALLWNDPROC"時代表安裝一個掛鉤處理過程,在系統將消息發送至目標窗口處理過程之前對該消息進行監視。 HOOKPROC lpfn, //指向相應的掛鉤處理過程。 HINSTANCE hMod, //指示了一個DLL句柄。該DLL包含參數lpfn所指向的掛鉤處理過程。 DWORD dwThreadId //指示了一個線程標識符,掛鉤處理過程與線程相關。若此參數值為0,則該掛鉤處理過程與所有現存的線程相關。 );如果要去掉消息鉤子,可以調用UnhookWindowsHookEx函數。
下面是注入的核心代碼。
//利用Windows API SetWindowsHookEx 實現注入DLL BOOL SetWinHKInject (char* pszDllPath,char* pszProcess) {//加載待注人的DLL到本進程空間hMod = LoadLibrary (pszDllPath) ;if (!hMod){return FALSE;}//獲取待注人DLL中導出的消息鉤子過程函數的地址lpFunc = (DWORD) GetProcAddress (hMod, "MyMessageProc") ;if (!lpFunc){FreeLibrary (hMod) ;return FALSE;}//獲取待注入進程的線程IDdwThreadId = GetTargetThreadIdFromProcname (pszProcess) ;if (!dwThreadId){FreeLibrary (hMod) ;return FALSE}//調用SetwindowsHookEx實現消息鉤子注人hook = SetWindowsHookEx (WH_ GETMESSAGE, / /WH KEYBOARD, / /WH_ CALLWNDPROC,(HOOKPROC) 1pFunC,hMod,dwThreadId) ;FreeLibrary (hMod) ;return TRUE; }//待注人DLL導出的消息鉤子函數MyMessageProc _declspec (dllexport) LRESULT MyMessageProc (int code, WPARAM wParam, LPARAM 1Param) {//對消息的處理return CallNextHookEx(g_hhook,code,wParam,lParam); }優點:代碼和原理簡單,容易發現。
缺點:容易被發現。
劫持進程創建注入
如果能在目標進程運行起來之前獲取目標進程的讀、寫等權限,那么注入將容易得多。以下是進程創建的關鍵API和調用序列。
Windows下創建進程的API是CreateProcess,它的原型如下。
BOOL CreateProcess ( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes。 LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID IpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation );主要介紹dwCreationFlags的一個值——CREATE_SUSPENDED的含義。
當給參數dwCreationFlags賦值CREATE_SUSPENDED來調用CreateProcess()函數的時候,該進程的主線程將以掛起的方式啟動,要想恢復主線程的運行,需要調用ResumeThread()函數。劫持進程加載就是在主線程被懸掛和恢復的這段時間內,把dll或代碼注人目標進程的。
步驟為以下三步:
(1)調用以掛起方式調用CreateProcess()函數,創建進程。
(2)采用遠線程方式注入外掛模塊。
(3)調用ResumThread()函數恢復游戲主線程。
但由于現在很多游戲進程在啟動時采用雙進程保護機制,所以即使通過上面的劫持進程成功實現加載,也只不過是注入雙進程保護的第一個進程。為了再次使用劫持進程創建機制來注人真正的游戲進程,需要認識用戶態下進程創建的函數調用序列,如圖
其中的KiFastSystemCall()函數相當于ring3轉ring0的一個通道。CreateProcess()函數最后通過KiFastSystemCall()函數進入內核態。可以在任意層次上通過Hook對應的函數來創建劫持進程,以達到加載的目的。例如,在ring3即將進入ing0的時候,即調用KiFastSystemCall()函數的時候,劫持這個函數的調用,可以實現加載。
優點:不易防御,成功率較高。
缺點:劫持時間不宜過長,否則會被發現;劫持后,如需再次劫持,則需要Hook,因此易被檢測。
總結
DLL注入共四個步驟:
1.附加到目標/遠程進程
2.在目標/遠程進程內分配內存
3.將DLL文件路徑,或者DLL文件,復制到目標/遠程進程的內存空間
4.控制進程運行DLL文件
所有這些步驟是通過調用一系列指定的API函數來完成的。每種技術需要進行特定的設置和選項配置。每種技術都有其優點和缺點
但對于有驅動保護的程序來說,這些都是處于3環層次的注入方法,在0環的保護下3環的注入方法就不太夠看了,要想真正的與驅動保護的程序對抗,只有也進入0環與之抗衡
總結
以上是生活随笔為你收集整理的DLL注入的多种方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用RMAN备份与恢复数据库(2)——参
- 下一篇: lingo入门教程之一 初识lingo