利用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
//////////////////////////////////////////////////////////////////////////}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
