Shared memory writes break debugged process
Under certain conditions (active shared memory, for example), modifying a shared memory map with PAGE_WRITECOPY can have adverse effects on the target process.
In the Process class exists the following:
hProcess = self.get_handle( win32.PROCESS_VM_WRITE |
win32.PROCESS_VM_OPERATION |
win32.PROCESS_QUERY_INFORMATION )
mbi = self.mquery(lpBaseAddress)
if not mbi.has_content():
raise ctypes.WinError(win32.ERROR_INVALID_ADDRESS)
if mbi.is_image() or mbi.is_mapped():
prot = win32.PAGE_WRITECOPY
elif mbi.is_writeable():
prot = None
elif mbi.is_executable():
prot = win32.PAGE_EXECUTE_READWRITE
else:
prot = win32.PAGE_READWRITE
if prot is not None:
In my case, I'm debugging a process that communicates with another via a shared memory section (via CreateFileMappingW with INVALID_HANDLE_VALUE and MapViewOfFile). When I attempt to write to this shared section, poke_dword will first attempt to detect the page protections and, if it's an image or mapped, mprotect it with PAGE_WRITECOPY, even if the section is writable. This causes the parent process to lock up and/or crash.
A couple things are unclear to me:
- Why mprotect a shared memory section
PAGE_WRITECOPYif it's writable? - Why check a mapped section's protection if it's writable?
- Why would this cause other processes sharing/accessing the section to crash/freeze?
I was able to fix this by simply switching the order of the checks:
if mbi.is_writeable():
prot = None
elif mbi.is_image() or mbi.is_mapped():
prot = win32.PAGE_WRITECOPY
elif mbi.is_executable():
prot = win32.PAGE_EXECUTE_READWRITE
else:
prot = win32.PAGE_READWRITE
I haven't fully debugged the root cause, but I do think the PAGE_WRITECOPY is at fault here. I'm also not sure what implications my fix may have under other scenarios.
Ok, so I've been thinking about this one and I don't think there's an easy solution. The original idea was to make pages write-copy when they belong to a DLL to prevent the patch from showing up in other processes, which was a thing that could happen in older version of Windows. So I'd need to 1) thoroughly test what happens if I blindly write into writeable areas without making a copy, 2) at least make an effort to tell if this memory section is being shared with another process. Since the current behavior was fine for most scenarios I did not address this at the time it was reported, and probably I won't for a while longer, but at least I wanted to document why.