# 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"

### 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