# Practical Binary Hardening with Control-flow Enforcement Technology - CET internals - ... ### Intel Control-flow Enforcement Technology - Hardware-based mitigation against control flow hjacking attack - CET = Shadow Stack + Indirect Branch Trecking (IBT) - Violations -> Control Protection fault (#CP) ### Why? - Static analysis alone cannot enforce caller-callee return pairing at runtime - CET provides hardware shadow stack + IBT with near-zero overhead - branch checking - ignore instructon after ret/call ### CET : The Concept - Shadow Stack - Protected copy of return addr checked by hardware - Saves return addresses whe `call` - Validates it with the one in shadow stack when `ret` - Indirect Branch Tracking ### CET Invariants - Shadow Stack - on every `ret`, check `RSP`(actia; ret) = `SSP` (shadow ret addr) - Indirect Branch Tracking - on every indirect `call/jmp` - forward-edge defense : indirect `call/jmp` target validation ### CET supports windows: user+kernel linux: only kernl ### What Does CET Assume? - W ^ X is intact no writable + executable pages - Shadow stack is HW-protected oordinary stores can't write it - OS has enabled CET CR4.CET + per-mode MSRs set ## IBT ### Implementation - A `0x3E` "notrack" ![](https://s.secrss.com/anquanneican/bf5551e17832090076d2b5dc51b904e3.jpg) ### ENDBR32 / ENDBR64 - `ENDBR{64,32}` : `F3 0F 1E {FA,FB}` - FA : 64 bits - FB : 32 bits - `F3 0F` = Multi-byte reserved NOP encoding - Old hardware w/o CET support -> no-op ### Edges - Backwared Edge : Return-Oriented Programming (ROP) - Attacker overwrites saved return address on the stack - Chains small gadgets ending in `ret` - Forwared Edge : JOP/COP - Attacker computes indirect jump/call targets (function pointers) ### Common gadget atttack #### ROP d #### JOP - JOP controls chains gadget w/ indirect branch, uses `jmp(reg)` insted of `ret` - dont reuse `ret` #### COP uses indirect call, insted of `ret/jmp` ### tl;dr - IBT -> prevent COP/JOP - Shadow Stack -> prevent ROP ### CVEs #### CVE-2025-32756 https://horizon3.ai/attack-research/attack-blogs/cve-2025-32756-low-rise-jeans-are-back-and-so-are-buffer-overflows/ - root cause: no bound check on b64(user_input) to a fixed stack ##### if CET enable - raise CP fault, attack will fails #### CVE-2025-0282 https://labs.watchtowr.com/exploitation-walkthrough-and-techniques-ivanti-connect-secure-rce-cve-2025-0282/ - attack path: fake `*this` pointer -> fake vtable redirect -> false deref -> stack pivot -> ROP -> RCE ### Exceptional Control Flow - There are legitimate cases when control flow a transferred to opaque continuation targets - Unwinding, `NtContinue`, `RtlRestoreContext` or `setjmp/longjmp` - APC delivery ## System Calls related talk: https://i.blackhat.com/asia-19/Thu-March-28/bh-asia-Sun-How-to-Survive-the-Hardware-Assisted-Control-Flow-Integrity-Enforcement.pdf ### NtContinue - Introduced `NtContinueEx` system call - Now `KCONTINUE_TYPE` = description ### KeVerifyContextXStateCetU - First validation routine for `NtContinue`, `NtSetContextThread`, ... ### K{e,i}VerifyContextIpForUserCet WHen context IP validation is enabled on a target process: - The kernel validates given RIP - The RIP must appear on the usr shadow stack - Reference EM Continuation / LongJump Table for a predefined setr tof staticcally known continuation targets - Relaxed behavior for backwards compatibility - If the executable does not have EH continuation table. ### EH Continuation Table - Linker : `/GUARD:EHCONT` - A data found in Load Config data directory in PE - `IMAGE_GUARD_EH_CONTINUATION_TABLE_PRESENT` bit set - `target_rva` = echo: valid continunation target >在結構化異常處理 (SEH) 異常回溯期間,使用 RtlRestoreContext 和 NtContinue 回溯到包含 __except 程式碼區塊的目標訊框。 __ __except 程式碼區塊的指令指標不應位於影子堆疊中,因為這會導致指令指標驗證失敗。編譯器開關 /guard:ehcont 會產生一個「EH 延續表」。此表包含二進位檔案中所有有效異常處理延續目標 NtContinue RVA 排序清單。 NtContinue 首先檢查影子堆疊中是否存在使用者提供的指令指針,如果未找到,則會檢查包含該指令指針的二進位檔案中的 EH 延續表 ref: https://learn.microsoft.com/en-us/cpp/build/reference/guard-enable-eh-continuation-metadata?view=msvc-170 ### LongJump Table - Linker : `/GUARD:LONGJMP` - a data found in Load Config data directory in PE - `IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT` bit set - An array of entries represented by `longjump_entry` - `target_rva` tells the kernel ... ### Unwinding `RtlVerifyUserUnwindTarget` ### JIT Code special handling for CET support ### Conclution Windows handle wirh set-context ip validation w/ CET ### CET Support on Windows JIT codes | Runtime | SHSTCK | | --------------- | ------ | | V8 | X | | SpiderMonkery | X | | JavaScriptCore | X | | .NET 9+ CoreCLR | V | | .NET native AOT | V | - only on .NET native & .NET 9+ core, impliment defaultly after .NET 9 ### Problem 1 : GC Return Addr Hijacking - GC needs to pause a managed thread - Overwrites a return addr on the real stack with a GC ... ### Solution 1 : User-Mode APC Suspension - GC Thread -> `QueueUserAPC2(SPECIAL_USER_APC)` -> Thread A -> APC fires at alartable point -> Cnters GC suspension #### 3 types of APCs - kernel mode APC -- kernel content - User Mode APC -- QueueUserAPC, running thread APCs - Special Kernel APC (aka Normal vs Special APC distinction) | Type | Runs In | Used By | Example | | ------------------ | ------- | ----------------- | ------------------------------------ | | Kernel-mode APC | Kernel | OS | I/O completion | | User-mode APC | User | Applications | `QueueUserAPC` | | Special Kernel APC | Kernel | OS (critical ops) | Thread termination, system internals | ### Prob 2. `RtlRestoreContex`: Restores the context of the caller to the specified context record. ### Sol 2. - CoreCLR does not call `SetProcessDynamicEHContinuationTargets` - CoreCLR is the runtime for .NET Core. It includes the garbage collector(GC), JIT compiler, primitive data types and low-level classes. ### Prob 3 native runtime component ### Sol 3 CET Binary Merkers ### Wrapup ### Key Takeaway - Broser engines still treat SHSTK + JIT renderer support as a hard integration area - Bypass `rtlrestorecontext` w/ clrRestoreNonVolatileContext ### Indirect Branch Tracking - CFG/XFG implements in software - CFG : Control Flow Guard 控制流防護 - 主要在間接調用(如 call 或 jmp 暫存器)前檢查目標地址有效性 - XFG : eXtended Flow Guard 擴展流防護 - 針對間接調用,檢查 Function Prototype Hash,防止惡意利用函數原型不同的間接跳轉 ## Undocumented CET Flags on Win!! - related issue :https://github.com/llvm/llvm-project/pull/150761 `/CETCOMPATSTRICT` - `KiFixupControlProtectionUserModeReturnMismatch` - Remove the compatibility behavior (AppCompat) `/cetipvalidationrelaxed[:no]` `/cetdynamicapisinproc[:no]` `/hotpatchcompatible[:no]` ### Singnal Handling with Shadow Stack ## linux Indirect Branch Tracking (IBT) When the Linux kernel supports CET/IBT, it will ensure that all indirect jump targets have `ENDBR` during compilation, booting and dynamic probe insertion, and prevent probes from destroying these protection instructions. ### CET limitation: deploy https://www.felixcloutier.com/x86/rstorssp