winappdbg icon indicating copy to clipboard operation
winappdbg copied to clipboard

Shared memory writes break debugged process

Open hatRiot opened this issue 7 years ago • 1 comments

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:

  1. Why mprotect a shared memory section PAGE_WRITECOPY if it's writable?
  2. Why check a mapped section's protection if it's writable?
  3. 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.

hatRiot avatar Aug 15 '18 07:08 hatRiot

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.

MarioVilas avatar Oct 30 '25 21:10 MarioVilas