A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about kernel-mode development.
 #28289  by flauteABC
 Tue Apr 12, 2016 3:06 pm
I want to place a jumper in Win 10 x64 win32k .text (PatchGuard disabled). However it seems this no longer works (on Windows 8 x64 and before it did):
Code: Select all
	
		PMDL Mdl = NULL;

		__try
		{
			// Create a descriptor
			Mdl = IoAllocateMdl(Address,Length,FALSE,FALSE,NULL);
		
			// Lock pages for io modification access
			MmProbeAndLockPages(Mdl,KernelMode,IoModifyAccess);
			
			// Map physical locked page
			AddrMapped = MmMapLockedPagesSpecifyCache(Mdl,KernelMode,MmNonCached,NULL,FALSE,HighPagePriority);

			RtlCopyMemory(AddrMapped, Data, Length);
		}
		// Cleanup
		__finally 
		{
			if(AddrMapped)
				MmUnmapLockedPages(AddrMapped, Mdl);
			
			if(Mdl != NULL)
			{
				MmUnlockPages(Mdl);
				IoFreeMdl(Mdl);
			}
		}
It fails with: ATTEMPTED_WRITE_TO_READONLY_MEMORY (be) at MmMapLockedPagesSpecifyCache. I am calling the code from the context of csrss.exe (GUI process) and before get win32k via ZwQuerySystemInformation SystemModuleInfo.

- Flaut
 #28316  by Vrtule
 Thu Apr 14, 2016 9:10 pm
AFAIK it is not possible to map a buffer described by a MDL to the krnel memory twice. I mean, if you are trying to describe a kernel memory buffer with a MDL and then to map it into the krnel memory, terrible things may happen. Try to map it into user memory instead.

Some years ago, I used MDLs to modify SSDT shadow: I mapped the table into the user portion of the System process (PID = 4), and modified it through that virtual addresses.
 #28329  by Dmitry Varshavsky
 Sat Apr 16, 2016 3:13 pm
Vrtule wrote:AFAIK it is not possible to map a buffer described by a MDL to the krnel memory twice. I mean, if you are trying to describe a kernel memory buffer with a MDL and then to map it into the krnel memory, terrible things may happen. Try to map it into user memory instead.

Some years ago, I used MDLs to modify SSDT shadow: I mapped the table into the user portion of the System process (PID = 4), and modified it through that virtual addresses.
That's completely incorrect.
1. It is possible to map a buffer, described by a MDL as many times as you need. One physical page may have several virtual addresses. The only important thing is to keep identical memory caching attributes for all mappings.
2. Mapping system memory to user-mode addresses is a really bad practice, even if it's done in system process context.
flauteABC wrote: It fails with: ATTEMPTED_WRITE_TO_READONLY_MEMORY (be) at MmMapLockedPagesSpecifyCache. I am calling the code from the context of csrss.exe (GUI process) and before get win32k via ZwQuerySystemInformation SystemModuleInfo.
- Flaut
The most likely that MmProbeAndLockPages call is failing with that status, not MmMapLockedPagesSpecifyCache.

You have 2 options: disable WP bit or MmGetPhysicalAddress->MmMapIoSpace(Ex)->...->MmUnmapIoSpace. Important thing, if target address is pageable, it must be locked first ( with read memory access )
 #28330  by Vrtule
 Sat Apr 16, 2016 7:32 pm
When looking at documentation to MmMapLockedPagesSpecifyChace (which is usualy used to map a memory described by a MDL), I see the following statemnt:
A driver must not try to create more than one system-address-space mapping for an MDL.
That is what I meant by my previous post.

Of course, it is possible to create multiple mappings for one physical pages (CPU allows it).

I also do not like mapping to user mode part of the System process but I consider is as a better alternative to manually playing with MDL flags.
 #28332  by Dmitry Varshavsky
 Sat Apr 16, 2016 10:44 pm
Vrtule wrote:When looking at documentation to MmMapLockedPagesSpecifyChace (which is usualy used to map a memory described by a MDL), I see the following statemnt:
A driver must not try to create more than one system-address-space mapping for an MDL.
That is what I meant by my previous post.

Of course, it is possible to create multiple mappings for one physical pages (CPU allows it).

I also do not like mapping to user mode part of the System process but I consider is as a better alternative to manually playing with MDL flags.
That is because MmMapLockedPagesSpecifyChace on success internally updates the state of MDL, namely MdlFlags field ( by adding MDL_MAPPED_TO_SYSTEM_VA ) and MappedSystemVa field.
On Windows debug build there is assertions for this:
Code: Select all
ASSERT ((MemoryDescriptorList->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA) == 0);
But on release build the old mapping ( if any ) will be simple overwritten, resulting in system resource wastage. That's why MSDN documentation encourages the use of MmGetSystemAddressForMdlSafe macro, which checks for MDL_MAPPED_TO_SYSTEM_VA flag ( and returns MappedSystemVa instead of excessive MmMapLockedPagesSpecifyCache call ).
That's the only reason.