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(§ionHandle, 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)