Intel's CET Shadow Stack issue

c++ / delphi package - dll injection and api hooking
jakeads
Posts: 6
Joined: Mon Mar 08, 2021 3:22 am

Intel's CET Shadow Stack issue

Post by jakeads »

In Windows 10 2004 (19041.622) on 11th Gen Intel CPU
When I call next hook inside my callback funtion in 64-bit native windows process (sc.exe, svchost.exe, ..),
the process crashed with C0000409 (Security check failure or Stack buffer overrun)

I verified it is Hardware-enforced Stack Protection.
https://techcommunity.microsoft.com/t5/ ... -p/2163340

If you hook a process with CET compatibility mode, the process will be terminated from kernel.
Is there any way to avoid this?
iconic
Site Admin
Posts: 1019
Joined: Wed Jun 08, 2005 5:08 am

Re: Intel's CET Shadow Stack issue

Post by iconic »

Hello,

We are recently aware of this issue and we are seeing what can possibly be done about it but as of this moment we do not have a workaround unfortunately. Does this only seem to happen in critical processes then? I imagine only those processes built with the CET linker setting?

--Iconic
jakeads
Posts: 6
Joined: Mon Mar 08, 2021 3:22 am

Re: Intel's CET Shadow Stack issue

Post by jakeads »

Currently, only critical processes seem to be activated.
But some svchost are activated and others are disabled.

Image

