Locking user process pages from kernelmode

I’ve been trying to figure a quick way to map pages belonging to a target process to system memory (win7 32bit). Currently I’m getting the target PID from another usermode assistant process. I am aware of all the fact that this is generally a bad idea. Here’s what I’ve done so far:

  1. Get DirectoryTableBase from KPROCESS.
  2. Pagewalk to PE header map it (using MmMapIoSpace) and get offset to relevant pages.
  3. Pagewalk again to map all relevant pages to system space (IoAllocateMdl + MmProbeAndLockPages).

This method works well for small programs, but when I try it on bigger ones my pagewalk partially fails (some PTEs contain the value ffffffff`00000460). Since the invalid PTEs becomes valid during several pagewalk attempts (and vice versa), I’m guessing the kernel swaps pages out of memory.

So my question is - how can I force the kernel to swap all pages of a process into memory so that my pagewalk will succeed? Is there a routine that makes the kernel swap pages into memory (given the process handle and the usermode virtual address of the page)?

Alternatively - are there any documented or undocumented routines that map pages to system space when given a process handle and a usermode virtual address?

I am afraid you will be requested (most likely in capitals, of course) by the usual suspects to disclose your name, as well as that of your company, pretty shortly. I am already holding my breath in anticipation of a good comedy…

Anton Bassov

Are you running the thread as part of the process (i.e.
KeStackAttachProcess)? MmProbeAndLockPages will make the pages resident if
you are in the context of the process, and it is a valid address range.

It is a less than great idea, but there are reasons to do it. Just be sure
to have a strong set of detection mechanisms so you can unmap the pages if
the process is dying.

Don Burn
Windows Driver Consulting
Website: http://www.windrvr.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Thursday, September 29, 2016 7:05 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Locking user process pages from kernelmode

I’ve been trying to figure a quick way to map pages belonging to a target
process to system memory (win7 32bit). Currently I’m getting the target PID
from another usermode assistant process. I am aware of all the fact that
this is generally a bad idea. Here’s what I’ve done so far:

1) Get DirectoryTableBase from KPROCESS.
2) Pagewalk to PE header map it (using MmMapIoSpace) and get offset to
relevant pages.
3) Pagewalk again to map all relevant pages to system space (IoAllocateMdl +
MmProbeAndLockPages).

This method works well for small programs, but when I try it on bigger ones
my pagewalk partially fails (some PTEs contain the value ffffffff`00000460).
Since the invalid PTEs becomes valid during several pagewalk attempts (and
vice versa), I’m guessing the kernel swaps pages out of memory.

So my question is - how can I force the kernel to swap all pages of a
process into memory so that my pagewalk will succeed? Is there a routine
that makes the kernel swap pages into memory (given the process handle and
the usermode virtual address of the page)?

Alternatively - are there any documented or undocumented routines that map
pages to system space when given a process handle and a usermode virtual
address?


NTDEV is sponsored by OSR

Visit the list online at:
http:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software
drivers!
Details at http:

To unsubscribe, visit the List Server section of OSR Online at
http:</http:></http:></http:>

>Are you running the thread as part of the process (i.e. KeStackAttachProcess)?

Apparently not…

In fact, I am quite “impressed” by the direct use of KPROCESS’s field(s), as well as by calling MmMapIoSpace() (which,IIRC, simply updates the PTE without even incrementing target page’s refcount in PFN database) in this context…

Anton Bassov

Using KeStackAttachProcess, locking the pages and staying attached to the target process gave me the needed result. Thanks for the advice.

There was one strange thing though. when I tried to map the pages using MmGetSystemAddressForMdlSafe or MmMapLockedPagesSpecifyCache (in order to allow the driver to detach from the process) the mapping to system space was inconsistent. I was getting random pages mapped alongside correctly mapped pages. The first page was always correctly mapped, but from there it was unpredictable. I checked the page index array generated at the end of the MDL after the call to MmProbeAndLockPages, and everything was correct.

Any thoughts on why this happens?

> Any thoughts on why this happens?

My guess - the process address space had been changed after pages were locked and mapped but before they were accessed by your driver. Locking and mapping user space pages doesn’t prevent from a process address space being changed. For example some virtual address ranges might be released and related pages are not part of a process space anymore, they can’t be reused as they are locked but their content is not updated with the current process state.

What did you mean by “correct”?
MDL contains some PFNs and they are always “correct” in the sense that they correspond to some physical pages. These physical pages are always “valid” as they are a part of underlying hardware.

What inconsistency did you see? Did you lock the pages for write or read?

I locked the pages for read. I’ll try to illustrate:

Lets say I wanted to map 5 pages to system memory. After the call to MmProbeAndLockPages, this is what the physical PFN list at the tail of the MDL looks like:

page 1
page 2
page 3
page 4
page 5

all these pages contain the relevant data (checked with !d command in windbg). After the call to MmGetSystemAddressForMdlSafe, when I check the data in the pages from the returned system address (using d command) I get:

page 1
page ??? (this page contains data from an unknown location)
page ???
page 3
page ???
page 5

on another attempt I might get:

page 1
page 2
page 3
page ???
page ???

This is what I meant by inconsistency. Since MmGetSystemAddressForMdlSafe didn’t fail I expected to find a system mapped address range corresponding to the physical PFN list at the tail of the MDL.

Which exactly d command are you using?