0

So i was recently trying to exploit a kernel mode driver (HEVD) and I encountered a problem which doesn't make sense to me. After i jumped to my shellcode (which resides in usermode and was made executable by VirtualProtect), the thread keeps generating a pagefault. Then the Thread keeps generating this pagefault in an endless loop (it doesn't throw an exception).

So i investegated what kind of page fault was triggered and i got the following output for the pagefault-handler:

Breakpoint 0 hit
nt!KiPageFault+0x8:
fffff806`7d201d08 488dac2480000000 lea     rbp,[rsp+80h]
0: kd> dd %rsp + 0x158
ffff9307`717e9768  51dce820 ffffad82 00000011 00000000
ffff9307`717e9778  ee49cf8e 000001a4 00000010 00000000
ffff9307`717e9788  00010206 00000000 717e97a0 ffff9307
ffff9307`717e9798  00000018 00000000 00000003 00000000
ffff9307`717e97a8  c00000bb 00000000 0000004d 00000000
ffff9307`717e97b8  00000018 00000000 00000003 00000000
ffff9307`717e97c8  7a0e643b fffff806 00000000 00000000
ffff9307`717e97d8  55555555 55555555 7a0e8b10 fffff806

Here we see the stack after the page fault occured. The Breakpoint is triggered immediatly after i resume the execution (and yes, the breakpoint is conditional for only this thread). The frame is exactly the same every time the breakpoint was triggered. So I tried to decode the stackframe. A pagefault pushes some infomation on the stack. I decoded it manually (I don't know a better way to do this) and I got that the following:

RFLAGS  10206
CS      10
RIP     000001a4ee49cf8e
Errcode 11 --> P, I bits set
CR2     000001a4ee49cf8e

This should be right decoded (maybe it's erroneous. The top of the stack was ffff9307`717e9770, so the 0x...11 was the last thing pushed onto the stack). So the errocodes says that the exception is thrown while the page was present and it was during an instruction fetch.

Now: I think this should mean a access violation because of the NX-Bit. But this cannot be because the address is executable, as this snippet shows:

                                           VA 000001a4ee49cf8e
PXE at FFFFA8D46A351018    PPE at FFFFA8D46A203498    PDE at FFFFA8D440693B90    PTE at 
FFFFA880D27724E0
contains 8A00000027704867  contains 0A0000010DA05867  contains 0A0000010F9BE867  contains 
0100000119B6C825
pfn 27704     ---DA--UW-V  pfn 10da05    ---DA--UWEV  pfn 10f9be    ---DA--UWEV  pfn 119b6c    ----A-
UREV

The executable bit is set for the pte. So I asked myself why this happens. It's a bit weird also that it doesn't throw a access-violation and create a bugcheck.

Also the OS runs on virtualbox. I looked up the settings and I noticed that SMEP and SMAP aren't supported by my virtual machine (but by my host system. VirtualBox catches cpuid-Instructions and pretends that this feature is disabled). So this shoudn't be the problem either. Also if you dump the register, the SMEP/SMAP bits in CR4 are not set.

I have really no clue what could be the cause of this problem. Maybe it's because of the virtual machine. It could also be because Windows gets confused when a thread runs userocde or something else. I really thought a long time about it but maybe I just overlookeda a simple reason.

Thanks in advance

Trac3r
  • 25
  • 5
  • Hmm yeah... your stack decoding looks right and your analysis of the possible root causes too. While reading I thought it was 1) a thread context problem 2) an IRQL level problem 3) really a SMEP problem, but your analysis seems to indicate that it is not any of those... Have your tried to flip the U/S bit of the PTE, just to see if it executes or not? (this should normally require a TLB invalidation, but that should work after multiple tries). – Neitsa Feb 25 '21 at 15:59
  • well yes now it doesn't loop forever but instead bugchecks because of kernel corruption, but this has another cause – Trac3r Mar 02 '21 at 13:05

0 Answers0