日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

DLL注入——使用远程线程

發布時間:2023/12/31 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 DLL注入——使用远程线程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.簡介

從根本上來說,DLL注入技術要求目標進程中的一個線程調用LoadLibrary來載入我們想要的DLL。由于我們不能輕易地控制別人進程中的線程,因此這種方法要求我們在目標進程中創建一個新的線程,Windows提供了創建遠程線程的函數。

HANDLE CreateRemoteThread([in] HANDLE hProcess,[in] LPSECURITY_ATTRIBUTES lpThreadAttributes,[in] SIZE_T dwStackSize,[in] LPTHREAD_START_ROUTINE lpStartAddress,[in] LPVOID lpParameter,[in] DWORD dwCreationFlags,[out] LPDWORD lpThreadId );
  • hProcess:用于創建線程的進程的句柄。
  • lpThreadAttributes:指向SECURITY_ATTRIBUTES結構的指針,該結構確定返回的句柄是否可以被子進程繼承。
  • dwStackSize:堆棧的初始大小,以字節為單位。如果此參數為零,則新線程使用默認大小。
  • lpStartAddress:指向線程要執行的應用程序定義函數的指針。
  • lpParameter:指向要傳遞給線程的變量的指針。
  • dwCreationFlags:控制線程創建的標志。
  • lpThreadId:指向接收線程標識符的變量的指針。如果該參數為NULL,則不返回線程標識符。

2.步驟

  • 用VirtualAllocEx函數在遠程進程的地址空間中分配一塊內存。
  • 用WriteProcessMemory函數把DLL的路徑名復制到第一步分配的內存中。
  • 用GetProcAddress函數來得到LoadLibraryW或LoadLibraryA函數的實際地址(在Kernel32.dll中)
  • 用CreateRemoteThread函數在遠程進程中創建一個線程,讓新線程調用正確的LoadLibrary函數并在參數中傳入第一步分配的內存地址。這時,DLL已經被注入到遠程進程的地址空間中,DLL的DllMain函數會收到DLL_PROCESS_ATTACH通知并且執行我們想要執行的代碼。
  • VirtualFreeEx來釋放第1步分配的內存。
  • 用GetProcAddress函數來得到FreeLibrary函數的實際地址(在Kernel32.dll中)
  • 用CreateRemoteThread函數在遠程進程中創建一個線程,讓新線程調用FreeLibrary函數并在參數中傳入遠程DLL的HMODULE。

步驟1、2、3原理簡介:

字符串“D://remoteDll.dll”,位于調用進程的空間地址中,我們把這個地址傳給新創建的遠程線程,遠程線程再把它傳給LoadLibrary,當LoadLibrary去訪問這個內存地址的時候,DLL的路徑字符串并不在那里,遠程進程的線程就很可能引發訪問違規。為了解決這個問題,我們需要把DLL的字符串存放到遠程進程的地址空間中去,所以會使用VirtualAllocEx和WriteProcessMemory方法。

3.示例

3.1先做一個動態庫remoteDll.dll

此庫的功能是,一旦被注入到進程的地址空間中,就報告該進程正在使用的所有DLL,并將打印信息寫入到本地文件D://out.txt中。

const char* filepath = "D://out.txt";BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved) {switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:{FILE* fp = freopen(filepath, "w", stdout);PBYTE pb = NULL;MEMORY_BASIC_INFORMATION mbi;while (VirtualQuery(pb, &mbi, sizeof(mbi)) == sizeof(mbi)){int nlen;char szModName[MAX_PATH];if (mbi.State == MEM_FREE)mbi.AllocationBase = mbi.BaseAddress;if ((mbi.AllocationBase == hModule) || (mbi.AllocationBase != mbi.BaseAddress) || (mbi.AllocationBase == NULL))nlen = 0;else{nlen = GetModuleFileNameA((HINSTANCE)mbi.AllocationBase, szModName, _countof(szModName));}if (nlen > 0){char szBuf[MAX_PATH] = { 0 };wsprintfA(szBuf, "\n%p-%s", mbi.AllocationBase, szModName);printf("%s\n", szBuf);}pb += mbi.RegionSize;} fclose(fp);}break;case DLL_THREAD_ATTACH:case DLL_THREAD_DETACH:case DLL_PROCESS_DETACH:break;}return TRUE; }

3.2寫一個測試程序

新建一個帶界面的程序

改了一下窗口界面,這里加了一個菜單項注入。

點擊注入出現彈窗,如下圖所示。

