CET

dandb3·2024년 6월 3일
0

pwnable

목록 보기
24/25

인텔의 CET(Control-flow Enforcement Technology)에 대해서 알아보자

CET는 CR4.CET 플래그가 1로 설정이 되어 있어야 enable 된다.
물론, 이 플래그는 ring 0에서만 설정할 수 있음.

1. endbr

개요

함수의 프롤로그 부분에 endbr64라는 명령어를 본 적이 있을 것이다. 이 명령어는 indirect branch tracking의 기능을 한다.

말 그대로 indirect하게 branch가 바뀌는 jmp, call과 같은 명령어가 실행될 때 그것을 tracking 한다는 뜻이다.

CPU 내부적으로 state machine을 통해서 관리한다.

ring 3의 경우 ‘IA32_U_CET ’, 나머지의 경우 ’IA32_S_CET‘ MSR의 플래그를 통해서 상태가 관리된다.

물론 CET 기능이 제공되지 않는 옛날 CPU라면 이 기능은 지원되지 않는다. endbr64 명령어도 그냥 nop으로 처리된다.

동작 원리

편의상 user mode에 대해서만 설명함.
평상시에는 IA32_U_CET.TRACKER = IDLE 상태로 존재한다.
그러다가 indirect branch tracking에 감지되면 해당 플래그는 WAIT_FOR_ENDBRANCH 상태로 바뀐다.

그 후 다음 명령어가 endbr64(혹은 32비트의 경우 32)가 나온다면 이를 올바른 명령어라고 확인한 후 플래그는 다시 IDLE로 바뀐다.

만약 endbr64가 아니라면, CPU는 #CP exception을 발생시킨다.

예시

예시를 통해 알아보자.

# case 1
call   QWORD PTR [r15+0x38]

# case 2
jmp    0x8338d

case 1의 경우, case 2와 다르게 메모리에 있는 값을 읽어온 후 그 다음에 읽어온 값으로 jmp를 하게된다. 그러므로 indirect branch에 해당한다.

대다수의 JOP, COP의 경우 함수 중간으로 코드를 건너뛰기 때문에 이에 대처할 수 있는 보호기법이다.

2. shadow stack

return address를 덮는 공격기법들을 막기 위해서 등장하였다.
기존 스택과 같이 존재하는 또 다른 스택이다.

함수 프롤로그에서 return address가 저장될 때 기존 스택과 shadow stack 둘 다 저장되게 된다.
그리고 나서 함수 에필로그에서 리턴할 때 shadow stack과 기존 스택의 값을 비교하는데, 만약 값이 다르면 return address가 오염된 것이므로 이 때 프로그램을 종료시키는 등의 동작을 하게 된다.

대신, 기존 스택에 저장되는 지역변수, 매개변수나 다른 정보들은 shadow stack에 저장되지 않는다.

소프트웨어적으로 구현 / 하드웨어적으로 구현 둘 다 가능하다.

멀티스레드의 경우 각각의 stack 당 하나의 shadow stack을 가지게 된다.

dockerfile에서 shadow stack 설정하기

ENV GLIBC_TUNABLES glibc.cpu.hwcaps=SHSTK

요런 식으로 설정해 줄 수 있다.

profile
공부 내용 저장소

0개의 댓글