Why can't write user mode virtual memory?

When I try to probe and lock a piece of memory for IoWriteAccess, an exception of STATUS_ACCESS_VIOLATION occured. I also tried IoReadAccess, the same thing happeded.

NTSTATUS WriteToVirtualMemory(PVOID dest, PVOID src, SIZE_T size)
{
NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
PMDL Mdl = NULL;
PVOID MappedAddress = NULL;
PVOID SeMem = NULL;

DebugPrint(“[WriteToVirtualMemory] dest=%08X src=%08X size=%d”, dest, src, size);

Mdl = IoAllocateMdl(dest, size, FALSE, FALSE, NULL);
if(Mdl==NULL)
{
DebugPrint(“[WriteToVirtualMemory]: Allocate MDL failed!”);
ntStatus = STATUS_UNSUCCESSFUL;
goto clean_up;
}

ntStatus = MmProtectMdlSystemAddress(Mdl, PAGE_EXECUTE_READWRITE);
if(NT_SUCCESS(ntStatus))
{
DebugPrint(“[WriteToVirtualMemory]: Protect pages failed with %s!”, OsrNTStatusToString(ntStatus));
goto clean_up;
}

try
{
MmProbeAndLockPages(Mdl, KernelMode, IoWriteAccess);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
ntStatus = GetExceptionCode();
DebugPrint(“[WriteToVirtualMemory]: Probe for write failed with %s”, OsrNTStatusToString(ntStatus));
IoFreeMdl(Mdl);
return ntStatus;
}

MappedAddress = MmMapLockedPagesSpecifyCache(Mdl, KernelMode, MmCached, NULL, FALSE, NormalPagePriority);
if(NULL==MappedAddress)
{
DebugPrint(“[WriteToVirtualMemory]: Map pages failed!”);
ntStatus = STATUS_UNSUCCESSFUL;
goto clean_up;
}

RtlCopyMemory(MappedAddress, src, size);
ntStatus = STATUS_SUCCESS;

clean_up:

if(MappedAddress)
{
MmUnmapLockedPages(MappedAddress, Mdl);
}

if(Mdl)
{
MmUnlockPages(Mdl);
IoFreeMdl(Mdl);
}

return ntStatus;
}

I think the memory is already locked in because I can read the data from that address (dest) without BSOD.

And I can write to the address in user mode by WriteProcessMemory().

Cound anyone help me? Thanks a lot!

“The MmProtectMdlSystemAddress routine can only be called on an MDL that has already been mapped. For example, the routine can be called on an MDL mapped by MmMapLockedPagesSpecifyCache.”

In addition to that, I think calling MmProtectMdlSystemAddress() is
superfluous in this case as MDL mappings are already readable, writable &
executable by default.

  • Cay

On Thu, 15 Jan 2009 11:27:52 +0100, wrote:
> “The MmProtectMdlSystemAddress routine can only be called on an MDL that
> has already been mapped. For example, the routine can be called on an
> MDL mapped by MmMapLockedPagesSpecifyCache.”

Well, I’m not sure about the executable part…

  • Cay

On Thu, 15 Jan 2009 12:05:10 +0100, Cay Bremer wrote:
> In addition to that, I think calling MmProtectMdlSystemAddress() is
> superfluous in this case as MDL mappings are already readable, writable
> & executable by default.
>
>
> - Cay
>
>
> On Thu, 15 Jan 2009 11:27:52 +0100, wrote:
>> “The MmProtectMdlSystemAddress routine can only be called on an MDL
>> that has already been mapped. For example, the routine can be called on
>> an MDL mapped by MmMapLockedPagesSpecifyCache.”

Thank you Sercan and Cay. But forget MmProtectMdlSystemAddress, why it is failed to lock the pages?

Yes, MmProtectMdlSystemAddress() isn’t the culprit inasmuch as it will
rather return STATUS_NOT_MAPPED_VIEW than issue a bug check (but your
subsequent evaluation is also wrong).

Are the pointers dest & src valid? Is it running in the target’s context?
What does the bug check read, etc.?
Please provide more information.

  • Cay

On Thu, 15 Jan 2009 12:25:07 +0100, wrote:
> Thank you Sercan and Cay. But forget MmProtectMdlSystemAddress, why it
> is failed to lock the pages?

Sorry, I misunderstood your question - it’s about an exception, not a bug
check.
I guess dest or the context is wrong.

  • Cay

