sharing user/kernel memory

Now ostensibly this should be a simple question. There is plenty written on the topic, but I need to explain my environment. I’m just trying to make a quick and dirty demo capability for Monday (not at all a production system), and I just literally need to be able to read 4 bytes of memory from user memory in kernel and see if it changed.

The documents I have looked at so far are:
http://www.osronline.com/article.cfm?article=39
and
download.microsoft.com/download/e/b/a/.../KM-UMGuide.doc
(I hate that google won’t let me just copy the non-obfuscated URL anymore! google that string to find the doc)

If I knew how to use IOCTLs, I would use them, but I don’t understand them and I’m pretty under the gun, so I wanted to try and use something just doing memory sharing of a single page which userspace could copy into and kernel could read. I wanted to use the KUSER_SHARED_DATA hack that I’ve seen before, but that’s not writable by userspace. I even tried to quick hack the page table entry to make it writable, but of course that didn’t work because I didn’t know how to to it in the context of the userspace application (more on that later).

Speaking of not knowing how to do things “in the context of” some process, that’s why I found the OSR article not helpful either. It said “For the rare device driver that will want to share a buffer directly with a user-mode application that’s located deep within a device stack, an enterprising driver writer can probably find a safe way to call MmMapLocked PagesSpecifyCache in the context of the requesting process.” I.e. that’s not helpful at all because it’s not telling me how I can even do their MmMapLockedPagesSpecifyCache method, and even if it were, If I could get into the context of the userspace app I would just do the quick one bit hack to make KUSER_SHARED_DATA writable.

So in the comments of the OSR post, someone said “I’m a bit puzzled: why not even consider using Section objects?”, so I started looking into section objects. That’s what lead me to the MS paper which talked about IOCTLS (again, I don’t understand them) and Section Objects.

The problem is, that also left me with a question with respect to InitializeObjectAttributes.

For the ObjectName parameter it says “This must either be a fully qualified object name, or a relative path name to the object directory specified by the RootDirectory parameter.” What does it mean for the object name to be fully qualified in this context? I’ve tried the below code with L"demo" and L"\??\demo" for the object name, but I always get ZwCreateSection failed with the below code in DriverEntry().

RtlInitUnicodeString(&objName, L"\??\demo");
InitializeObjectAttributes(&initAttrib, &objName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
//The 0x80000000 is SEC_COMMIT because I’m having include problems if I add winnt.h
Status = ZwCreateSection(&sectionHandle, SECTION_ALL_ACCESS, &initAttrib, 0x1000, PAGE_READWRITE, 0x80000000, NULL);
if(Status != STATUS_SUCCESS){
DbgPrint(“ZwCreateSection failed\n”);
}
baseVA = 0x7ffd0000;
viewSize = 0x1000;
// NtCurrentProcess = ( (HANDLE)(LONG_PTR) -1 ), again winnt.h include issues
Status = ZwMapViewOfSection(sectionHandle, ( (HANDLE)(LONG_PTR) -1 ), &baseVA, 0, 0x1000, NULL, &viewSize, ViewUnmap, MEM_TOP_DOWN, PAGE_READWRITE);
if(Status != STATUS_SUCCESS){
DbgPrint(“ZwMapViewOfSection failed\n”);
}

(Yes, I know SECTION_ALL_ACCESS is discouraged, but I just picked it to try and give my code the quickest possible chance of success).

Any thoughts on what I’m doing wrong, or if there’s a quicker way to simply get kernel to be able to read 4 bytes of userspace memory?

Thanks for all your help

Angie V.

P.s. honestly I’m more comfortable with manipulating page tables than I am with understanding the windows APIs, owing to my background in *nix kernel development. So I had at one point tried to just find the CR3 for the userspace process that I wanted to read memory from, and then was going to manually map physical memory to the virtual memory of my choosing. But I found something strange. People say that when you do !process 0 0 and list the processes on the system, that the DirBase field is the saved CR3 for the process context. But I saw the following:

PROCESS 823c8830 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000
DirBase: 0038b000 ObjectTable: e1000c90 HandleCount: 489.
Image: System

PROCESS 81d0f858 SessionId: none Cid: 030c Peb: 7ffda000 ParentCid: 0004
DirBase: 0a3c0020 ObjectTable: e14cb728 HandleCount: 21.
Image: smss.exe

PROCESS 81f911f8 SessionId: 0 Cid: 0370 Peb: 7ffdb000 ParentCid: 030c
DirBase: 0a3c0040 ObjectTable: e16208a0 HandleCount: 523.
Image: csrss.exe

PROCESS 82044488 SessionId: 0 Cid: 0388 Peb: 7ffdf000 ParentCid: 030c
DirBase: 0a3c0060 ObjectTable: e1606868 HandleCount: 568.
Image: winlogon.exe

And basically everything has a DirBase which 1) is not paged aligned, and 2) would all be pfn numbers 0x0A3C. I don’t think everyone in userspace is sharing a memory space, so what’s up with that? Why doesn’t DirBase show the saved CR3? Is it because it’s a PAE system and I should be looking at the other 32 bits too? (I noticed that EPROCESS.KPROCESS.DirectoryTableBase was listed as [2], so I’m assuming it’s 64 bits wide)

