DLL注入的一般步驟為:
(1)取得注入進程ID dwRemoteProcessId;
(2)取得注入DLL的完全路徑,並將其轉換為寬字符模式pszLibFileName;
(3)利用Windows API OpenProcess打開宿主進程,應該開啟下列選項:
a.PROCESS_CREATE_THREAD:允許在宿主進程中創建線程;
b.PROCESS_VM_OPERATION:允許對宿主進程中進行VM操作;
c.PROCESS_VM_WRITE:允許對宿主進程進行VM寫。
(4)利用Windows API VirtualAllocEx函數在遠程線程的VM中分配DLL完整路徑寬字符所需的存儲空間,並利用Windows API WriteProcessMemory函數將完整路徑寫入該存儲空間;
(5)利用Windows API GetProcAddress取得Kernel32模塊中LoadLibraryW函數的地址,這個函數將作為隨后將啟動的遠程線程的入口函數;
(6)利用Windows API CreateRemoteThread啟動遠程線程,將LoadLibraryW的地址作為遠程線程的入口函數地址,將宿主進程里被分配空間中存儲的完整DLL路徑作為線程入口函數的參數以另其啟動指定的DLL;
(7)清理現場。
示范代碼:
//打開目標進程 HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,g_Pid); if (!hProcess) { AfxMessageBox(TEXT("打開進程失敗")); return; } //在目標進程申請一段內存區域 來存放DLL路徑 LPVOID pRemoteBase=VirtualAllocEx(hProcess,NULL,0x1000,MEM_COMMIT,PAGE_READWRITE); if (pRemoteBase==NULL) { AfxMessageBox(TEXT("申請內存區域失敗")); return; } //在目標進程中寫入DLL路徑 寫入的長度要+1 字符串終止符 if (!WriteProcessMemory(hProcess,pRemoteBase,(LPTSTR)(LPCTSTR)DllPath,DllPath.GetLength()+1,NULL)) { AfxMessageBox(TEXT("進程寫入失敗")); //失敗就釋放原先申請的內存區域 撤銷內存頁的提交狀態 VirtualFreeEx(hProcess,pRemoteBase,0x1000,MEM_DECOMMIT); return; } //得到LoadLibraryA的函數地址 因為Kernel32的加載地址在每個應用程序中都一樣 LPTHREAD_START_ROUTINE pfn=(LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32.dll"),"LoadLibraryA"); //創建遠程線程 執行加載 HANDLE hRemoteThread = CreateRemoteThread(hProcess,NULL,0,pfn,pRemoteBase,0,NULL); if (hRemoteThread==NULL) { AfxMessageBox(TEXT("創建遠程線程失敗")); //釋放原先申請的內存區域 撤銷內存頁的提交狀態 VirtualFreeEx(hProcess,pRemoteBase,0x1000,MEM_DECOMMIT); return; } AfxMessageBox(TEXT("成功注入")); //等待線程退出 WaitForSingleObject(hRemoteThread,-1); //釋放原先申請的內存區域 撤銷內存頁的提交狀態 VirtualFreeEx(hProcess,pRemoteBase,0x1000,MEM_DECOMMIT); //關閉句柄 CloseHandle(hRemoteThread); CloseHandle(hProcess);