System crash modifying cr4 register

Good evening,

Recently I’ve been trying to modify the CR4 register to enable the 22’th bit (PKE, for Intel processors)
However upon enabling PKE and overwriting cr4 with the new value my system crashes with an exception (UNEXPECTED_KERNEL_MODE_TRAP)

Trying to clear the interrupt flag (_disable()) doesn’t seem to resolve the issue either, it generates a new IRQL issue.
There’s not much to be told from the crash dump but it can be found below as well as the code:

Code for modifying CR4 (Obviously works fine without enabling PKE)
auto cr4 = __readcr4(); cr4 |= 0x400000; __writecr4(cr4);

Crash dump in WinDbg:
https://hastebin.com/vifucusuxi.pl (To save space)

Did you really expect that to work? If the operating system didn’t turn it on, then I don’t see how you can. Had you already set up the PKRU register for the user space? If not, isn’t the system going to explode as soon as you switch back to user mode?

@Tim_Roberts said:
Did you really expect that to work? If the operating system didn’t turn it on, then I don’t see how you can. Had you already set up the PKRU register for the user space? If not, isn’t the system going to explode as soon as you switch back to user mode?

Not all intel processors support PKR which likely why it’s disabled by default, but no I haven’t set up the register (Mainly intended on modifying the bit inside the PTE for my pages specifically) but I could give that a go as well to verify.

which likely why it’s disabled by default

Hmmmm… I’m not an expert in this, but I tend to think it’s not enabled by default because it’s problematic (Google is your friend here); don’t you need more kernel-mode support than just banging the enable bit?

Peter

The research work all seems to be from Intel and Microsoft, but is also
linux only (libmpk). As Peter noted, you can’t just flip a bit.

Mark Roddy

Right. As soon as you turn on that bit and flip back to user-mode the processor is going to start enforcing the protection key rights. If you haven’t set them up, then all the rights are denied. The processor is blocked from going into user mode, and you get a fatal double-fault.

Put another way, it’s quite likely that this doesn’t do what you think it does.

I don’t think that I have ever heard of this before, but as I read up on this feature, I am struggling to find a valid use for it.

As I understand it, this allows UM threads to mask off a subset of their own access to certain address ranges. While a ‘cool I can do it all from UM’ feature, at best this is some kind of defense in depth technique. Because the protection for each thread is controlled via a register, any block of code can arbitrarily change it. So the only kind of malware that this can protect against is some that does not know of its existence (security by obscurity) and with only 16 tags available, all but the simplest programs will not be able to designate valid ‘now it is okay to write from this thread’ protocols