WriteProcessMemory callers should continue requesting both PROCESS_VM_WRITE and PROCESS_VM_OPERATION; success with only PROCESS_VM_WRITE is observable implementation behavior for some writable target pages, not the documented access contract.
Why the tested call succeeds
The public contract states that the handle must contain both rights:
-
PROCESS_VM_WRITEpermits writing to process memory. -
PROCESS_VM_OPERATIONpermits operations on the process address space and is explicitly associated with bothVirtualProtectExandWriteProcessMemoryin the process-rights table.^1^ - The
WriteProcessMemoryreference likewise requires both rights.^2^
However, Microsoft has described WriteProcessMemory as conditionally changing page protection when the destination is read-only: it temporarily makes the page writable, writes the bytes, and restores the original protection. This debugger-oriented behavior requires the caller to be able to modify protection; otherwise that attempt fails.^3^ VirtualProtectEx itself requires PROCESS_VM_OPERATION.^4^
That produces two relevant cases:
- The destination is already writable.
The current Windows implementation may complete the copy usingPROCESS_VM_WRITEwithout performing a protection operation. This is consistent with the observed result. - The destination is not writable and
WriteProcessMemorymust adjust its protection.
The operation needs the authority represented byPROCESS_VM_OPERATION; a handle lacking that right cannot rely on the write succeeding.
The tested repository therefore demonstrates that PROCESS_VM_OPERATION is not necessarily checked on every successful execution path. It does not establish that the right can safely be omitted from code intended to satisfy the API contract across target pages or Windows versions.
Recommended access mask
Use the documented minimum for production code:
DWORD access =
PROCESS_VM_WRITE |
PROCESS_VM_OPERATION |
PROCESS_QUERY_LIMITED_INFORMATION;
HANDLE process = OpenProcess(access, FALSE, processId);
if (!process) {
// Handle GetLastError().
}
Add PROCESS_VM_READ only if the program also calls ReadProcessMemory; it is not part of the documented WriteProcessMemory requirement.^1^
Is the documentation inaccurate?
It is conservative rather than a precise description of every internal path. The text documents the supported permissions callers must obtain, while the implementation can avoid using PROCESS_VM_OPERATION when no address-space operation is necessary.
A useful documentation clarification would be:
Callers must request
PROCESS_VM_WRITEandPROCESS_VM_OPERATION. Some implementations may successfully write to an already-writable region with onlyPROCESS_VM_WRITE, but applications must not rely on that behavior.
This distinction can be submitted through Feedback → This page on the WriteProcessMemory documentation page, including:
- the Windows build tested;
- the exact
OpenProcessaccess mask; - the target page’s protection;
- a minimal reproducer showing success without
PROCESS_VM_OPERATION; - whether the same test fails against a read-only target page.
References