endbr64指令(x64)

Last Updated: 2023-03-31 09:45:38 Friday

-- TOC --

CFI:Control Flow Integrity

计算机经常受到旨在控制软件行为的外部攻击,攻击者利用软件漏洞,可以破坏程序的执行,并获得对软件行为的控制。

在二进制安全中,大部分的漏洞利用方式是劫持控制流,劫持后,使程序按照攻击者的攻击思路运行下去。控制流劫持是一种危害性极大的攻击方式,攻击者能够通过它来获取目标机器的控制权,甚至进行提权操作,对目标机器进行全面控制。当攻击者掌握了被攻击程序的内存错误漏洞后,一般会考虑发起控制流劫持攻击。

早期的攻击通常采用代码注入的方式,通过上载一段代码,将控制转向这段代码执行。例如,应用程序中的缓冲区溢出可能导致对敏感系统函数的调用,可能是应用程序从未打算使用的函数。

通过栈溢出控制程序中某个函数的返回地址,然后在该地址上布置shellcode,将控制流劫持至shellcode。为了阻止此类攻击,在硬件的支持下,现代操作系统都增加了DEP(Data-Execution-Prevention)机制,通过限制内存页不能同时具备执行权限和写权限,即隔离数据与代码来阻止程序运行攻击者的恶意数据。

what is shellcode?

Shellcode is a small piece of code that is typically used in the exploitation of software vulnerabilities. It is usually written in assembly language and designed to be executed directly by a computer's processor. The purpose of shellcode is to give an attacker remote access to a target system so they can execute arbitrary commands, download and install malware or steal sensitive data. Shellcode is often injected into a target system through a buffer overflow or other vulnerability in order to bypass application security measures such as firewalls or antivirus software. Once executed, shellcode can have full control over the target system, making it a powerful tool for cybercriminals and hackers. (比如一段通过syscall启动bash的asm代码)

为了突破DEP的防御,攻击者又探索出了代码重用攻击方式,他们利用被攻击程序中的代码片段,进行拼接以形成攻击逻辑。代码重用攻击包括Return-to-libc、ROP(Return Oriented Programming)、JOP(Jump Oriented Programming)等。研究表明,当被攻击程序的代码量达到一定规模后,一般能够从被攻击程序中找到图灵完备的代码片段,绕过DEP保护,最后达到攻击者的目的。

what is ROP?

ROP, short for Return-Oriented Programming, is a technique used in computer security exploits to bypass the non-executable stack protection mechanisms by reusing short sequences of machine code called "gadgets" from within the existing program's code (known as the "rop chain") to perform arbitrary operations.

The basic idea behind ROP is to overwrite the return address of a function call with the address of a gadget, which then executes its own sequence of instructions before returning control back to the attacker's code. This allows an attacker to execute arbitrary code in the context of the exploited program, such as elevating privileges, executing a shell, or stealing data.

The effectiveness of ROP attacks depends on the ability to find suitable gadgets within the targeted program's code that can be chained together to achieve the desired result. As a result, modern systems employ various measures to prevent ROP attacks, such as Address Space Layout Randomization (ASLR), Control Flow Integrity (CFI), and Code Signing.

为了抵御控制流劫持攻击,Abadi等人于2005年提出了控制流完整性(Control Flow Integrity, CFI)的防御机制,是一种通过保证控制流的完整性来实现软件防篡改的方法(基于插桩技术)。其核心思想是限制程序运行中的控制转移,使之始终处于原有的控制流图所限定的范围内。它规定软件执行必须遵循提前确定的Control Flow Graph(CFG)路径。

endbr64/endbr32

该指令是Intel CET(Control flow Enforcement Technology)技术的一部分。

参考:https://www.intel.com/content/www/us/en/developer/articles/technical/technical-look-control-flow-enforcement-technology.html

Intel CET offers hardware protection against Return-oriented Programming (ROP) and Jump/Call-oriented Programming (JOP/COP) attacks, which manipulate control flow in order to re-use existing code for malicious purposes.

Its two major features are:

The opcode is chosen to be a NOP on older processors, such that the instruction is ignored if CET is not supported, the same happens on CET-capable processors where indirect branch tracking is disabled.

So what does endbr64 do?

Preconditions:

程序中的代码,有些入口有endbr64(库中的接口),有一些没有(用户自己编写的接口),这是怎么回事?动态使能CET?

The CPU sets up a small state machine which tracks the type of the last branch. Take the following example:

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

check_login:
    endbr64
    ...

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

没有攻击的正常情况:

  1. some_function retrieves the address of the virtual method check_login from the virtual method table vtable and calls it.
  2. Since this is an indirect call, the CET state machine is activated and set to trigger on the next instruction (TRACKER = WAIT_FOR_ENDBRANCH).
  3. The next instruction is endbr64, so the indirect call is considered "safe" and execution continues (the endbr64 still behaves as a no-op). The state machine is reset (TRACKER = IDLE).

有攻击时:

An attacker somehow managed to manipulate vtable such that vtable+8 now points to authenticated.

  1. some_function retrieves the address of authenticated from the virtual method table vtable and calls it.
  2. Since this is an indirect call, the CET state machine is activated and set to trigger on the next instruction (TRACKER = WAIT_FOR_ENDBRANCH).
  3. The next instruction is mov byte [is_admin], 1, not the expected endbr64 instruction. The CET state machine infers that control flow was manipulated and raises a #CP fault, terminating the program.

Without CET, the control flow manipulation would have gone unnoticed and the attacker would have obtained admin privileges.

In summary, the indirect branch tracking feature of Intel CET ensures that indirect calls and jumps can only redirect to functions which start with an endbr64 instruction.

下面是理解的关键:

Note that this does not ensure that the right function is called - if an attacker changes control flow to jump to a different function which starts with endbr64 as well, the state machine won't complain and keep executing the program. However, this still greatly reduces the attack surface, as most ROP/JOP/COP attacks target instructions mid-function (or even jump right "into" instructions).

how endbr64 works?

endbr64 is an x86-64 instruction that is used as part of Control Flow Enforcement Technology (CET), which is a security feature designed to mitigate certain types of attacks such as Return Oriented Programming (ROP) and Jump Oriented Programming (JOP).

The basic idea behind CET is to create shadow stacks that keep track of the call site addresses using a separate stack from the regular call stack. This can help detect when an attacker tries to redirect program execution by overwriting the return address on the regular call stack.

However, there is still a vulnerability in this approach: an attacker could potentially use gadgets that don't include a ret instruction at the end, preventing the shadow stack from being updated properly. In other words, an attacker could subvert the control-flow enforcement mechanism by using a gadget to jump directly to another gadget without actually returning to the original code.

This is where endbr64 comes in. It is used to mark the end of a branch instruction sequence (such as a jmp or call) and ensures that the shadow stack is updated even if the branch doesn't end with a ret. The endbr64 instruction is placed immediately after the branch instruction and signals to the processor that the branch has ended and that the shadow stack should be updated accordingly.

In summary, endbr64 is a security feature designed to complement Control Flow Enforcement Technology (CET) by ensuring that the shadow stack is correctly updated even in the presence of branches that do not end with a ret instruction. This helps to prevent attacks such as ROP and JOP that attempt to hijack program execution by manipulating the control flow of the program.

本文链接:https://cs.pynote.net/hd/asm/202302172/

-- EOF --

-- MORE --