MmCopyVirtualMemory returns 0x8000000d

Hello folks,
I am trying to call MmCopyVirtualMemory but it keeps returning 0x8000000d. just to give some context: The code is running in the right process context and the virtual address is valid. The virtual address in this case basically an address where my DLL is mapped. I am trying to write something to the in memory image using MmCopyVirtualMemory. !vad on the address indicates that it is EXECUTE_WRITECOPY. I was under the impression that if anything is written to a page with EXECUTE_WRITECOPY protection, a private copy of the page will be created for that process. However, I am seeing MmCopyVirtualMemory consistently failing with error 0x8000000d.
And idea what could be going on? Thanks!

MmCopyVirtualMemory (which is undocumented) is designed for copying from user process to user process. Are you copying from kernel to user? If so, then why not just ProbeForWrite and use RtlCopyMemory?

Thanks Tim. I am able to copy from user space address to kernel buffer but not copy it back. I am using the PreviousMode as KernelMode.

If so, then why not just ProbeForWrite and use RtlCopyMemory?
I did try that before trying the MmCopyVirtualMemory function. ProbeForWrite raises an exception even though the protection flags are EXECUTE_WRITECOPY.

ProbeForWrite raises an exception …

…which means the target virtual address is simply invalid. The most likely scenario here is that you are in the wrong process context.

BTW, have you ever heard of IoAllocateMdl(), MmProbeAndLockPages() and MmMapLockedPagesSpecifyCache() functions? This is how one is supposed to access the userland from the KM driver. You would not have to post your question here if you took this option…

Anton Bassov

Hi Anton, Couple of things. - I have already tried the RtlCopyMemory route, probing and Locking the pages and creating an MDL. All result in an exception. - Although I am doing this from load image notification routine where the process context is correct, I have tried the KeStackAttachProcess too; that didn’t help either. - Now coming to whether memory is valid. I am pretty sure the memory is valid because I am first reading from the exact same location and copying it in a kernel buffer and then modifying the kernel buffer and copying it back. And I can see in the debugger that buffer has the right expected contents after reading. So I am pretty sure the address is valid; it’s the copy operation from kernel to user buffer that fails. Other way round it works. - !vad also works correctly on the user address and shows the protection type as EXECUTE_WRITECOPY The key issue that I am trying to figure out is why I am unable to write to an address which has EXECUTE_WRITECOPY protection.

The key issue that I am trying to figure out is why I am unable to write to an address which has EXECUTE_WRITECOPY protection.

OMG - I completely overlooked this part.

If a page is mapped as a copy-on-write one, what else should one expect if they try to write to it??? Of course you are getting an exception - after all, this is how copy-on-write is meant to work. When you try to modify a copy-on-write page, the CPU raises page fault exception, because the target page is, in actuality, mapped as a RO one in its PTE. The page fault handler allocates a new page, copies the contents of the old one to it , and modifies the target PTE, so that the target address gets backed up by the newly-allocated physical page. This page gets mapped as a writable one, so that you can modify it without any problem.

ProbeForWrite raises an exception

… simply because the target page is mapped as a RO one at the moment. Otherwise, the very concept of COW simply would not work…

even though the protection flags are EXECUTE_WRITECOPY.

The above mentioned sequence would happen transparently to your code if you did it from the userland, but you are trying to do it from a driver. Apparently, page fault handler does not even check this part if you do it from the KM, and dispatches the exception to the “culprit” straight away.

BTW, what are you trying to do? Are you trying to modify some DLL’s executable code or what?

Anton Bassov