Windows系统编程:跨进程使用句柄和操作内存详解
创作时间:
作者:
@小白创作中心
Windows系统编程:跨进程使用句柄和操作内存详解
引用
CSDN
1.
https://blog.csdn.net/weixin_58038441/article/details/143100414
在Windows系统编程中,跨进程使用句柄和操作内存是两个重要的技术点。本文将详细介绍如何通过继承和复制方式实现跨进程使用句柄,以及如何通过WinHex和WriteProcessMemory修改进程内存。同时,还会讲解内存属性和内存分页的相关知识。
前言
各位读者,大家好!本文将为大家讲解Windows系统编程中跨进程使用句柄和操作内存的相关知识。通过本文的学习,你将能够掌握如何在不同进程间共享句柄,以及如何通过编程方式修改其他进程的内存。
问题
让我们先抛出一个问题:进程A获得的句柄能否直接给进程B使用?
尝试通过以下代码进行实验:
// A程序
void CADlg::OnBnClickedGethandle()
{
DWORD dwPid = GetDlgItemInt(IDC_PID);
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
CString strFmt;
strFmt.Format("%08X", hProc);
SetDlgItemText(IDC_HANDLE, strFmt);
}
// B程序
void CBDlg::OnBnClickedUsehandle()
{
CString strHandle;
GetDlgItemText(IDC_HANDLE, strHandle);
HANDLE hProc = (HANDLE)strtoul(strHandle.GetBuffer(), NULL, 16);
if (TerminateProcess(hProc, 0))
{
AfxMessageBox("结束成功!");
}
else
{
AfxMessageBox("结束失败!");
}
}
实验过程:
- 结论:进程B是无法直接使用A的进程句柄的
OpenProcess
OpenProcess函数用于打开进程对象。
HANDLE OpenProcess(
[in] DWORD dwDesiredAccess,
[in] BOOL bInheritHandle,
[in] DWORD dwProcessId
);
跨进程使用句柄
方式一:继承 - 子进程继承父进程已经打开的句柄
通过C++类来理解CreateProcess和OpenProcess的继承关系。
void CADlg::OnBnClickedGethandle()
{
DWORD dwPid = GetDlgItemInt(IDC_PID);
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwPid);
CString strFmt;
strFmt.Format("%08X", hProc);
SetDlgItemText(IDC_HANDLE, strFmt);
}
void CADlg::OnBnClickedCreatechild()
{
CString strPath;
GetDlgItemText(IDC_CHILD, strPath);
STARTUPINFO si = { };
si.cb = sizeof(si);
PROCESS_INFORMATION pi = { };
BOOL Ret = CreateProcess(
strPath.GetBuffer(),
NULL,
NULL,
NULL,
TRUE, // 允许子进程继承父进程的句柄
0,
NULL,
NULL,
&si,
&pi
);
if (!Ret)
{
AfxMessageBox("CreateProcess Failed!");
}
}
实验过程:
- 可以观察到通过继承的方式,成功跨进程使用句柄
- 子进程只能继承在自身被创建之前父进程打开的句柄,自身创建后父进程打开的句柄无法继承
方式二:复制句柄
使用DuplicateHandle函数将句柄表里的句柄拷贝到对方的句柄表里。
BOOL DuplicateHandle(
[in] HANDLE hSourceProcessHandle,
[in] HANDLE hSourceHandle,
[in] HANDLE hTargetProcessHandle,
[out] LPHANDLE lpTargetHandle,
[in] DWORD dwDesiredAccess,
[in] BOOL bInheritHandle,
[in] DWORD dwOptions
);
void CADlg::OnBnClickedGethandle()
{
DWORD dwPid = GetDlgItemInt(IDC_PID);
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwPid);
HANDLE hProcSelf = GetCurrentProcess();
DWORD dwPidB = GetDlgItemInt(IDC_PID2);
HANDLE hProcB = OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwPidB);
HANDLE hInB = NULL;
DuplicateHandle(hProcSelf, hProc, hProcB, &hInB, 0, FALSE, DUPLICATE_SAME_ACCESS);
CString strFmt;
strFmt.Format("%08X", hInB);
SetDlgItemText(IDC_HANDLE, strFmt);
}
实验过程:
- 适用场景:跨权限操作一些东西,比如有system权限的进程拿到句柄给管理员权限的进程用
跨进程操作内存
设计思路:通过修改进程内存地址,来修改游戏模式
通过WinHex修改内存
通过在WinHex中查找flag的位置,手动修改游戏模式
注意:当程序正在使用时,WinHex无法修改
通过WriteProcessMemory修改内存
函数原型:
BOOL WriteProcessMemory(
[in] HANDLE hProcess,
[in] LPVOID lpBaseAddress,
[in] LPCVOID lpBuffer,
[in] SIZE_T nSize,
[out] SIZE_T *lpNumberOfBytesWritten
);
示例代码:
int main()
{
HWND hWnd = FindWindow(NULL, "游戏");
DWORD dwPid;
GetWindowThreadProcessId(hWnd, &dwPid);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
LPVOID pAddr = (LPVOID)0x01B2A00B;
BYTE btCode = 0xFF;
WriteProcessMemory(hProcess, pAddr, &btCode, sizeof(btCode), NULL);
return 0;
}
- 通过
FindWindow查找对应标题 - 从
GetWindowThreadProcessId获取pid - 打开要写入的进程
- 写入内存
内存属性
- 内存访问属性:R读,W写,X执行,C写时拷贝。修改内存访问属性:
VirtualProtectEx。 - ProcessHacker查看内存属性:exe双击 - Memory - Protection。
WriteProcessMemory不用判断内存属性,每次写之前修改内存属性,写完后还原内存属性。- 写完数据不还原属性:会被检测(向只读内存写入数据,看是否触发异常,触发则表明正常)
- 内存的基本单位4k【一个分页0x1000】,所以当修改0x1225的内存属性实则修改了0x0 ~ 0x2048的内存属性
BOOL VirtualProtectEx(
HANDLE hProcess,
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flNewProtect,
PDWORD lpflOldProtect
);
参数说明:
- 参数3:修改属性的内存大小。修改内存属性会影响到这一段地址空间涉及到的所有内存分页。跨越页面边界的2字节范围会导致两个页面的保护属性都被更改。
- 参数4:内存属性
PAGE_READONLY:只读PAGE_READWRITE:可读可写PAGE_WRITECOPY:写时拷贝PAGE_EXECUTE:可执行PAGE_EXECUTE_READ:可执行可读PAGE_EXECUTE_READWRITE:可执行可读写PAGE_EXECUTE_WRITECOPY:可执行可写时拷贝
内存分页
- 内存分页:大小0x1000(4096),4kb。系统管理内存的基本单位。属性改一字节影响一个分页。
- 申请内存时,系统至少分配一个分页,一个字节也分配一个分页。
new和malloc是在系统分配的基础上再次分配,在系统分配的分页中再次分配需要的字节。- 操作系统喜欢将统一权限属性的放在一起的原因是方便管理,且不浪费内存,也更容易维护。
总结
本文介绍了继承、复制句柄的方式跨进程使用句柄,使用WinHex、WriteProcessMemory修改内存,以及内存属性和内存分页的相关知识。这些内容对于Windows系统编程和进程间通信具有重要的参考价值。
热门推荐
俄乌战争中的乌克兰无人机概览
数据分析中的误差分析指标全解析
Excel中怎么提取最新价格
不锈钢管的特性是什么
公积金贷款利率为什么不能降?如何选择公积金贷款利率?
主播签约合同属于什么合同
满服和汉服对比,缺乏优雅和灵动,这下知道为啥清朝人那么丑了
董事参与公司经营管理吗
上市公司独立董事会的作用:确保公司治理的有效性和透明度
与阳极氧化相比,微弧氧化有什么优点?
电脑截图新玩法,探索内置与第三方工具轻松搞定电脑截图
Win11截图技巧大揭秘:多种方法你都知道哪些?
检测评估需求开始显现 动力电池全生命周期数字化箭在弦上
9款最佳音频转文字转录软件解决方案
推动可持续发展:行业参与者和投资者共同努力的目标
扫一扫功能
扫一扫功能
摩托车、电动自行车交通安全警示教育片
银行的银行卡的分类与功能特点有哪些?
如何购买环保运动服
Excel中将A4页面调整为A3页面的详细步骤
一根手杖也能讲明白:力偶矩怎么计算?
“你在问什么?”——探讨日常对话中的提问方式与交流技巧
ZLG嵌入式笔记 | “三防”防什么?什么时候需要“三防”?
股价从最高点暴跌98%后,AMC院线股票该买入还是卖出?
股市风向标 | AMC院线美股盘前跌超9%
智能视觉检测如何优化HDR拍摄效果
泰山“泉”题刻赏析:常念贪欲之害、常怀律己之心
腮腺结石怎么检查
十大手机大型网络游戏有哪些?如何选择适合自己的游戏?