A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about kernel-mode development.
 #30551  by 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.
 #30557  by 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.
 #30810  by 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.
 #30811  by 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?