Word of warning: be prepared for some serious static to likely follow in the
way of objections to your goal because it’s not safe. It isn’t - writing to
kernel memory from user mode is about as unsafe as it gets, but I also hear
what you are saying about this being an under the gun thing for Monday, so
here goes.

That being said, I’m confused. Are you:

a.) trying to WRITE to kernel memory then
b.) read ‘user mode memory’ from the kernel

Let’s back up - if all you want to do is read/write 4 bytes, ioctls are BY
FAR the easiest way to go; I can explain how, but I need to know whether
it’s (a) or (b) first.

mm

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@gmail.com
Sent: Sunday, September 19, 2010 1:37 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] sharing user/kernel memory

Now ostensibly this should be a simple question. There is plenty written on
the topic, but I need to explain my environment. I’m just trying to make a
quick and dirty demo capability for Monday (not at all a production system),
and I just literally need to be able to read 4 bytes of memory from user
memory in kernel and see if it changed.

The documents I have looked at so far are:
http://www.osronline.com/article.cfm?article=39
and
download.microsoft.com/download/e/b/a/.../KM-UMGuide.doc
(I hate that google won’t let me just copy the non-obfuscated URL anymore!
google that string to find the doc)

If I knew how to use IOCTLs, I would use them, but I don’t understand them
and I’m pretty under the gun, so I wanted to try and use something just
doing memory sharing of a single page which userspace could copy into and
kernel could read. I wanted to use the KUSER_SHARED_DATA hack that I’ve seen
before, but that’s not writable by userspace. I even tried to quick hack the
page table entry to make it writable, but of course that didn’t work because
I didn’t know how to to it in the context of the userspace application (more
on that later).

Speaking of not knowing how to do things “in the context of” some process,
that’s why I found the OSR article not helpful either. It said “For the rare
device driver that will want to share a buffer directly with a user-mode
application that’s located deep within a device stack, an enterprising
driver writer can probably find a safe way to call MmMapLocked
PagesSpecifyCache in the context of the requesting process.” I.e. that’s not
helpful at all because it’s not telling me how I can even do their
MmMapLockedPagesSpecifyCache method, and even if it were, If I could get
into the context of the userspace app I would just do the quick one bit hack
to make KUSER_SHARED_DATA writable.

So in the comments of the OSR post, someone said “I’m a bit puzzled: why not
even consider using Section objects?”, so I started looking into section
objects. That’s what lead me to the MS paper which talked about IOCTLS
(again, I don’t understand them) and Section Objects.

The problem is, that also left me with a question with respect to
InitializeObjectAttributes.

For the ObjectName parameter it says “This must either be a fully qualified
object name, or a relative path name to the object directory specified by
the RootDirectory parameter.” What does it mean for the object name to be
fully qualified in this context? I’ve tried the below code with L"demo" and
L"\??\demo" for the object name, but I always get ZwCreateSection failed
with the below code in DriverEntry().

RtlInitUnicodeString(&objName, L"\??\demo");
InitializeObjectAttributes(&initAttrib, &objName, OBJ_CASE_INSENSITIVE |
OBJ_KERNEL_HANDLE, NULL, NULL); //The 0x80000000 is SEC_COMMIT because I’m
having include problems if I add winnt.h Status =
ZwCreateSection(&sectionHandle, SECTION_ALL_ACCESS, &initAttrib, 0x1000,
PAGE_READWRITE, 0x80000000, NULL); if(Status != STATUS_SUCCESS){
DbgPrint(“ZwCreateSection failed\n”);
}
baseVA = 0x7ffd0000;
viewSize = 0x1000;
// NtCurrentProcess = ( (HANDLE)(LONG_PTR) -1 ), again winnt.h include
issues Status = ZwMapViewOfSection(sectionHandle, ( (HANDLE)(LONG_PTR) -1 ),
&baseVA, 0, 0x1000, NULL, &viewSize, ViewUnmap, MEM_TOP_DOWN,
PAGE_READWRITE); if(Status != STATUS_SUCCESS){
DbgPrint(“ZwMapViewOfSection failed\n”); }

