Skip to content

AD2040: PeEnableArmBTI

Summary

Property Value
ID AD2040
Name PeEnableArmBTI
Category Security
Severity Warning
Applies to PE (Windows ARM64)

Description

ARM64 PE binaries should enable Branch Target Identification (BTI) to prevent arbitrary code execution from indirect branches.

How It Works

The rule checks for BTI enablement:

  1. BTI instructions at function entry points
  2. ARM64 PE header flags indicating BTI
  3. GNU property notes for BTI

Why This Matters

BTI ensures that indirect branches can only land on designated landing pads, preventing attackers from jumping to arbitrary code locations.

How BTI Works

Without BTI:
  BR X0  →  Can jump anywhere

With BTI:
  BR X0  →  Must land on BTI instruction
            Otherwise: fault

Valid landing pad:
  BTI C    ; Valid target for calls
  ...function code...

BTI Landing Pad Types

Instruction Valid For
BTI C Indirect calls (BLR)
BTI J Indirect jumps (BR)
BTI JC Both calls and jumps

Attack Mitigation

Attacker controls X0:
  BR X0  →  gadget at 0x12345678

With BTI:
  BR X0  →  0x12345678 doesn't start with BTI
         →  Hardware fault
         →  Attack blocked

Combined with PAC

Protection Attack Surface
BTI alone Forward-edge CFI
PAC alone Return address protection
BTI + PAC Comprehensive CFI

Performance Considerations

BTI has near-zero runtime overhead:

Metric Impact
Runtime overhead <0.5% typical
Code size increase ~1-2% (BTI landing pads)
Memory overhead None
Hardware support Required (ARMv8.5+)

Why overhead is negligible: - BTI instructions are essentially NOPs on the normal execution path - Hardware validation happens in parallel with instruction fetch - No additional memory accesses or branches

Combined PAC + BTI: - Enabling both together adds approximately 1-2% overhead - This is the recommended configuration for comprehensive protection - Use -mbranch-protection=standard for both

Resolution

Enable BTI for ARM64 Windows builds:

# Clang
clang --target=aarch64-pc-windows-msvc -mbranch-protection=bti program.c

# Combined PAC + BTI (recommended)
clang --target=aarch64-pc-windows-msvc -mbranch-protection=standard program.c

CMake Configuration

if(CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64")
    add_compile_options(-mbranch-protection=standard)
endif()