To enable shadow stack enforcement statically, you need to compile with linker setting(/CETCOMPAT).
Then IMAGE_DLLCHARACTERISTICS_EX_CET_COMPAT bit will be written to PE header (https://docs.microsoft.com/en-us/window ... cteristics)

Applications can also choose to dynamically enable shadow stack enforcement, by using the PROC_THREAD_ATTIBUTE_MITIGATION_POLICY attribute in CreateProcess. This allows programs with multiple executables with the same name to specify specific processes to enable enforcement.

Also there is SetProcessDynamicEnforcedCetCompatibleRanges API to set dynamic enforced CETCOMPAT ranges for the specified process from outside the target process.


I guess HSP checks on RET instruction.
As far as I remeber, x64 stack frame chain was broken inside callback function in older madCHook version.
Does current madCHook use RET to call next hook?
If then, is there any flag or method to hook without using RET (only JMP or something)?

Thanks.
madshi
Site Admin
Posts: 10434
Joined: Sun Mar 21, 2004 5:25 pm

Re: Intel's CET Shadow Stack issue

Post by madshi »

I will look into this very soon. It's not an easy fix, though. I'll have to rewrite some of the assembler stubs, which is tricky and time consuming. So it will take a couple of days.

The issue probably happens if the API you're hooking has a JMP or CALL instruction in the first 5 or 6 bytes of its API code. In that case madCodeHook currently uses a PUSH + RET logic in x64 in some situations in order to replace a relative JMP/CALL instruction (which can only go +/- 2GB far) with a true 64bit JMP/CALL.
iconic
Site Admin
Posts: 1019
Joined: Wed Jun 08, 2005 5:08 am

Re: Intel's CET Shadow Stack issue

Post by iconic »

It's not an easy fix, though.
I also don't think this will be a simple fix after reading more in-depth about CET. For example, I guess it's also watching context changes so (e.g: NtContinue) can't be adjusted, well then this would be a major issue when it came to setting a new EIP/RIP inside any exception handler. Also, CET checks not only for RET but also CALL, JMP and Indirect Branching, so it's going to be VERY difficult to make such adjustments to both MCH and madExcept :o

--Iconic
madshi
Site Admin
Posts: 10434
Joined: Sun Mar 21, 2004 5:25 pm

Re: Intel's CET Shadow Stack issue

Post by madshi »

What does it watch for JMP and CALL instructions?

I'm not too worried about exception handling. I don't recall madCodeHook using that. For madExcept, it doesn't matter all too much, because CET will likely not be enabled for processes which don't have the "CET compatible" flag set.
iconic
Site Admin
Posts: 1019
Joined: Wed Jun 08, 2005 5:08 am

Re: Intel's CET Shadow Stack issue

Post by iconic »

I'm not sure exactly what it monitors for the CALL and JMP instructions 100% however according to what OP linked us to here https://techcommunity.microsoft.com/t5/ ... -p/2163340
it validates a lot of things to prevent quite a lot of binary instruction manipulations, included but not limited to IP validation.

I don't think just fixing up stubs to not look like ROP will make it compatible. I'm also aware that 99% of madExcept users control their own binary compilation and distribution but some certainly will not like the idea of not using the /CETCOMPAT linker flag, and those that are using portion of madExcept inside an injected DLL (I know a couple customers that do this personally) are also injected into processes that they have no control over come compilation time. MCH is the larger issue here, of course. With Delphi and madExcept it shouldn't matter though like you said.

I was reading that AMD's Zen 3 architecture will also have support for this, I have a Ryzen 3950x but it's based on Zen 2 so I still can't confirm what works vs. what is a violation, sadly.

--Iconic
iconic
Site Admin
Posts: 1019
Joined: Wed Jun 08, 2005 5:08 am

Re: Intel's CET Shadow Stack issue

Post by iconic »

Here's additional information about CET from a Blackhat presentation that I read the other day, it's a bit dated but offers some information as well. Since then CET has imposed even more restrictions from the hardware-assisted level. https://i.blackhat.com/asia-19/Thu-Marc ... cement.pdf

P.S: I checked the MCH .pas unit (a lazy CTRL + F search for eip :=) and I do see EIP/RIP adjusted in small portions of an exception handler contained within, I think this will also be considered a violation, but guessing. Until we can personally test we won't know of course.

--Iconic
madshi
Site Admin
Posts: 10434
Joined: Sun Mar 21, 2004 5:25 pm

Re: Intel's CET Shadow Stack issue

Post by madshi »

I don't see anything about CALL and JMP instructions being watched in the first link. Yes, CALL instructions get special handling, but only for the purpose of "filling" the shadow stack, so that the RET return address can be verified successfully. Other than that, I don't see any special handling for CALL and JMP mentioned. Or did I miss something?

The link talks about "the call" failing, but they don't mean CALL but instead "the call to NtSetContext", where the "to NtSetContext" being implied.
iconic
Site Admin
Posts: 1019
Joined: Wed Jun 08, 2005 5:08 am

Re: Intel's CET Shadow Stack issue

Post by iconic »

Hopefully that article mostly pertains to the context of that one API but when the real stack and shadow are compared, but a CALL instruction automatically (behind the scenes) pushes the return address onto the stack for you before jumping to the target region, so if the 2 stacks are compared fully, depending on what all of MCH does, it might have an issue. I know that it's used absolute jmp's in the past <0x25FF absolute address>, jmp rel (0xE9) target, some push/ret (0x68 <address> 0xC3) etc. but also I'd have to revisit what your old MIXTURE_MODE did (I think it was helpful for Winsock hooking issues).

Maybe it's me who is overthinking things, sure would like to be able to test directly instead of reading multiple documents. But, you may in fact be right and only need to address a couple things and not several. Check the Blackhat link for a lot more of the technical details, the first link doesn't have all of them.

We'll just have to test all areas where binary code is altered to see if they're a violation, in a nutshell.

--Iconic
madshi
Site Admin
Posts: 10434
Joined: Sun Mar 21, 2004 5:25 pm

Re: Intel's CET Shadow Stack issue

Post by madshi »

I'm carefully optimistic that "simply" replacing PUSH+RET with a JMP should do the trick. But let's wait and say. And even if it's true, it still needs carefully written assembler stubs... :?
iconic
Site Admin
Posts: 1019
Joined: Wed Jun 08, 2005 5:08 am

Re: Intel's CET Shadow Stack issue

Post by iconic »

Absolutely, let's wait and see what is considered a "violation" via CET terms, in the meanwhile I'll also be "cautiously" optimistic :D
it still needs carefully written assembler stubs
Yes, very.

--Iconic
jakeads
Posts: 6
Joined: Mon Mar 08, 2021 3:22 am

Re: Intel's CET Shadow Stack issue

Post by jakeads »

madshi wrote: Tue Mar 09, 2021 10:11 pm I don't see anything about CALL and JMP instructions being watched in the first link. Yes, CALL instructions get special handling, but only for the purpose of "filling" the shadow stack, so that the RET return address can be verified successfully. Other than that, I don't see any special handling for CALL and JMP mentioned. Or did I miss something?
https://techcommunity.microsoft.com/t5/ ... -p/1247815
madshi
Site Admin
Posts: 10434
Joined: Sun Mar 21, 2004 5:25 pm

Re: Intel's CET Shadow Stack issue

Post by madshi »

Yet again, I don't see anything in that link pointing to using CALL and JMP instructions being watched (other than watching CALLs to fill the shadow stack). The only thing that is no longer "allowed" seems to be the use of PUSH+RET (and similar tricky ways of using RET).
jakeads
Posts: 6
Joined: Mon Mar 08, 2021 3:22 am

Re: Intel's CET Shadow Stack issue

Post by jakeads »

Yes, I think only RET.
Windows seems to support Shadow Stack, not Indirect Branch Tracking of CET.
Control-flow Enforcement Technology (CET) provides the following capabilities to defend against ROP/JOP
style control-flow subversion attacks:
 Shadow Stack – return address protection to defend against Return Oriented Programming,
 Indirect branch tracking – free branch protection to defend against Jump/Call Oriented Programming.

https://software.intel.com/sites/defaul ... review.pdf
Post Reply