(Yes, I know SECTION_ALL_ACCESS is discouraged, but I just picked it to try
and give my code the quickest possible chance of success).

Any thoughts on what I’m doing wrong, or if there’s a quicker way to simply
get kernel to be able to read 4 bytes of userspace memory?

Thanks for all your help

Angie V.

P.s. honestly I’m more comfortable with manipulating page tables than I am
with understanding the windows APIs, owing to my background in *nix kernel
development. So I had at one point tried to just find the CR3 for the
userspace process that I wanted to read memory from, and then was going to
manually map physical memory to the virtual memory of my choosing. But I
found something strange. People say that when you do !process 0 0 and list
the processes on the system, that the DirBase field is the saved CR3 for the
process context. But I saw the following:

PROCESS 823c8830 SessionId: none Cid: 0004 Peb: 00000000 ParentCid:
0000
DirBase: 0038b000 ObjectTable: e1000c90 HandleCount: 489.
Image: System

PROCESS 81d0f858 SessionId: none Cid: 030c Peb: 7ffda000 ParentCid:
0004
DirBase: 0a3c0020 ObjectTable: e14cb728 HandleCount: 21.
Image: smss.exe

PROCESS 81f911f8 SessionId: 0 Cid: 0370 Peb: 7ffdb000 ParentCid: 030c
DirBase: 0a3c0040 ObjectTable: e16208a0 HandleCount: 523.
Image: csrss.exe

PROCESS 82044488 SessionId: 0 Cid: 0388 Peb: 7ffdf000 ParentCid: 030c
DirBase: 0a3c0060 ObjectTable: e1606868 HandleCount: 568.
Image: winlogon.exe

And basically everything has a DirBase which 1) is not paged aligned, and 2)
would all be pfn numbers 0x0A3C. I don’t think everyone in userspace is
sharing a memory space, so what’s up with that? Why doesn’t DirBase show the
saved CR3? Is it because it’s a PAE system and I should be looking at the
other 32 bits too? (I noticed that EPROCESS.KPROCESS.DirectoryTableBase was
listed as [2], so I’m assuming it’s 64 bits wide)


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

If you cannot understand IOCTL’s then you should not be trying to mess
with shared memory, the simplest schemes of shared memory use IOCTL’s
and from there range to several orders of magnitude complexity above a
driver handling IOCTL’s. Take a look at src\general\ioctl for samples
how to use IOCTL’s.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

xxxxx@gmail.com” wrote in message
news:xxxxx@ntdev:

