本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/vcforever/archive/2005/03/15/320144.aspx
在上一篇文章《線程的遠程注入》中介紹瞭如何讓其他的進程中執行自己的代碼的一種方法
及自己定義一個線程,在線程體中編寫執行代碼,然後使用VirtualAllocEx函數爲線程體以
及線程中用到的字符常量和調用的MessageBox入口函數地址,在目標進程中開闢存儲區,然
後再通過WriteProcessMemory函數,將這些數據寫入目標進程的地址空間中。最後通過
CreateRemoteThread函數,讓自己的線程運行在目標進程中。
上面的方法需要爲線程和常量在目標進程中開闢足夠的存儲空間,而且這個空間的大小很難
確定,稍不注意就會發生訪問違規的錯誤。
下面我來介紹另外一種在其他進程中執行自己的代碼的方法,讓目標進程加載我們自己編寫的
DLL模塊。
首先我們來創建一個DLL模塊(稍後我們將要把這個DLL加載到目標進程中,讓目標進程來運行
DLL中的代碼)。
我們創建的這個DLL模塊非常簡單,只是得到加載該DLL的進程的ID,然後通過MessageBox函數
顯示出來,當然也可以寫一些複雜的代碼。不過我們這裏只是介紹一下方法,有個顯示結果足
以:)。下面就是DLL模塊的代碼:
- //Test.dll源代碼
- //
- #include <windows.h>
- BOOL APIENTRY DllMain(HANDLE hMoudle, DWORD dwReason, LPVOID lpReserved)
- {
- char* pszProcessId = (char*)malloc(10*sizeof(char));
- switch(dwReason) {
- case DLL_PROCESS_ATTACH:
- _itoa(GetCurrentProcessId(), pszProcessId, 10);
- MessageBox(NULL, pszProcessId, "Notice", MB_ICONINFORMATION | MB_OK);
- case DLL_PROCESS_DETACH:
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- break;
- }
- return TRUE;
- }
下一步我們就可以專注於如何把這個DLL掛接到目標進程中。
首先我們通過OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId)來打開我們試圖加載DLL的進程(注意
進程的打開權限一定要設置爲PROCESS_ALL_ACCESS,因爲我們要在目標進程中創建線程)。
然後我們可以使用CreateRemoteThread來創建LoadLibraryA線程來啓動我們的這個DLL。
LoadLibraryA存在於系統的kernel32.dll中用來加載DLL模塊,該函數只有一個參數就是DLL文件的名稱(該
名稱包括路徑)。由於加載DLL的操作是在其他進程中進行,所以我們必須把DLL的文件名稱拷貝到目標進程
的地址空間中。
我們必須計算出該文件名所佔的內存空間
int nLength = (strlen(pszFileName)+1)*sizeof(char);
接下來使用VirtualAllocEx函數爲DLL文件名在目標進程中分配地址空間,在使用WriteProcessMemory將
DLL的文件名拷貝到剛剛分配的地址中。
下一步就是取得LoadLibraryA函數的入口地址
PTHREAD_START_ROUTINE pfnLoadLibraryA =
(PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32.dll"), "LoadLibraryA");
因爲kernel32.dll模塊是系統的核心模塊,所以該模塊中的函數地址在所有進程中全都相同。
我們在本進程中得到的LoadLibraryA函數的入口地址同樣適用於其他進程。
所有條件已經具備,最後我們使用CreateRemoteThread函數,將LoadLibraryA函數的入口地址以及DLL的文件
名作爲參數,即可讓目標進程加載我們自己的DLL,至於你要讓你的DLL中運行什麼代碼,就自己看着辦吧!
讓遠程進程掛接自己的DLL的思路就是這樣,下面給出完整代碼:
- #include <windows.h>
- #include <psapi.h>
- #include <string>
- #include <iostream>
- #pragma comment(lib, "Psapi.lib")
- //提升進程訪問權限
- void enableDebugPriv()
- {
- HANDLE hToken;
- LUID sedebugnamue;
- TOKEN_PRIVILEGES tkp;
- if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
- return;
- if (!LookupPrivilegue(NULL, SE_DEBUG_NAME, &sedebugnamue)) {
- CloseHandle(hToken);
- return;
- }
- tkp.PrivilegeCount = 1;
- tkp.Privileges[0].Luid = sedebugnamue;
- tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
- if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL))
- CloseHandle(hToken);
- }
- //根據進程名稱取得進程ID,如果有多個運行實例則返回第一個枚舉出來的進程ID
- DWORD getSpecifiedProcessId(const char* pszProcessName)
- {
- DWORD processId[1024], cbNeeded, dwProcessesCount;
- HANDLE hProcess;
- HMODULE hMod;
- char szProcessName[MAX_PATH] = "UnknownProcess";
- DWORD dwArrayInBytes = sizeof(processId)*sizeof(DWORD);
- if (!EnumProcesses(processId, dwArrayInBytes, &cbNeeded))
- return 0;
- //計算數組中的元素個數
- dwProcessesCount = cbNeeded / sizeof(DWORD);
- enableDebugPriv();
- for (UINT i = 0; i < dwProcessesCount; i++) {
- hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId[i]);
- if (!hProcess) {
- continue;
- } else {
- if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) {
- GetModuleBaseName(hProcess, hMod, szProcessName, sizeof(szProcessName));
- if (!_stricmp(szProcessName, pszProcessName)) {
- CloseHandle(hProcess);
- return processId[i];
- }
- }
- }
- }
- CloseHandle(hProcess);
- return 0;
- }
- int main(int argc, char* argv[])
- {
- std::cout << "please input the name of target process !" << std::endl;
- //等待輸入進程名稱
- std::string strProcessName;
- std::cin >> strProcessName;
- //在這裏爲了簡單起見,使用了絕對路徑
- char szDllPath[MAX_PATH] = "D://test.dll";
- char szFileName[MAX_PATH] = "D://test.dll";
- //提升進程訪問權限
- enableDebugPriv();
- if (strProcessName.empty()) {
- MessageBox(NULL, "The target process name is invalid !", "Notice", MB_ICONSTOP);
- return -1;
- }
- //根據進程名稱得到進程ID
- DWORD dwTargetProcessId = getSpecifiedProcessId(strProcessName.c_str());
- HANDLE hTargetProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwTargetProcessId);
- if (!hTargetProcess) {
- MessageBox(NULL, "Open target process failed !", "Notice", MB_ICONSTOP);
- return -1;
- }
- //計算DLL文件名稱所佔的存儲空間
- int memorySize = (strlen(szDllPath) + 1) * sizeof(char);
- //在目標進程中開闢存儲空間,用來存放DLL的文件名稱
- char* pszFileNameRemote = (char*)VirtualAllocEx(hTargetProcess,
- 0, memorySize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
- if (!pszFileNameRemote) {
- MessageBox(NULL, "Alloc dll name string in target process failed !", "Notice", MB_ICONSTOP);
- return -1;
- }
- //將DLL的文件名寫入目標進程地址空間
- if (!WriteProcessMemory(hTargetProcess, pszFileNameRemote,
- (LPVOID)szFileName, memorySize, NULL)) {
- MessageBox(NULL, "Write dll name string to target process failed !",
- "Notice", MB_ICONSTOP);
- return -1;
- }
- PTHREAD_START_ROUTINE pfnStartAddr =
- (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
- HANDLE hRemoteThread = CreateRemoteThread(hTargetProcess,
- NULL, 0, pfnStartAddr, pszFileNameRemote, 0, NULL);
- WaitForSingleObject(hRemoteThread, INFINITE);
- VirtualFreeEx(hTargetProcess, 0, memorySize, NULL);
- if (hRemoteThread)
- CloseHandle(hTargetProcess);
- return 0;
- }
本文參考了西祠高手shotgun的《揭開木馬的神祕面紗》,代碼爲自己所寫,放在這裏供大家參考。
大家可以參考上面的步驟自己實現一遍!