Intel's CET Shadow Stack issue
Intel's CET Shadow Stack issue
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?
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?
Re: Intel's CET Shadow Stack issue
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
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
Re: Intel's CET Shadow Stack issue
Currently, only critical processes seem to be activated.
But some svchost are activated and others are disabled.

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.
But some svchost are activated and others are disabled.
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.
Re: Intel's CET Shadow Stack issue
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.
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.
Re: Intel's CET Shadow Stack issue
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 madExceptIt's not an easy fix, though.

--Iconic
Re: Intel's CET Shadow Stack issue
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.
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.
Re: Intel's CET Shadow Stack issue
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
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
Re: Intel's CET Shadow Stack issue
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
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
Re: Intel's CET Shadow Stack issue
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.
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.
Re: Intel's CET Shadow Stack issue
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
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
Re: Intel's CET Shadow Stack issue
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... 

Re: Intel's CET Shadow Stack issue
Absolutely, let's wait and see what is considered a "violation" via CET terms, in the meanwhile I'll also be "cautiously" optimistic
--Iconic

Yes, very.it still needs carefully written assembler stubs
--Iconic
Re: Intel's CET Shadow Stack issue
https://techcommunity.microsoft.com/t5/ ... -p/1247815madshi 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?
Re: Intel's CET Shadow Stack issue
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).
Re: Intel's CET Shadow Stack issue
Yes, I think only RET.
Windows seems to support Shadow Stack, not Indirect Branch Tracking of CET.
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