On Thu, 15 Jan 2009 12:52:00 +0100, Cay Bremer wrote:
> Yes, MmProtectMdlSystemAddress() isn’t the culprit inasmuch as it will
> rather return STATUS_NOT_MAPPED_VIEW than issue a bug check (but your
> subsequent evaluation is also wrong).
>
> Are the pointers dest & src valid? Is it running in the target’s
> context? What does the bug check read, etc.?
> Please provide more information.
>
>
> - Cay
>
>
> On Thu, 15 Jan 2009 12:25:07 +0100, wrote:
>> Thank you Sercan and Cay. But forget MmProtectMdlSystemAddress, why it
>> is failed to lock the pages?

> ntStatus = MmProtectMdlSystemAddress(Mdl, PAGE_EXECUTE_READWRITE);

Read the documentation on this. This require the already mapped MDL, and your MDL is not mapped, it is even not locked yet.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

Nick Lee wrote:

Thank you Sercan and Cay. But forget MmProtectMdlSystemAddress,
why it is failed to lock the pages?

What? I thought your name was Finewings?

I have two accounts. Now I am at home with this account logged in.

I mean, when the I want to write data to a virtual address, is it the right to do this. Why the destination page can be locked in? Is it because its protection type doesn’t fit? This thread runs in the target process’s context.

Pay attention to that: An exception of STATUS_ACCESS_VIOLATION will also come out even I ask for “IoReadAccess” in MmProbeAndLockPages.

NTSTATUS WriteToVirtualMemory(PVOID dest, PVOID src, SIZE_T size)
{
NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
PMDL Mdl = NULL;
PVOID MappedAddress = NULL;
PVOID SeMem = NULL;

DebugPrint(“[WriteToVirtualMemory] dest=%08X src=%08X size=%d”, dest, src,
size);

Mdl = IoAllocateMdl(dest, size, FALSE, FALSE, NULL);
if(Mdl==NULL)
{
DebugPrint(“[WriteToVirtualMemory]: Allocate MDL failed!”);
ntStatus = STATUS_UNSUCCESSFUL;
goto clean_up;
}

try
{
MmProbeAndLockPages(Mdl, KernelMode, IoWriteAccess);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
ntStatus = GetExceptionCode();
DebugPrint(“[WriteToVirtualMemory]: Probe for write failed with %s”,
OsrNTStatusToString(ntStatus));
IoFreeMdl(Mdl);
return ntStatus;
}

MappedAddress = MmMapLockedPagesSpecifyCache(Mdl, KernelMode, MmCached, NULL,
FALSE, NormalPagePriority);
if(NULL==MappedAddress)
{
DebugPrint(“[WriteToVirtualMemory]: Map pages failed!”);
ntStatus = STATUS_UNSUCCESSFUL;
goto clean_up;
}

RtlCopyMemory(MappedAddress, src, size);
ntStatus = STATUS_SUCCESS;

clean_up:

if(MappedAddress)
{
MmUnmapLockedPages(MappedAddress, Mdl);
}

if(Mdl)
{
MmUnlockPages(Mdl);
IoFreeMdl(Mdl);
}

return ntStatus;
}

Perhaps the pages you are asking for write access to are explicitly marked
as read only?
Mark Roddy

On Thu, Jan 15, 2009 at 9:58 AM, wrote:

