Windows 1.跨进程使用句柄 先创建两个MFC的进程分别为A,B
A:
B:
使用方式
(1)继承方式
父进程打开的句柄继承给子进程使用
父进程的句柄是否继承给子进程使用
判断句柄是否可以被继承(安全属性) 第一个为进程句柄 第二个为线程句柄
若安全属性为true 那么当createprocess为true时句柄会传给子进程 为FALSE时句柄不会传给子进程
但若安全属性为false时 无论createprocess为true还是false都不会传给子进程
A:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ZeroMemory (&si, sizeof (si));si.cb = sizeof (si); ZeroMemory (&pi, sizeof (pi));SECURITY_ATTRIBUTES sa = {}; sa.nLength = sizeof (sa); sa.bInheritHandle = TRUE; if (!CreateProcessW (TEXT ("C:\\vs\\B\\x64\\Debug\\B.exe" ), NULL , &sa, NULL , FALSE, 0 , NULL , NULL , &si, &pi) ) { AfxMessageBox (_T("CreateProcess failed" )); return ; } CString strFmt; strFmt.Format (L"%08X" , pi.hProcess); SetDlgItemText (EDT_BHDANDLE, strFmt); UpdateWindow (); WaitForSingleObject (pi.hProcess, INFINITE); CloseHandle (pi.hProcess); CloseHandle (pi.hThread);
B:
1 2 3 4 5 6 7 8 void CBDlg::OnBnClickedButton1 () { CString str; GetDlgItemText (EDT_BHANDLE, str); HANDLE hBProc = (HANDLE)strtoul (str.GetBuffer (), NULL , 16 ); TerminateProcess (hBProc, 0 ); }
若由A进程启动B进程 B进程关闭A进程 A启动B进程获取的句柄 在B进程启动之前 与B进程无关 B没有继承A的句柄
A进程创建两次B进程 B1并没有继承A的句柄 而B2继承了A的句柄 使得B2可以关闭B1(同理B2的进程需要B3来关闭)
(2)拷贝方式
将句柄拷贝到指定进程,无视父子进程
参数1、2:原进程被拷贝的句柄
参数3:目标进程的句柄
参数4:拷贝到目标进程后句柄的值
参数5:拷贝到目标进程的句柄的权限
参数6:拷贝出来的新句柄是否被继承
拷贝的句柄所具有的权限 若为same 则与原句柄相同
1 2 3 4 5 6 7 8 HANDLE hBProc = NULL ; DuplicateHandle (GetCurrentProcess (),pi.hProcess, pi.hProcess,&hBProc, 0 , FALSE, DUPLICATE_SAME_ACCESS );
全部代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 void CADlg::OnBnClickedButton1 () { HANDLE hCurProc = GetCurrentProcess (); HANDLE hCurThread = GetCurrentThread (); STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory (&si, sizeof (si)); si.cb = sizeof (si); ZeroMemory (&pi, sizeof (pi)); SECURITY_ATTRIBUTES sa = {}; sa.nLength = sizeof (sa); sa.bInheritHandle = TRUE; if (!CreateProcessW (TEXT ("C:\\vs\\B\\x64\\Debug\\B.exe" ), NULL , &sa, NULL , FALSE, 0 , NULL , NULL , &si, &pi) ) { AfxMessageBox (_T("CreateProcess failed" )); return ; } HANDLE hBProc = NULL ; DuplicateHandle (GetCurrentProcess (),pi.hProcess, pi.hProcess,&hBProc, 0 , FALSE, DUPLICATE_SAME_ACCESS ); CString strFmt; strFmt.Format (L"%08X" , pi.hProcess); SetDlgItemText (EDT_BHDANDLE, strFmt); UpdateWindow (); WaitForSingleObject (pi.hProcess, INFINITE); CloseHandle (pi.hProcess); CloseHandle (pi.hThread); } void CADlg::OnEnChangeBhdandle () { }
(3)伪句柄
伪句柄仅限作用于当前线程\进程
通过这两个API获取的这两个句柄的值一直都是不变的
1 2 GetCurrentProcess()为-1 0xffffffff GetCurrentThread()为-2 0xfffffffe
不管怎么调用 值都不变
上述两个即为伪句柄
2.跨进程操作内存
参数1:句柄
参数2:地址
参数3:数据的缓冲区
参数4:写的数据的大小
参数5:写入的数据的字节数若为NULL则忽略
获取句柄:
参数1:权限
参数2:安全属性
参数3:进程ID
获取进程ID:
但是需要获取窗口句柄
获取窗口句柄:
若无窗口句柄 则换成遍历寻找进程名 或者路径 (不同的API)
修改的地址为只读不能写 通过VirtualProtectEx 这个API修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 HWND hWndGame = FindWindow (NULL ,"Visual Studio Installer" ); if (hWndGame == NULL ) { cout << "获取窗口句柄失败" << endl; return 0 ; } DWORD dwProId = 0 ; DWORD dwThreadId = GetWindowThreadProcessId ( hWndGame, &dwProId); if (dwThreadId == 0 ){ cout << "获取线程ID失败" << endl; return 0 ; } HANDLE hProc = OpenProcess (PROCESS_ALL_ACCESS, FALSE, dwProId); if (hProc == NULL ){ cout << "获取进程句柄失败" << endl; return 0 ; }
修改内存数据:
1 2 3 4 5 6 7 LPVOID pAddrGod = (LPVOID)0x00227526 ; BYTE bt = 0xF5 ; DWORD dwOldProc = 0 ; BOOL bRet = WriteProcessMemory (hProc, pAddrGod, &bt,sizeof (bt),NULL ); if (!bRet) { cout << "无敌失败" << endl; }
参数4:新修改的属性
参数5:没改之前的属性
Windows内存以分页形式进行管理 在修改内存属性时会影响整个分页 从而使内存大小发生改变
同内存属性的内存是连在一起的 不同属性拆开
1 2 3 4 5 6 7 8 9 10 11 12 13 14 LPVOID pAddrGod = (LPVOID)0x00227526 ; BYTE bt = 0xF5 ; DWORD dwOldProc = 0 ; BOOL bRet = VirtualProtectEx (hProc, pAddrGod, sizeof (bt), PAGE_READWRITE, &dwOldProc); if (!bRet){ cout << "修改内存属性失败" << endl; return 0 ; } bRet = WriteProcessMemory (hProc, pAddrGod, &bt, sizeof (bt),NULL ); if (!bRet) { cout << "无敌失败" << endl; } VirtualProtectEx (hProc, pAddrGod, sizeof (bt), dwOldProc, &dwOldProc);