WriteProcessMemory需PROCESS_VM_WRITE与PROCESS_VM_OPERATION权限,且调用进程须启用SeDebugPrivilege特权;目标地址须可写、已提交、非保护进程内存,否则易返回ERROR_ACCESS_DENIED或ERROR_PARTIAL_COPY。

WriteProcessMemory 需要哪些前提权限
直接调用 WriteProcessMemory 大概率失败,不是函数写错了,而是进程没拿到目标进程的句柄权限。Windows 默认拒绝跨进程内存写入,必须显式申请 PROCESS_VM_WRITE | PROCESS_VM_OPERATION 权限,且调用者进程本身得有 SeDebugPrivilege 特权(通常仅管理员或 SYSTEM 进程默认拥有)。
常见错误现象:WriteProcessMemory 返回 false,GetLastError() 是 ERROR_ACCESS_DENIED(5)或 ERROR_PARTIAL_COPY(299)——后者往往是因为目标地址未提交、不可写,或地址根本不在目标进程有效内存范围内。
- 先用
OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, pid)获取句柄,不能只传PROCESS_ALL_ACCESS(权限过大,常被 UAC 拦截) - 若打开失败且错误码是
ERROR_PRIVILEGE_NOT_HELD(1314),需调用AdjustTokenPrivileges启用当前进程的SeDebugPrivilege - 目标进程不能是保护进程(如带 PPL 的
csrss.exe、smss.exe,或开启 CFG/AMPG 的现代应用),否则即使有权限也会被内核拦截
目标地址怎么找才不会崩溃
往任意地址写数据 = 99% 触发访问冲突或 AV。Shellcode 注入要求目标地址:已分配、可写、足够大、且执行时不会被覆盖或释放。不能硬编码地址(ASLR 下每次加载位置不同),也不能往代码段硬写(DEP 会触发异常)。
正确做法是先在目标进程中申请一块可读写执行(RWX)内存:
立即学习“C++免费学习笔记(深入)”;
- 用
VirtualAllocEx(hProc, NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)分配——注意第 2 个参数为NULL让系统选址,别填固定值 - 若返回
NULL,检查GetLastError():可能是目标进程是 WoW64 而你用了 64 位注入器(或反过来),也可能是目标进程启用了 SMEP/SMAP(极少见但可能) - 分配后立即用
WriteProcessMemory写入 Shellcode,不要等几秒再写——内存页状态可能变化
WriteProcessMemory 写入 Shellcode 的典型调用要点
WriteProcessMemory 本身很简单,但和 Shellcode 生命周期强耦合。它只是“搬运工”,不负责执行、不处理重定位、不绕过 CFG/EMET。
- 第 3 个参数(源缓冲区)必须是本地进程可读的内存,比如
shellcode_buf数组或VirtualAlloc分配的页;不能传字符串字面量(可能在只读段) - 第 4 个参数(大小)必须严格等于 Shellcode 实际长度,多一个字节都可能覆盖后续指令或结构体;可用
sizeof(shellcode)或提前计算好的变量 - 第 5 个参数(写入字节数指针)建议非空传入,用于确认是否全部写入成功;若返回值小于预期,说明部分失败(例如目标地址被其他线程修改、或触发了 ETW 监控)
- 写入后必须调用
CreateRemoteThread或NtCreateThreadEx才能执行,WriteProcessMemory不改变目标进程控制流
为什么你的 Shellcode 运行就崩
写进去了 ≠ 能跑。现代 Windows 下,Shellcode 崩溃原因往往和 WriteProcessMemory 无关,而是执行环境问题:
- Shellcode 里用了相对地址跳转(如
call/jmp),但没做重定位——x64 下 RIP-relative 指令没问题,但 x86 下绝对地址会失效 - 调用了
LoadLibraryA/GetProcAddress却没自己解析 PE 导出表,或没处理延迟导入(IAT 为空) - 目标进程开启了 CFG(Control Flow Guard),而 Shellcode 的间接调用(如函数指针跳转)未通过 CFG 验证表
- Shellcode 自身含空字节(
\x00),被当成字符串截断——尤其用strcpy类函数复制时;应全程用memcpy和明确长度操作
调试时别只盯 WriteProcessMemory 返回值,用 OutputDebugString 或远程日志打点,确认 Shellcode 是否真进了内存、是否被 DEP 拦截、是否在入口就访问了非法地址。


