> I have two accounts. Now I am at home with this account logged in.
>
> I mean, when the I want to write data to a virtual address, is it the right
> to do this. Why the destination page can be locked in? Is it because its
> protection type doesn’t fit? This thread runs in the target process’s
> context.
>
> Pay attention to that: An exception of STATUS_ACCESS_VIOLATION will also
> come out even I ask for “IoReadAccess” in MmProbeAndLockPages.
>
> NTSTATUS WriteToVirtualMemory(PVOID dest, PVOID src, SIZE_T size)
> {
> NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
> PMDL Mdl = NULL;
> PVOID MappedAddress = NULL;
> PVOID SeMem = NULL;
>
> DebugPrint(“[WriteToVirtualMemory] dest=%08X src=%08X size=%d”,
> dest, src,
> size);
>
> Mdl = IoAllocateMdl(dest, size, FALSE, FALSE, NULL);
> if(Mdl==NULL)
> {
> DebugPrint(“[WriteToVirtualMemory]: Allocate MDL failed!”);
> ntStatus = STATUS_UNSUCCESSFUL;
> goto clean_up;
> }
>
> try
> {
> MmProbeAndLockPages(Mdl, KernelMode, IoWriteAccess);
> }
> except(EXCEPTION_EXECUTE_HANDLER)
> {
> ntStatus = GetExceptionCode();
> DebugPrint(“[WriteToVirtualMemory]: Probe for write failed
> with %s”,
> OsrNTStatusToString(ntStatus));
> IoFreeMdl(Mdl);
> return ntStatus;
> }
>
> MappedAddress = MmMapLockedPagesSpecifyCache(Mdl, KernelMode,
> MmCached, NULL,
> FALSE, NormalPagePriority);
> if(NULL==MappedAddress)
> {
> DebugPrint(“[WriteToVirtualMemory]: Map pages failed!”);
> ntStatus = STATUS_UNSUCCESSFUL;
> goto clean_up;
> }
>
> RtlCopyMemory(MappedAddress, src, size);
> ntStatus = STATUS_SUCCESS;
>
> clean_up:
>
> if(MappedAddress)
> {
> MmUnmapLockedPages(MappedAddress, Mdl);
> }
>
> if(Mdl)
> {
> MmUnlockPages(Mdl);
> IoFreeMdl(Mdl);
> }
>
> return ntStatus;
> }
>
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

Yes, I think the pages are excutable and readable. But why can’t I ask for “IoReadAccess”?

If you are trying to write to user memory from your driver and you are already in the correct process context why not just call RtlCopyMemory() under try/except. Of course before doing that you need to ProbeForWrite() to make sure that the memory is indeed user memory and appears to be writable.

Looking at the function prototyp if you are not in the right process context it is not going to work.

Also !pte extension in the debugger is extremly handy in determining if the adress is valid, readable, writable, etc…

Alex

Date: Thu, 15 Jan 2009 20:22:32 -0500> From: xxxxx@msn.com> To: xxxxx@lists.osr.com> Subject: RE:[ntdev] Why can’t write user mode virtual memory?> > Yes, I think the pages are excutable and readable. But why can’t I ask for “IoReadAccess”? > > —> NTDEV is sponsored by OSR> > For our schedule of WDF, WDM, debugging and other seminars visit: > http://www.osr.com/seminars\> > To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer


Windows Live?: Keep your life in sync.
http://windowslive.com/explore?ocid=TXT_TAGLM_WL_t1_allup_explore_012009

Then how to change the user mode vitual memory’s protection type, just like VirtualProtect does in user mode?

This would rank fairly high in the list of Really Really Bad Ideas.

Note that when you are doing operations like this, you are acting as a proxy
for the user, and should not presume to have privileges that exceed those of
the user. This means that if the user couldn’t write to that memory, you
shouldn’t either. Otherwise, you can happily ignore the user’s protected
memory and write all over their code or other protected space, which strikes
me as an exceptionally poor design, unless, of course, you are doing
something like writing a rootkit that is designed to inject malware code
into the user’s space.

Why would you even *consider* the action of writing into user
write-protected memory? There’s a *reason* that memory is write-protected,
and you should not change it. If the *user* does VirtualProtect, it is the
user’s responsibility, but a driver should definitely not go around trying
to do this.

Why do you have user-mode addresses anyway? Wouldn’t you want to use
kernel-mapped pages for the buffer?
joe

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@msn.com
Sent: Friday, January 16, 2009 12:21 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Why can’t write user mode virtual memory?

Then how to change the user mode vitual memory’s protection type, just like
VirtualProtect does in user mode?


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


This message has been scanned for viruses and dangerous content by
MailScanner, and is believed to be clean.

I am wondering when a region of EXCUTE_READWRITE user mode memory was mapped to system address, was it still copy-on-write?

IIRC the CPU mode which Windows uses does not honor the “write protect” PTE bit, so, COW is impossible in the kernel.

This information can be dated though.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

wrote in message news:xxxxx@ntdev…
>I am wondering when a region of EXCUTE_READWRITE user mode memory was mapped to system address, was it still copy-on-write?
>
>

Thank you very much!

Beginning with Windows 2000, read-only kernel memory is write-protected
unless large pages are used.

  • Cay

On Fri, 16 Jan 2009 15:16:37 +0100, Maxim S. Shatskih
wrote:
> IIRC the CPU mode which Windows uses does not honor the “write
> protect” PTE bit, so, COW is impossible in the kernel.
>
> This information can be dated though.