Reading pageable memory at HIGH_LEVEL

Forum for discussion about kernel-mode development.

Reading pageable memory at HIGH_LEVEL

Postby pwl » Fri Jul 07, 2017 6:22 pm

I've a small hypervisor that is able to intercept some exceptions. Let's call it exception EXC. When EXC is raised in kernelmode, hypervisor gets control via VmExit and I'm able to dereference memory at GUEST_RIP (pointing to kernelspace) to find out what instruction raised EXC. When GUEST_RIP points to userspace, attempts to deref this memory ends with bugcheck 0xD1:

Code: Select all
The DRIVER_IRQL_NOT_LESS_OR_EQUAL bug check has a value of 0x000000D1. This indicates that a kernel-mode driver attempted to access pageable memory at a process IRQL that was too high.


My questions are:
1. Is it safe to simply dereference kernel memory inside a kernel driver?
2. How to solve the bugcheck issue?
3. Assuming GUEST_RIP points to userspace, is it necessary to set cr3 to GUEST_CR3 before reading GUEST_RIP memory? Guest's RIP comes from a random userspace process and each process has its own cr3 value.
pwl
 
Posts: 6
Joined: Sat Jul 01, 2017 7:44 pm
Reputation point: 0

Re: Reading pageable memory at HIGH_LEVEL

Postby pwl » Sun Jul 09, 2017 9:30 am

I tried this:

Code: Select all

NTSTATUS
ReadPageableMemory(
   PVOID VirtualAddress,
   ULONG Length,
   PUCHAR DestBuffer
)
{
   mdl = IoAllocateMdl(VirtualAddress, Length, FALSE, FALSE, NULL);
   if (!mdl)
   {
      ...
   }
   try {      
      MmProbeAndLockPages(mdl, UserMode, IoReadAccess);
   }
   except(EXCEPTION_EXECUTE_HANDLER)
   {
      ...
   }
   SrcBuffer = MmGetSystemAddressForMdlSafe(mdl, HighPagePriority | MdlMappingNoExecute);
   if (!SrcBuffer) {
      ...
   }
   RtlCopyMemory(DestBuffer, SrcBuffer, Length);
   MmUnlockPages(mdl);
   IoFreeMdl(mdl);
        ...


I invoke it like this

Code: Select all
KeLowerIrql(GuestIrql);
HostCr3 = __readcr3();
__writecr3(VmxRead(GUEST_CR3));
ReadPageableMemory((PVOID)GuestRip, sizeof(GuestInstrBuf), GuestInstrBuf);
KeRaiseIrql(HIGH_LEVEL, &GuestIrql);
__writecr3(HostCr3);


The result is, the hypervisor works for some time (seconds), then either:
- vmware hangs
- VmxReads from VMCS start to fail without providing error codes
- BugCheck 101 happens with processors stuck in ReadPageableMemory (apparently TLB flushes happen inside and it's time consuming)

I just need to read few bytes to identify the instruction at GuestRIP.
pwl
 
Posts: 6
Joined: Sat Jul 01, 2017 7:44 pm
Reputation point: 0

Re: Reading pageable memory at HIGH_LEVEL

Postby m5home » Sat Sep 02, 2017 1:50 pm

I don't think anyone can read the pageable memory when IRQL is higher than APC_LEVEL.
The woman of my avatar: MiYue, the first empress dowager of China. In the TV series "The Legend of MiYue", my favourite movie star SunLi plays MiYue.
User avatar
m5home
 
Posts: 82
Joined: Wed Jun 06, 2012 1:21 am
Reputation point: 50

Re: Reading pageable memory at HIGH_LEVEL

Postby Vrtule » Sat Sep 02, 2017 2:38 pm

1) No, the restrictions are the same as for user mode memory – you cannot safely dereference pageable kernel memory at IRQL >= DISPATCH_LEVEL.
2) your routine actually does it – you can describe the target memory region by a MDL and lock the region, so the memory won't go away (into the page file etc.). However, you need to do this at reasonably low IRQL and you still may run into a bugcheck if the target memory region does not exist.

Why is your hypervisor running at IRQL = HIGH_LEVEL?
User avatar
Vrtule
 
Posts: 413
Joined: Sat Mar 13, 2010 9:14 pm
Location: Czech Republic
Reputation point: 92


Return to Kernel-Mode Development

Who is online

Users browsing this forum: No registered users and 4 guests