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系统编程和进程间通信具有重要的参考价值。
热门推荐
家庭友好型工作场所:让员工更幸福,让企业更 competitive
山西到底有多少古城?除了平遥古城,原来还有这么多历史遗迹
春节压岁钱:经济学视角下的“跨期投资”
争吵后,重来一次,让爱情保鲜
家庭和睦秘籍:这些沟通技巧让你告别争吵
五色时间管理法:廖晓一教你高效平衡工作家庭
工作家庭平衡的艺术:从心理学视角解读许雯雯和周玉明的成功之道
工作与生活的完美平衡:职场妈妈的福音
丽水·仙都:浙江最美自然景观推荐
社交礼仪小贴士:如何在聚会中展现魅力
十款适合跨年聚会时候玩的扑克牌游戏合集
南门湾:东山岛最美自然景观,电影《左耳》取景地
东山岛两日游,打卡最美“东方夏威夷”
东山岛必打卡:南门湾、金銮湾、苏峰山
读25首描写名胜古迹的诗词,感受震撼古今的诗词和风景之美
开学前三天,又想家了
被压缩的现代化:年轻人为何不想呆在家?
茶文化带动乡村经济:从凤凰镇到全国的实践探索
《茶经》再现江湖:唐代茶文化的复兴与现代传承
神农尝百草,茶文化起源揭秘
怎么学会倾听别人内心的需求
LLVM安装指南:新手也能秒变高手
《新世纪福音战士》粉丝必看:完美还原绫波丽经典台词
LLVM-C debug版本安装避坑指南
LLVM-C最佳硬件配置指南选题分析报告
绫波丽经典台词背后的秘密:从冷漠到温暖的哲学之旅
绫波丽经典台词翻译挑战赛
香港流行歌曲如何改变内地乐坛?
端午节和粽子在屈原之前就有了?屈原:这个节日原本和我无关
清明节:南北习俗差异的深度解析