> Now ostensibly this should be a simple question. There is plenty written on the topic, but I need to explain my environment. I’m just trying to make a quick and dirty demo capability for Monday (not at all a production system), and I just literally need to be able to read 4 bytes of memory from user memory in kernel and see if it changed.
>
> The documents I have looked at so far are:
> http://www.osronline.com/article.cfm?article=39
> and
> download.microsoft.com/download/e/b/a/.../KM-UMGuide.doc
> (I hate that google won’t let me just copy the non-obfuscated URL anymore! google that string to find the doc)
>
> If I knew how to use IOCTLs, I would use them, but I don’t understand them and I’m pretty under the gun, so I wanted to try and use something just doing memory sharing of a single page which userspace could copy into and kernel could read. I wanted to use the KUSER_SHARED_DATA hack that I’ve seen before, but that’s not writable by userspace. I even tried to quick hack the page table entry to make it writable, but of course that didn’t work because I didn’t know how to to it in the context of the userspace application (more on that later).
>
> Speaking of not knowing how to do things “in the context of” some process, that’s why I found the OSR article not helpful either. It said “For the rare device driver that will want to share a buffer directly with a user-mode application that’s located deep within a device stack, an enterprising driver writer can probably find a safe way to call MmMapLocked PagesSpecifyCache in the context of the requesting process.” I.e. that’s not helpful at all because it’s not telling me how I can even do their MmMapLockedPagesSpecifyCache method, and even if it were, If I could get into the context of the userspace app I would just do the quick one bit hack to make KUSER_SHARED_DATA writable.
>
> So in the comments of the OSR post, someone said “I’m a bit puzzled: why not even consider using Section objects?”, so I started looking into section objects. That’s what lead me to the MS paper which talked about IOCTLS (again, I don’t understand them) and Section Objects.
>
> The problem is, that also left me with a question with respect to InitializeObjectAttributes.
>
> For the ObjectName parameter it says “This must either be a fully qualified object name, or a relative path name to the object directory specified by the RootDirectory parameter.” What does it mean for the object name to be fully qualified in this context? I’ve tried the below code with L"demo" and L"\??\demo" for the object name, but I always get ZwCreateSection failed with the below code in DriverEntry().
>
> RtlInitUnicodeString(&objName, L"\??\demo");
> InitializeObjectAttributes(&initAttrib, &objName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
> //The 0x80000000 is SEC_COMMIT because I’m having include problems if I add winnt.h
> Status = ZwCreateSection(&sectionHandle, SECTION_ALL_ACCESS, &initAttrib, 0x1000, PAGE_READWRITE, 0x80000000, NULL);
> if(Status != STATUS_SUCCESS){
> DbgPrint(“ZwCreateSection failed\n”);
> }
> baseVA = 0x7ffd0000;
> viewSize = 0x1000;
> // NtCurrentProcess = ( (HANDLE)(LONG_PTR) -1 ), again winnt.h include issues
> Status = ZwMapViewOfSection(sectionHandle, ( (HANDLE)(LONG_PTR) -1 ), &baseVA, 0, 0x1000, NULL, &viewSize, ViewUnmap, MEM_TOP_DOWN, PAGE_READWRITE);
> if(Status != STATUS_SUCCESS){
> DbgPrint(“ZwMapViewOfSection failed\n”);
> }
>
> (Yes, I know SECTION_ALL_ACCESS is discouraged, but I just picked it to try and give my code the quickest possible chance of success).
>
> Any thoughts on what I’m doing wrong, or if there’s a quicker way to simply get kernel to be able to read 4 bytes of userspace memory?
>
> Thanks for all your help
>
> Angie V.
>
>
> P.s. honestly I’m more comfortable with manipulating page tables than I am with understanding the windows APIs, owing to my background in *nix kernel development. So I had at one point tried to just find the CR3 for the userspace process that I wanted to read memory from, and then was going to manually map physical memory to the virtual memory of my choosing. But I found something strange. People say that when you do !process 0 0 and list the processes on the system, that the DirBase field is the saved CR3 for the process context. But I saw the following:
>
>
> PROCESS 823c8830 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000
> DirBase: 0038b000 ObjectTable: e1000c90 HandleCount: 489.
> Image: System
>
> PROCESS 81d0f858 SessionId: none Cid: 030c Peb: 7ffda000 ParentCid: 0004
> DirBase: 0a3c0020 ObjectTable: e14cb728 HandleCount: 21.
> Image: smss.exe
>
> PROCESS 81f911f8 SessionId: 0 Cid: 0370 Peb: 7ffdb000 ParentCid: 030c
> DirBase: 0a3c0040 ObjectTable: e16208a0 HandleCount: 523.
> Image: csrss.exe
>
> PROCESS 82044488 SessionId: 0 Cid: 0388 Peb: 7ffdf000 ParentCid: 030c
> DirBase: 0a3c0060 ObjectTable: e1606868 HandleCount: 568.
> Image: winlogon.exe
>
> …
>
> And basically everything has a DirBase which 1) is not paged aligned, and 2) would all be pfn numbers 0x0A3C. I don’t think everyone in userspace is sharing a memory space, so what’s up with that? Why doesn’t DirBase show the saved CR3? Is it because it’s a PAE system and I should be looking at the other 32 bits too? (I noticed that EPROCESS.KPROCESS.DirectoryTableBase was listed as [2], so I’m assuming it’s 64 bits wide)

>a production system), and I just literally need to be able to read 4 bytes of memory from user memory

in kernel and see if it changed.

Better to send an IOCTL to the driver on each update of these bytes. Simplest possible way.

Other ways:

  • allocate in user mode, then send this memory as IOCTL’s buffer with an overlapped IOCTL. The driver will pend this IOCTL for a long time, and call MmGetSystemAddressForMdlSafe(Irp->MdlAddress). Then the driver can update by using this mapped address - it is a double map to both user and kernel.

  • allocate in kernel mode, allocate an exact multiple of PAGE_SIZE to avoid exposing other kernel memory blocks to user mode, and then call MmMapLockedPages(UserMode) on the MDL describing this kernel memory.

