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系统编程和进程间通信具有重要的参考价值。
热门推荐
挑西瓜别只听声音,掌握五个诀窍,轻松挑出皮薄多汁的优质西瓜
郭京飞新剧《黄雀》:从没见过一部剧这么多贼
适合减肥的碳水化合物
钓鱼如何用饵料?
一文读懂:数字化应急预案系统——革新应急响应模式,提升处置效能
MBTI2025深度解析:掌握16种性格特质与职业发展
商科实习,更“卷”吗?
香港研究生留学生活全方位体验分享
什么食物有助于提高孕妇免疫力?
长姐罗欢:中国女子体操队的定心丸
一路“欢”歌向前行——仙桃体操运动员罗欢成长经历
蓝星花的花语是什么?如何用蓝星花表达情感?
宠物饮食:南瓜可否喂狗?
遭遇网络骚扰怎么办?这份应对指南请收好
GRS数据线:环保与性能兼备的绿色之选
2025年金融市场大考:美联储政策将如何重塑美债、美元与黄金命运?
购买电视后的正确使用和维护指南
心态决定命运,做到这三点,好运自来!
孩子突然爱咬指甲要警惕!儿童心理问题的8个危险动作
双金属耐磨钢板:工业应用的革新选择
通报 | 土狗咬伤2个大人、4个孩子!被犬袭击后这样处理→
404 Not Found
Vue.js项目中如何配置404页面
头痛按摩什么穴位最快最有效
按虎口好处竟那么多?中医教你「3手法」有效缓解头痛、躯干、下肢痛
脾胃虚弱是怎么回事?原因、症状与调理方法全解析
运维团队管理指南:从职责分配到绩效评估
八种运动减肥法让你快速减肥不反弹
得了感冒能洗澡吗?感冒期间洗澡的注意事项
挑西瓜不要光听声音,教你5个技巧,轻松挑出皮薄多汁的优质西瓜