標籤:
//提升進程存取權限 bool enableDebugPriv() { HANDLE hToken; LUID sedebugnameValue; TOKEN_PRIVILEGES tkp; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { return false; } if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue)) { CloseHandle(hToken); return false; } tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = sedebugnameValue; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) { CloseHandle(hToken); return false; } return true; } struct ToRemoteProccess{ char title[256]; char content[256]; DWORD MsgBoxAddress;};////定義MessageBox類型的函數指標 typedef void (__stdcall *Msgbox)(HWND hWnd,LPCTSTR title,LPCTSTR content,DWORD uType );DWORD threadProc(LPVOID lParam){// //程式崩潰// MessageBox(NULL, "title", "content", MB_OK);/*****************************************************************************************************線程體修改完畢之後我們運行程式,將線程注入到宿主進程之中。不過此時會產生一個非法訪問的錯誤。原因就是線程體中的MessageBox(NULL, "title", "content", MB_OK);函數的第二和第三個參數所指向的字串是存在於當前進程的地址空間中,宿主進程中的線程訪問該字串"hello"就會出現訪問記憶體非法的錯誤。解決的方法就是將該字串的內容也拷貝到宿主進程的地址空間中,而且連同MessageBox函數在User32.dll中的地址也拷貝到宿主進程之中。 *****************************************************************************************************/ //正確執行 ToRemoteProccess *tmpTRP = (ToRemoteProccess *)lParam; Msgbox tmpMsgbox; tmpMsgbox = (Msgbox)(tmpTRP->MsgBoxAddress); tmpMsgbox(0,tmpTRP->content,tmpTRP->title,0); //正確執行// __asm// {// mov eax,0x00401480// call eax// } return 0;}void CRemoteCallerDlg::OnButton1() { // TODO: Add your control notification handler code here //提升本程式的許可權 enableDebugPriv(); //獲得遠程進程控制代碼 HWND hWnd=::FindWindow(NULL,_T("BloodTest")); //目標進程ID DWORD dwProcessId; //目標線程ID DWORD dwThreadId; dwThreadId=::GetWindowThreadProcessId(hWnd,&dwProcessId); //目標進程控制代碼 HANDLE HandlToRemoteProcess=::OpenProcess(PROCESS_ALL_ACCESS,false,dwProcessId); if(HandlToRemoteProcess == NULL) { AfxMessageBox(_T("OpenProcess失敗")); return; } //申請線程函數記憶體 const DWORD dwThreadSize = 4096; void* threadProcAddr=::VirtualAllocEx(HandlToRemoteProcess,0,dwThreadSize,MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if(threadProcAddr == NULL) { AfxMessageBox(_T("VirtualAllocEx失敗")); return; } //將線程代碼寫入到遠程進程 DWORD NumberOfBytesWrittenOfProc; BOOL retWriteProcessMemory=::WriteProcessMemory(HandlToRemoteProcess,threadProcAddr,&threadProc, dwThreadSize, &NumberOfBytesWrittenOfProc); if(!retWriteProcessMemory) { AfxMessageBox(_T("WriteProcessMemory失敗")); return; } //構造線程參數 DWORD NumberOfBytesWrittenOfParam; ToRemoteProccess trp; ZeroMemory(&trp,sizeof(ToRemoteProccess)); HMODULE hUser32 = LoadLibrary("User32.dll"); trp.MsgBoxAddress = (DWORD)GetProcAddress(hUser32,"MessageBoxA"); _sntprintf(trp.title,sizeof("title"),"%s","title"); _sntprintf(trp.content,sizeof("content"),"%s","content"); //申請參數空間 ToRemoteProccess *pRemoteParamAddr = (ToRemoteProccess *)::VirtualAllocEx(HandlToRemoteProcess,0,sizeof(ToRemoteProccess),MEM_COMMIT,PAGE_READWRITE); if(pRemoteParamAddr == NULL) { AfxMessageBox(_T("VirtualAllocEx失敗")); return; } //參數寫進記憶體 retWriteProcessMemory =::WriteProcessMemory(HandlToRemoteProcess,pRemoteParamAddr,&trp, sizeof(ToRemoteProccess), &NumberOfBytesWrittenOfParam); if(!retWriteProcessMemory) { AfxMessageBox(_T("WriteProcessMemory失敗")); return; } //建立遠程線程 DWORD RemoteThreadId; HANDLE retRemoteThread=::CreateRemoteThread(HandlToRemoteProcess,NULL,0,(LPTHREAD_START_ROUTINE)threadProcAddr,(LPVOID)pRemoteParamAddr,0 ,&RemoteThreadId); if (retRemoteThread == NULL) { AfxMessageBox(_T("CreateRemoteThread失敗")); return; } //清理 VirtualFreeEx(HandlToRemoteProcess,threadProcAddr,dwThreadSize,MEM_RELEASE); VirtualFreeEx(HandlToRemoteProcess,pRemoteParamAddr,sizeof(ToRemoteProccess),MEM_RELEASE); FreeLibrary(hUser32); CloseHandle(HandlToRemoteProcess);//////////////////////////////////////////////////////////////////////////// LPVOID VirtualAllocEx( // HANDLE hProcess, // LPVOID lpAddress, // SIZE_T dwSize, // DWORD flAllocationType, // DWORD flProtect // ); // // hProcess:// 申請記憶體所在的進程控制代碼。// lpAddress: // 保留頁面的記憶體位址;一般用NULL自動分配 。// dwSize:// 欲分配的記憶體大小,位元組單位;注意實際分 配的記憶體大小是頁記憶體大小的整數倍 // // flAllocationType 可取下列值:// MEM_COMMIT:為特定的頁面地區分配記憶體中或磁碟的分頁檔中的實體儲存體// MEM_PHYSICAL :分配實體記憶體(僅用於地址視窗擴充記憶體)// MEM_RESERVE:保留進程的虛擬位址空間,而不分配任何實體儲存體。保留頁面可通過繼續調用VirtualAlloc()而被佔用// MEM_RESET :指明在記憶體中由參數lpAddress和dwSize指定的資料無效 // MEM_TOP_DOWN:在儘可能高的地址上分配記憶體(Windows 98忽略此標誌)// MEM_WRITE_WATCH:必須與MEM_RESERVE一起指定,使系統跟蹤那些被寫入分配地區的頁面(僅針對Windows 98)// // flProtect可取下列值:// PAGE_READONLY: 該地區為唯讀。如果應用程式試圖訪問地區中的頁的時候,將會被拒絕訪// PAGE_READWRITE 地區可被應用程式讀寫// PAGE_EXECUTE: 地區包含可被系統執行的代碼。試圖讀寫該地區的操作將被拒絕。// PAGE_EXECUTE_READ :地區包含可執行代碼,應用程式可以讀該地區。// PAGE_EXECUTE_READWRITE: 地區包含可執行代碼,應用程式可以讀寫該地區。// PAGE_GUARD: 地區第一次被訪問時進入一個STATUS_GUARD_PAGE異常,這個標誌要和其他保護標誌合并使用,表明地區被第一次訪問的許可權// PAGE_NOACCESS: 任何訪問該地區的操作將被拒絕// PAGE_NOCACHE: RAM中的頁映射到該地區時將不會被微處理器緩衝(cached)// // 注:PAGE_GUARD和PAGE_NOCHACHE標誌可以和其他標誌合并使用以進一步指定頁的特徵。PAGE_GUARD標誌指定了一個防護頁(guard page),即當一個頁被提交時會因第一// 次被訪問而產生一個one-shot異常,接著取得指定的存取權限。PAGE_NOCACHE防止當它映射到虛擬頁的時候被微處理器緩衝。這個標誌方便裝置驅動使用直接記憶體存取方// 式(DMA)來共用記憶體塊。// // 傳回值:// 執行成功就返回分配記憶體的首地址,不成功就是NULL。// // // BOOL WriteProcessMemory(// HANDLE hProcess,// LPVOID lpBaseAddress,// LPVOID lpBuffer,// DWORD nSize,// LPDWORD lpNumberOfBytesWritten// );// // 參數:// hProcess:由OpenProcess返回的進程控制代碼。如參數傳資料為 INVALID_HANDLE_VALUE 【即-1】目標進程為自身進程// lpBaseAddress:要寫的記憶體首地址,再寫入之前,此函數將先檢查目標地址是否可用,並能容納待寫入的資料。// lpBuffer:指向要寫的資料的指標。// nSize:要寫入的位元組數。// lpNumberOfBytesWritten:成功寫入的資料的大小// // 傳回值:// 非零值代表成功.// // HANDLE CreateRemoteThread(// HANDLE hProcess,// LPSECURITY_ATTRIBUTES lpThreadAttributes,// SIZE_T dwStackSize,// LPTHREAD_START_ROUTINE lpStartAddress,// LPVOID lpParameter,// DWORD dwCreationFlags,// LPDWORD lpThreadId// );// 參數說明:// hProcess:目標進程的控制代碼// lpThreadAttributes:指向線程的安全描述結構體的指標,一般設定為NULL,表示使用預設的安全層級// dwStackSize:線程堆棧大小,一般設定為0,表示使用預設的大小,一般為1M// lpStartAddress:線程函數的地址// lpParameter:線程參數// dwCreationFlags:線程的建立方式// lpThreadId:輸出參數,記錄建立的遠程線程的ID//////////////////////////////////////////////////////////////////////////}
利用API注入線程