最近在看病毒相關內容,看著大部分知識都知道,不知道用起來行不行。下午正好有人問怎麼注入線程,在公司用《windows核心編程》的注入DLL程序修改了一下,實現了遠程注入DLL調用函數。剛才回來,覺得照著別人的程序改,總還是學不到家,自己花了兩個小時寫了一個。能注入到其他進程中,執行彈出MessageBox框。當然,能注入去彈出這個框,就能干很多壞事了,看你想干什麼了。把代碼貼上來,也不改了,反正能看懂。有幾個細節可能會忽略: 1. ThreadFunc應該定義成static,不能是全局函數。如果是全局函數,只能取到jmp ThreadFunc這塊代碼的地址。 2. 在調試模式會使寫函數數據時數據出錯。 下午就被這兩個東西浪費了一個多小時。 [cpp] // InjectToRemoteProcess.cpp : 定義應用程序的入口點。 // #include "stdafx.h" #include "InjectToRemoteProcess.h" #define MAX_LOADSTRING 100 // 全局變量: HINSTANCE hInst; // 當前實例 TCHAR szTitle[MAX_LOADSTRING]; // 標題欄文本 TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口類名 // 此代碼模塊中包含的函數的前向聲明: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK Inject(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: 在此放置代碼。 MSG msg; HACCEL hAccelTable; // 初始化全局字符串 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_INJECTTOREMOTEPROCESS, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // 執行應用程序初始化: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_INJECTTOREMOTEPROCESS)); // 主消息循環: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // // 函數: MyRegisterClass() // // 目的: 注冊窗口類。 // // 注釋: // // 僅當希望 // 此代碼與添加到 Windows 95 中的“RegisterClassEx” // 函數之前的 Win32 系統兼容時,才需要此函數及其用法。調用此函數十分重要, // 這樣應用程序就可以獲得關聯的 // “格式正確的”小圖標。 // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_INJECTTOREMOTEPROCESS)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_INJECTTOREMOTEPROCESS); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex); } // // 函數: InitInstance(HINSTANCE, int) // // 目的: 保存實例句柄並創建主窗口 // // 注釋: // // 在此函數中,我們在全局變量中保存實例句柄並 // 創建和顯示主程序窗口。 // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // 將實例句柄存儲在全局變量中 hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // 函數: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目的: 處理主窗口的消息。 // // WM_COMMAND - 處理應用程序菜單 // WM_PAINT - 繪制主窗口 // WM_DESTROY - 發送退出消息並返回 // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 分析菜單選擇: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; case IDM_INJECT: DialogBox(hInst,MAKEINTRESOURCE(IDD_DLG_INJECT),hWnd,Inject); default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: 在此添加任意繪圖代碼... EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // “關於”框的消息處理程序。 INT_PTR CALLBACK About(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 || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; } struct ProcStruct { FARPROC MsgAddr; TCHAR strMsg[24]; TCHAR strTitle[24]; }; static DWORD __stdcall ThreadFunc(ProcStruct * pPS) { typedef int (__stdcall *pMsgBox)(HWND,LPCTSTR,LPCTSTR,UINT); pMsgBox MsgBox =(pMsgBox)pPS->MsgAddr; MsgBox(NULL,pPS->strMsg,pPS->strTitle,0); return 0; } static DWORD __stdcall OffsetFunc(LPVOID* pParam) { return 0; } bool AdjustProcessTokenPrivilege() { LUID luidTmp; HANDLE hToken; TOKEN_PRIVILEGES tkp; if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { //OutputDebugString("AdjustProcessTokenPrivilege OpenProcessToken Failed ! \n"); return false; } if(!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidTmp)) { //OutputDebugString("AdjustProcessTokenPrivilege LookupPrivilegeValue Failed ! \n"); CloseHandle(hToken); return FALSE; } tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = luidTmp; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if(!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) { //OutputDebugString("AdjustProcessTokenPrivilege AdjustTokenPrivileges Failed ! \n"); CloseHandle(hToken); return FALSE; } return true; } DWORD InjectFunctionToProcess(DWORD dwProcessId) { AdjustProcessTokenPrivilege(); try { HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | // Required by Alpha PROCESS_CREATE_THREAD | // For CreateRemoteThread PROCESS_VM_OPERATION | // For VirtualAllocEx/VirtualFreeEx PROCESS_VM_WRITE, // For WriteProcessMemory FALSE, dwProcessId); if (hProcess == NULL) { return 0; } HMODULE hUser32 = GetModuleHandle(_T("User32.dll")); if (hProcess == NULL) { return 0; } FARPROC MsgAddr = GetProcAddress(hUser32,"MessageBoxW"); ProcStruct PS; PS.MsgAddr =MsgAddr; _tcscpy(PS.strMsg,_T("This is Message!")); _tcscpy(PS.strTitle,_T("Title")); //開辟存儲變量的內存空間 void * pMemProcStruct = VirtualAllocEx(hProcess,NULL,sizeof(ProcStruct),MEM_COMMIT,PAGE_READWRITE); if (!pMemProcStruct) { return 0; } //復制參數內容 if (!WriteProcessMemory(hProcess,pMemProcStruct,&PS,sizeof(ProcStruct),NULL)) { return 0; } //開辟存儲調用函數的空間 DWORD FuncLen = (DWORD)OffsetFunc - (DWORD)ThreadFunc; void * pMemFunction = VirtualAllocEx(hProcess,NULL,FuncLen,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE); if (!pMemFunction) { return 0; } //復制函數內容 if (!WriteProcessMemory(hProcess,pMemFunction,ThreadFunc,FuncLen,NULL)) { return 0; } //啟動線程函數注入進程 HANDLE hRemoteThread = CreateRemoteThread(hProcess,NULL,NULL,(LPTHREAD_START_ROUTINE)pMemFunction,pMemProcStruct,NULL,NULL); if (!hRemoteThread) { return 0; } //等待線程結束 WaitForSingleObject(hRemoteThread,INFINITE); //釋放參數內容 VirtualFreeEx(hProcess,pMemProcStruct,sizeof(ProcStruct),MEM_RELEASE); //釋放函數內容 VirtualFreeEx(hProcess,pMemFunction,FuncLen,MEM_RELEASE); } catch (...) { return -1; } return 0; } // “注入”框的消息處理程序。 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) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } else if (LOWORD(wParam) == IDOK) { DWORD dwProcessId = GetDlgItemInt(hDlg, IDC_INJECTTOREMOTEPROCESS, NULL, FALSE); if (dwProcessId == 0) { // A process ID of 0 causes everything to take place in the // local process; this makes things easier for debugging. dwProcessId = GetCurrentProcessId(); } if (!InjectFunctionToProcess(dwProcessId)) { MessageBox(NULL,_T("DLL Injection/Ejection successful."),_T("Title"),0); } else { MessageBox(NULL,_T("DLL Injection/Ejection failed."),_T("Error"),0); } } break; } return (INT_PTR)FALSE; }