65

我一直在尝试理解 GCC 生成的汇编语言代码,并且经常在许多函数的开头遇到此指令,包括_start(),但找不到任何解释其目的的指南:

31-0000000000001040 <_start>:
32:    1040:    f3 0f 1e fa             endbr64 
33-    1044:    31 ed                   xor    ebp,ebp
4

2 回答 2

63

它代表“End Branch 64 bit”——或者更准确地说,是 Terminate Indirect Branch in 64 bit。

这是操作:

IF EndbranchEnabled(CPL) & EFER.LMA = 1 & CS.L = 1
  IF CPL = 3
  THEN
    IA32_U_CET.TRACKER = IDLE
    IA32_U_CET.SUPPRESS = 0
  ELSE
    IA32_S_CET.TRACKER = IDLE
    IA32_S_CET.SUPPRESS = 0
  FI
FI;

否则,该指令被视为NOP.

CET功能用于确保您的间接分支实际转到有效位置。这允许额外的安全性。这是英特尔关于它的段落:

ENDBRANCH(详见第 73 节)是一条新指令,用于标记程序中间接调用和跳转的有效跳转目标地址。该指令操作码被选择为旧机器上的 NOP,这样使用 ENDBRANCH 新指令编译的程序在没有 CET 强制的情况下继续在旧机器上运行。在支持 CET 的处理器上,ENDBRANCH 仍然是 NOP,主要用作处理器流水线的标记指令以检测控制流违规。CPU 实现了一个跟踪间接 jmp 和调用指令的状态机。当看到这些指令之一时,状态机从 IDLE 移动到 WAIT_FOR_ENDBRANCH 状态。在 WAIT_FOR_ENDBRANCH 状态下,程序流中的下一条指令必须是 ENDBRANCH。

于 2019-07-06T00:44:55.533 回答
15

endbr64(和endbr32) 是英特尔控制流强制技术(CET)的一部分(另请参阅英特尔软件开发人员手册,第 1 卷,第 18 章)。

英特尔 CET 提供针对返回导向编程 (ROP)跳转/面向调用编程 (JOP/COP)攻击的硬件保护,这些攻击操纵控制流以将现有代码重新用于恶意目的。

它的两大特点是

  • 用于跟踪返回地址的影子堆栈和
  • 间接分支跟踪,这endbr64是其中的一部分。

虽然 CET 只是在当前的处理器中慢慢变得可用,但从 GCC 8 开始就已经支持它,默认情况下会插入endbrXX指令。操作码被选择为旧处理器上的无操作,这样如果不支持 CET,则忽略该指令;在禁用间接分支跟踪的支持 CET 的处理器上也会发生同样的情况。


那么做endbr64什么呢?

前提条件:

  • 必须通过将控制寄存器标志设置CR4.CET为 1 来启用 CET。
  • IA32_U_CET设置了(用户模式)或IA32_S_CET(管理员模式)MSR 中的间接分支跟踪的适当标志。

CPU 设置了一个小型状态机,用于跟踪最后一个分支的类型。举个例子:

some_function:
    mov rax, qword [vtable+8]
    call rax
    ...

check_login:
    endbr64
    ...
authenticated:
    mov byte [is_admin], 1
    ...
    ret

现在让我们简要地看一下两种情况。

无攻击:

  1. some_functioncheck_login虚拟方法表 中检索虚拟方法的地址vtable并调用它。
  2. 由于这是一个间接调用,因此 CET 状态机被激活并设置为在下一条指令 ( TRACKER = WAIT_FOR_ENDBRANCH) 上触发。
  3. 下一条指令是endbr64,因此间接调用被认为是“安全的”并继续执行(endbr64仍然表现为无操作)。状态机被重置 ( TRACKER = IDLE)。

攻击:
攻击者以某种方式设法操纵vtable现在vtable+8指向authenticated.

  1. some_functionauthenticated从虚拟方法表中检索地址vtable并调用它。
  2. 由于这是一个间接调用,因此 CET 状态机被激活并设置为在下一条指令 ( TRACKER = WAIT_FOR_ENDBRANCH) 上触发。
  3. 下一条指令是mov byte [is_admin], 1,而不是预期的endbr64指令。CET 状态机推断控制流被操纵并引发#CP故障,终止程序。

如果没有 CET,控制流操作将被忽视,攻击者将获得管理员权限。


总之,英特尔 CET 的间接分支跟踪功能确保间接调用和跳转只能重定向到以endbr64指令开头的函数。

请注意,这并不能确保调用了正确的函数——如果攻击者更改控制流以跳转到另一个同样开头的函数endbr64,状态机将不会抱怨并继续执行程序。然而,这仍然大大减少了攻击面,因为大多数 JOP/COP 攻击针对的是中间功能指令(甚至直接“跳转到”指令)。

于 2021-09-17T15:49:24.977 回答