Note that shared memory is evil :slight_smile: it is not protected by the locks automatically, so corruptions of such data can (and do) occur. It is more or less OK if there is 1 writer and many readers, like for KUSER_SHARED_DATA.

I’m really very much surprised that in UNIX you can directly update PTEs and not mess up the VM subsystem. I think there are some APIs in UNIX too, like kmap() in Linux.

And surely adding an IOCTL to the driver is times simpler then shared memory.


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

mm said:

“a.) trying to WRITE to kernel memory then
b.) read ‘user mode memory’ from the kernel”

I want to read 4 bytes of memory from kernel space, but because that was the whole EPROCESS route and not working, I’m fine with reading the memory from userspace and copying it to somewhere that kernel space can read it.

I’m fine with IOCTLs if people can point me at an example which is pretty much just copy and paste for both the userspace and kernel side, because my primary concern was that it was going to take too much effort to work through all the documentation to understand it. But if there’s some code which is very close to what I want to do then I suppose there’s enough hours left in the day to try and understand it :wink:

Angie V.

Thanks Don, I will check src\general\ioctl to start with (I didn’t have general because I didn’t install everything).

Angie V.

We already did - IOCTL.

That’s as close as you are going to get.

Basically, what you roughly have to do is as follows (using the Win7 WDK wdm
sample, as that’s all I have installed on this particular machine):

sioctl.c:

In SioctlDeviceControl(), change the code below to do what you want - read
the memory, write it to OutBuf, et. c. It almost does that already.

case IOCTL_SIOCTL_METHOD_BUFFERED:

//
// In this method the I/O manager allocates a buffer large enough to
// to accommodate larger of the user input buffer and output buffer,
// assigns the address to Irp->AssociatedIrp.SystemBuffer, and
// copies the content of the user input buffer into this
SystemBuffer
//

SIOCTL_KDPRINT((“Called IOCTL_SIOCTL_METHOD_BUFFERED\n”));
PrintIrpInfo(Irp);

//
// Input buffer and output buffer is same in this case, read the
// content of the buffer before writing to it
//

inBuf = Irp->AssociatedIrp.SystemBuffer;
outBuf = Irp->AssociatedIrp.SystemBuffer;

//
// Read the data from the buffer
//

SIOCTL_KDPRINT((“\tData from User :”));
//
// We are using the following function to print characters instead
// DebugPrint with %s format because we string we get may or
// may not be null terminated.
//
PrintChars(inBuf, inBufLength);

//
// Write to the buffer over-writes the input buffer content
//

RtlCopyBytes(outBuf, data, outBufLength);

SIOCTL_KDPRINT(("\tData to User : "));
PrintChars(outBuf, datalen );

//
// Assign the length of the data copied to IoStatus.Information
// of the Irp and complete the Irp.
//

Irp->IoStatus.Information =
(outBufLength
//
// When the Irp is completed the content of the SystemBuffer
// is copied to the User output buffer and the SystemBuffer is
// is freed.
//

break;

Then in the user mode application, only send IOCTL_SIOCTL_METHOD_BUFFERED
(not any of the other ones) and modify it accept the value back from your
driver.

Good luck,

mm

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@gmail.com
Sent: Sunday, September 19, 2010 3:07 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] sharing user/kernel memory

mm said:

“a.) trying to WRITE to kernel memory then
b.) read ‘user mode memory’ from the kernel”

I want to read 4 bytes of memory from kernel space, but because that was the
whole EPROCESS route and not working, I’m fine with reading the memory from
userspace and copying it to somewhere that kernel space can read it.

I’m fine with IOCTLs if people can point me at an example which is pretty
much just copy and paste for both the userspace and kernel side, because my
primary concern was that it was going to take too much effort to work
through all the documentation to understand it. But if there’s some code
which is very close to what I want to do then I suppose there’s enough hours
left in the day to try and understand it :wink:

Angie V.


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

> I’m fine with IOCTLs if people can point me at an example which is pretty much just copy and paste

for both the userspace and kernel side, because my primary concern was that it was going to take too
much effort to work through all the documentation to understand it.

So, you agree to patch the alive PTE tables and not require the documentation, but need the documentation to send an IOCTL?


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