利用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類型的函數(shù)指針
typedef void (__stdcall *Msgbox)(HWND hWnd,LPCTSTR title,LPCTSTR content,DWORD uType );
DWORD threadProc(LPVOID lParam)
{
// //程序崩潰
// MessageBox(NULL, "title", "content", MB_OK);
/*****************************************************************************************************
線程體修改完畢之后我們運行程序,將線程注入到宿主進程之中。不過此時會產(chǎn)生一個非法訪問的錯誤。原
因就是線程體中的MessageBox(NULL, "title", "content", MB_OK);函數(shù)的第二和第三個參數(shù)所指向的字符串
是存在于當前進程的地址空間中,宿主進程中的線程訪問該字符串"hello"就會出現(xiàn)訪問內存非法的錯誤。
解決的方法就是將該字符串的內容也拷貝到宿主進程的地址空間中,而且連同MessageBox函數(shù)在User32.dll
中的地址也拷貝到宿主進程之中。
*****************************************************************************************************///正確執(zhí)行ToRemoteProccess *tmpTRP = (ToRemoteProccess *)lParam;Msgbox tmpMsgbox;tmpMsgbox = (Msgbox)(tmpTRP->MsgBoxAddress);tmpMsgbox(0,tmpTRP->content,tmpTRP->title,0);//正確執(zhí)行
// __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;}//申請線程函數(shù)內存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;}//構造線程參數(shù)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");//申請參數(shù)空間ToRemoteProccess *pRemoteParamAddr = (ToRemoteProccess *)::VirtualAllocEx(HandlToRemoteProcess,0,sizeof(ToRemoteProccess),MEM_COMMIT,PAGE_READWRITE);if(pRemoteParamAddr == NULL){AfxMessageBox(_T("VirtualAllocEx失敗"));return;}//參數(shù)寫進內存retWriteProcessMemory =::WriteProcessMemory(HandlToRemoteProcess,pRemoteParamAddr,&trp, sizeof(ToRemoteProccess), &NumberOfBytesWrittenOfParam);if(!retWriteProcessMemory){AfxMessageBox(_T("WriteProcessMemory失敗"));return;}//創(chuàng)建遠程線程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:
// 欲分配的內存大小,字節(jié)單位;注意實際分 配的內存大小是頁內存大小的整數(shù)倍
//
// flAllocationType 可取下列值:
// MEM_COMMIT:為特定的頁面區(qū)域分配內存中或磁盤的頁面文件中的物理存儲
// MEM_PHYSICAL :分配物理內存(僅用于地址窗口擴展內存)
// MEM_RESERVE:保留進程的虛擬地址空間,而不分配任何物理存儲。保留頁面可通過繼續(xù)調用VirtualAlloc()而被占用
// MEM_RESET :指明在內存中由參數(shù)lpAddress和dwSize指定的數(shù)據(jù)無效
// MEM_TOP_DOWN:在盡可能高的地址上分配內存(Windows 98忽略此標志)
// MEM_WRITE_WATCH:必須與MEM_RESERVE一起指定,使系統(tǒng)跟蹤那些被寫入分配區(qū)域的頁面(僅針對Windows 98)
//
// flProtect可取下列值:
// PAGE_READONLY: 該區(qū)域為只讀。如果應用程序試圖訪問區(qū)域中的頁的時候,將會被拒絕訪
// PAGE_READWRITE 區(qū)域可被應用程序讀寫
// PAGE_EXECUTE: 區(qū)域包含可被系統(tǒng)執(zhí)行的代碼。試圖讀寫該區(qū)域的操作將被拒絕。
// PAGE_EXECUTE_READ :區(qū)域包含可執(zhí)行代碼,應用程序可以讀該區(qū)域。
// PAGE_EXECUTE_READWRITE: 區(qū)域包含可執(zhí)行代碼,應用程序可以讀寫該區(qū)域。
// PAGE_GUARD: 區(qū)域第一次被訪問時進入一個STATUS_GUARD_PAGE異常,這個標志要和其他保護標志合并使用,表明區(qū)域被第一次訪問的權限
// PAGE_NOACCESS: 任何訪問該區(qū)域的操作將被拒絕
// PAGE_NOCACHE: RAM中的頁映射到該區(qū)域時將不會被微處理器緩存(cached)
//
// 注:PAGE_GUARD和PAGE_NOCHACHE標志可以和其他標志合并使用以進一步指定頁的特征。PAGE_GUARD標志指定了一個防護頁(guard page),即當一個頁被提交時會因第一
// 次被訪問而產(chǎn)生一個one-shot異常,接著取得指定的訪問權限。PAGE_NOCACHE防止當它映射到虛擬頁的時候被微處理器緩存。這個標志方便設備驅動使用直接內存訪問方
// 式(DMA)來共享內存塊。
//
// 返回值:
// 執(zhí)行成功就返回分配內存的首地址,不成功就是NULL。
//
//
// BOOL WriteProcessMemory(
// HANDLE hProcess,
// LPVOID lpBaseAddress,
// LPVOID lpBuffer,
// DWORD nSize,
// LPDWORD lpNumberOfBytesWritten
// );
//
// 參數(shù):
// hProcess:由OpenProcess返回的進程句柄。如參數(shù)傳數(shù)據(jù)為 INVALID_HANDLE_VALUE 【即-1】目標進程為自身進程
// lpBaseAddress:要寫的內存首地址,再寫入之前,此函數(shù)將先檢查目標地址是否可用,并能容納待寫入的數(shù)據(jù)。
// lpBuffer:指向要寫的數(shù)據(jù)的指針。
// nSize:要寫入的字節(jié)數(shù)。
// lpNumberOfBytesWritten:成功寫入的數(shù)據(jù)的大小
//
// 返回值:
// 非零值代表成功.
//
// HANDLE CreateRemoteThread(
// HANDLE hProcess,
// LPSECURITY_ATTRIBUTES lpThreadAttributes,
// SIZE_T dwStackSize,
// LPTHREAD_START_ROUTINE lpStartAddress,
// LPVOID lpParameter,
// DWORD dwCreationFlags,
// LPDWORD lpThreadId
// );
// 參數(shù)說明:
// hProcess:目標進程的句柄
// lpThreadAttributes:指向線程的安全描述結構體的指針,一般設置為NULL,表示使用默認的安全級別
// dwStackSize:線程堆棧大小,一般設置為0,表示使用默認的大小,一般為1M
// lpStartAddress:線程函數(shù)的地址
// lpParameter:線程參數(shù)
// dwCreationFlags:線程的創(chuàng)建方式
// lpThreadId:輸出參數(shù),記錄創(chuàng)建的遠程線程的ID
//////////////////////////////////////////////////////////////////////////}
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生
總結
- 上一篇: vector的reserve和resiz
- 下一篇: dnf辅助外挂C++源代码