輸入進程ID,點擊確定即可,下面是注入的回調函數。

// “注入”框的消息處理程序。 INT_PTR CALLBACK Inject(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {UNREFERENCED_PARAMETER(lParam);switch (message){case WM_INITDIALOG:{return (INT_PTR)TRUE;}case WM_COMMAND:if (LOWORD(wParam) == IDOK){//獲取ID值DWORD processID = GetDlgItemInt(hDlg, IDC_EDIT1, NULL, FALSE);if (processID == 0){processID = GetCurrentProcessId();}if (InjectLib(processID, TEXT("D://remoteDll.dll"))){printf("inject ok");EjectLib(processID, TEXT("D://remoteDll.dll"));}else{printf("inject failed");}EndDialog(hDlg, LOWORD(wParam));return (INT_PTR)TRUE;}else if (LOWORD(wParam) == IDCANCEL){EndDialog(hDlg, LOWORD(wParam));return (INT_PTR)TRUE;}break;}return (INT_PTR)FALSE; }

InjectLib函數如下:

BOOL WINAPI InjectLib(DWORD processID, PCWSTR pszLibFile) {BOOL bOk = FALSE;HANDLE hProcess = NULL, hThread = NULL;PWSTR pszLibFileRemote = NULL;__try{hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD |PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, processID);if (hProcess == NULL)__leave;int cch = 1 + lstrlenW(pszLibFile);int cb = cch * sizeof(wchar_t);pszLibFileRemote = (PWSTR)VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);if (pszLibFileRemote == NULL)__leave;if (!WriteProcessMemory(hProcess, pszLibFileRemote, (PVOID)pszLibFile, cb, NULL))__leave;FARPROC pfnThreadRtn = GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");if (pfnThreadRtn == NULL)__leave;hThread = CreateRemoteThread(hProcess, NULL, 0, (PTHREAD_START_ROUTINE)pfnThreadRtn, pszLibFileRemote, 0, NULL);if (hThread == NULL)__leave;WaitForSingleObject(hThread, INFINITE);bOk = TRUE;}__finally{if (pszLibFileRemote != NULL)VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);if (hThread != NULL)CloseHandle(hThread);if (hProcess != NULL)CloseHandle(hProcess);}return bOk; }

EjectLib函數如下:

BOOL WINAPI EjectLib(DWORD processID, PCWSTR pszLibFile) {BOOL bOk = FALSE;HANDLE hthSnapshot = NULL;HANDLE hProcess = NULL, hThread = NULL;PWSTR pszLibFileRemote = NULL;__try{//獲取指定進程的快照,以及這些進程使用的堆、模塊和線程。hthSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processID);if (hthSnapshot == INVALID_HANDLE_VALUE)__leave;MODULEENTRY32W me = { sizeof(me) };BOOL bFound = FALSE;BOOL bMoreMods = Module32FirstW(hthSnapshot, &me); //檢索與進程關聯的第一個模塊的信息。for (; bMoreMods; bMoreMods = Module32NextW(hthSnapshot, &me)) //檢索與進程或線程關聯的下一個模塊的信息{bFound = (_wcsicmp(me.szModule, pszLibFile) == 0) || (_wcsicmp(me.szExePath, pszLibFile));if (bFound)break;}if (!bFound)__leave;hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD |PROCESS_VM_OPERATION, FALSE, processID);if (hProcess == NULL)__leave;FARPROC pfnThreadRtn = GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "FreeLibrary");if (pfnThreadRtn == NULL)__leave;//me.modBaseAddr 在所屬進程的上下文中模塊的基地址。hThread = CreateRemoteThread(hProcess, NULL, 0, (PTHREAD_START_ROUTINE)pfnThreadRtn, me.modBaseAddr, 0, NULL);if (hThread == NULL)__leave;WaitForSingleObject(hThread, INFINITE);bOk = TRUE;}__finally{if (hthSnapshot != NULL)CloseHandle(hthSnapshot);if (hThread != NULL)CloseHandle(hThread);if (hProcess != NULL)CloseHandle(hProcess);}return bOk; }

3.3執行程序

打開一個記事本程序,找到PID,如下圖所示,PID = 20752。

運行3.2中的程序,輸入這個PID,點擊確定注入成功。

3.4運行結果

注入之后,在本地文件out.txt中,可以看見正在該記事本程序正在使用的DLL。

總結

以上是生活随笔為你收集整理的DLL注入——使用远程线程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。