windows下writeprocessmemory修改其他进程内存可行但需满足权限、句柄、内存保护及架构匹配等条件;linux下需ptrace附加后通过/proc/pid/mem写入,且受seccomp和权限限制。

Windows下用WriteProcessMemory修改目标进程内存
直接改其他进程内存在Windows上可行,但需要满足几个硬性条件:目标进程必须处于同一用户权限下(或更高权限进程操作低权限进程),且你已获得其有效句柄。最常踩的坑是忽略OpenProcess返回值检查,导致后续WriteProcessMemory静默失败。
关键步骤如下:
- 调用
OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid)获取句柄——注意PROCESS_ALL_ACCESS在现代系统中常被拒绝,建议按需组合PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION - 确保目标地址可写:用
VirtualQueryEx检查内存页属性,若为PAGE_READONLY或PAGE_EXECUTE_READ,需先用VirtualProtectEx临时改为PAGE_READWRITE -
WriteProcessMemory成功后,记得恢复原保护属性(尤其对代码段),否则可能触发AV或杀软告警 - 32位程序无法打开64位进程句柄(反之亦然),
IsWow64Process要提前判断架构匹配性
Linux下通过/proc/pid/mem写入内存
Linux没有公开API直接写其他进程内存,但可通过/proc/pid/mem这个特殊文件实现——前提是你的进程拥有目标进程的ptrace权限(通常要求同用户或CAP_SYS_PTRACE能力)。
常见错误是忘记ptrace(PTRACE_ATTACH, pid, nullptr, nullptr)前置操作,导致open("/proc/1234/mem", O_RDWR)返回Permission denied。
- 必须先
ptrace(PTRACE_ATTACH, pid, ...)暂停目标进程,否则写入会失败或被内核拦截 - 写入前用
lseek定位到目标地址(注意是虚拟地址,不是物理地址) - 写完立即
ptrace(PTRACE_DETACH, pid, ...),否则目标进程会卡死 - 该方法在容器或seccomp限制环境下大概率失效,
strace -e trace=process可快速验证是否被拦截
为什么GetModuleHandleEx + WriteProcessMemory常失败
很多人想“先拿到模块基址再算偏移”,但GetModuleHandleEx只能查**当前进程**的模块句柄,对其他进程完全无效。跨进程找模块基址必须用EnumProcessModules(Windows)或解析/proc/pid/maps(Linux)。
- Windows下用
EnumProcessModules配合GetModuleFileNameEx识别模块,再用GetModuleInformation取基址 - Linux下读
/proc/pid/maps,按行匹配模块名和r-xp标记,提取首列地址(如7f8b2c000000-7f8b2c002000 r-xp中的7f8b2c000000) - ASLR启用时,每次启动基址都变,硬编码地址必然失败
- 64位进程地址空间大,
DWORD类型变量存不下指针,务必用ULONG_PTR或uintptr_t
调试器权限与UAC绕过的真实代价
想绕过UAC或以SYSTEM权限写系统进程?别试了。从Windows Vista起,UIPI(用户界面特权隔离)和PPL(Protected Process Light)机制会让这类操作直接返回ACCESS_DENIED,即使你用SeDebugPrivilege提权也无济于事。
真正能稳定工作的场景其实很窄:同一用户下的桌面应用间通信、游戏外挂(非反作弊环境)、本地调试工具。一旦涉及svchost.exe、lsass.exe或带Protected标记的进程,内核会直接拦截写请求,连日志都不留。
最易被忽略的是内存对齐——WriteProcessMemory对非对齐写入虽不报错,但部分驱动级Hook会丢弃未按页对齐的修改;而/proc/pid/mem在Linux上要求lseek偏移必须是sizeof(long)整数倍,否则write()返回EINVAL。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











