我一直在尝试理解由GCC生成的汇编语言代码,并经常在许多函数开始时遇到此指令,包括_start()
,但找不到任何说明其用途的指南:
31-0000000000001040 <_start>:
32: 1040: f3 0f 1e fa endbr64
33- 1044: 31 ed xor ebp,ebp
发布于 2021-09-17 15:49:25
endbr64
(和endbr32
)是Intel's (CET)的一部分(另请参阅Intel Software Developer Manual, Volume 1, Chapter 18)。
英特尔CET提供针对Return-oriented Programming (ROP)和Jump/Call-oriented Programming (JOP/COP)攻击的硬件保护,这些攻击会操纵控制流,以便出于恶意目的重新使用现有代码。
它的两个主要特性是
endbr64
是其中的一部分。虽然CET在当前一代处理器中正在慢慢变得可用,但它是默认插入endbrXX
指令的already supported as of GCC 8。操作码在较旧的处理器上被选择为无操作,因此如果不支持CET,则忽略该指令;在支持CET的处理器上也会发生同样的情况,其中禁用了间接分支跟踪。
那么endbr64
做了什么呢?
Preconditions:
必须通过将控制寄存器标志CR4.CET
设置为1来启用
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
现在让我们简要地看一下两个场景。
无攻击:
some_function
从下一条指令中检索虚拟方法(TRACKER = WAIT_FOR_ENDBRANCH
).check_login
的地址并调用它。virtual method table vtable
由于这是一个间接调用,状态机被激活,并设置为在下一条指令时触发,下一条指令为endbr64
,因此间接调用被认为是“安全的”,并继续执行( endbr64
仍表现为无操作)。状态机被重置为(TRACKER = IDLE
).
攻击:
攻击者以某种方式操纵了vtable
,使vtable+8
现在指向authenticated
。
some_function
从虚拟方法表(TRACKER = WAIT_FOR_ENDBRANCH
).authenticated
中检索vtable
的地址并调用它。mov byte [is_admin], 1
,而不是预期的endbr64
指令。CET状态机推断控制流被操纵并引发#CP
错误,从而终止程序。如果没有CET,控制流操作将不会被注意到,并且攻击者将获得管理员权限。
总之,英特尔CET的间接分支跟踪功能确保间接调用和跳转只能重定向到以endbr64
指令开头的函数。
请注意,这并不能确保调用正确的函数-如果攻击者更改控制流以跳转到也以endbr64
开头的不同函数,状态机将不会抱怨并继续执行程序。然而,这仍然极大地减少了攻击面,因为大多数JOP/COP攻击的目标是中间功能的指令(甚至是向右跳到指令中)。
发布于 2019-07-06 08:44:56
它代表"End Branch 64 bit“--或者更准确地说,以64位终止间接分支。
下面是操作:
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和call指令。当看到其中一条指令时,状态机将从IDLE状态转移到WAIT_FOR_ENDBRANCH状态。在WAIT_FOR_ENDBRANCH状态下,程序流中的下一条指令必须是ENDBRANCH.如果看不到ENDBRANCH,处理器将导致控制保护异常(#CP),否则状态机将返回IDLE状态。
https://stackoverflow.com/questions/56905811
复制相似问题