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系统编程和进程间通信具有重要的参考价值。
热门推荐
大数定律中的大数是多大?
怎样能放松心情不再焦虑的方法
股指和期货有什么关系?两者在市场中如何相互影响?
女方有病史如何影响离婚诉讼?
探究昆明外来人口数量:占比、来源及生活状况全解析
犹太认证注意事项
西安商品房交房标准及注意事项详解
《揭秘八字:心理命运密码解析》
红花与西红花的区别有哪些?
教你写出一份完美的借条:15个关键点全解析
定金、订金、押金、保证金、违约金这“法律五金”,到底能不能退?
VR全景制作入门指南:逐步解析学习路线与实战。
如何避免继承父母债务纠纷、离婚前债务和逃废金融债务
日本测试高速公路“自动驾驶优先车道”
网上操作商标地址变更,轻松实现地址变更流程
商标变更的步骤有哪些
C语言中的printf和C++中的cout有什么区别?
如何测量食物的热量:科学方法大揭秘
黄腐酸在农业上的应用及其重要作用
揭秘华为手机的出厂日期查询方法
十一岁的小孩是否可以进行种植牙?了解儿童种植牙的相关知识与注意事项
《2024中国企业数字化转型案例研究报告》重磅发布!
羧甲基纤维素钠高温性能分析与应用前景
残疾人个税优惠政策解读:减征对象、范围及标准速看
服药期间,5类食物需谨慎食用,以免影响药效
NBA篮球暂停规则详解:短暂停、长暂停与官方暂停全解析
护照限制出境怎么解除手续
如何解释美元汇率的大幅下跌?这种下跌对经济有何影响?
来姨妈可以吃冰淇淋吗
个人收入所得税专项扣除政策解析:哪些支出可以享受优惠?