利用API注入线程
//提升進程訪問權限
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"));//目標進程IDDWORD dwProcessId;//目標線程IDDWORD 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
//////////////////////////////////////////////////////////////////////////}
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生
總結
- 上一篇: vector的reserve和resiz
- 下一篇: 挖坑机器人算法