일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 시그널
- 리눅스
- kernel
- 컴퓨터구조
- 시스템 프로그래밍
- 리버싱
- px4
- pwn.college
- 워게임
- Leviathan
- 프로그래밍
- C++
- 취약점
- css
- radare2
- 시스템
- 알고리즘
- Bandit
- 시스템프로그래밍
- 드론
- C언어
- pwncollege
- 커널
- wargame
- Pwnable.kr
- 리눅스 커널
- 어셈블리어
- write up
- 리눅스커널
- 시스템해킹
- Today
- Total
Computer Security
#16 cr4 overwrite 기법 본문
cr4 overwrite 기법
kernel ROP 에서 파생된 기법으로, cr4 레지스터의 SMEP 제어 비트를 제거해서 SMEP 보호 기법을 비활성화 하는 기법이다.
BOF 상황에서 overflow 할 수 있는 크기가 작거나, 마땅한 ROP 가젯을 찾기 어려울 때 시도해볼만한 기법이다.
제한적인 상황에서 SMAP 제어 비트를 제거하여 SMAP도 우회가 가능하다.
cr4 레지스터
- control 레지스터 중 하나로, 프로세서에서 지원하는 다양한 기능에 대한 제어를 담당하는 레지스터이다.
- 20번째 SMEP 제어 비트가 있으며, 이 비트를 제거할 경우 SMEP를 비활성화 할 수 있다.
우리는 아래의 파일들로 실습 할 것이다.
start.sh : qemu script
test.c : 간단한 취약점이 터지는 디바이스 드라이버 예제
cr4_check.c : 커널 패닉을 일으켜 cr4 레지스터의 값을 확인하는 code
exp.c : cr4 overwrite 기법을 이용해 권한 상승을 일으키는 exploit code
1. start.sh 를 살펴보자.
KASLR : 적용 X
SMEP : 적용 O
SMAP : 적용 X
2.BOF 취약점을 이용해 커널의 흐름을 원하는 대로 조작할 수 있는 디바이스 드라이버 예제인 test.c를 살펴보자.
test_write()함수
copy_from_user 함수를 이용해 유저로부터 원하는 크기의 데이터를 전달 받은 뒤, 지역변수 arr에 복사하는 역할을 한다.
이로인해 BOF 취약점이 터지게된다.
kbuild 옵션을 통해 SSP(canary) 보호 기법을 제외한 뒤 컴파일 한 예제 드라이버다.
3. cr4_check.c 를 살펴보자.
커널 패닉을 일으켜 cr4 레지스터의 값을 확인하는 코드이다.
write()를 이용해 test 드라이버에 dummy 값 40바이트를 전달한다.
커널 스택의 return address 부분을 dummy 값이 덮게 되고, 커널 패닉이 발생하게된다.
4. ./start.sh 로 qemu를 실행한후, cr4_cehck를 실행해보자.
RIP가 0x414141...로 변조되어 kernel panic이 발생하고, 패닉 로그에서 cr4레지스터의 값을 알 수 있다.
cr4레지스터의 초기값은 0x1006f0 이다.
5.exp.c 의 main()함수 부분
1. /dev/test 장치를 open() 한다.
2. 현재의 context를 저장하는 backup_rv() 함수를 호출한다.
3. cr4 레지스터를 덮어쓰는 가젯과 ret2usr기법으로 작성한 payload()함수의 주소를 이용해서 ROP payload를 작성한다.
4. write()함수를 이용해서 test 드라이버에 ROP payload를 전달한다.
SMEP가 걸려있음에도 불구하고 ret2usr를 사용할 수 있는 이유는 cr4 레지스터의 SMEP제어비트를 제거 해서 SMEP를 비활성화 했기 때문이다.
6. payload 부분을 분석해 보자.
AAAAAAAA... |
pop rax; ret; |
0x6f0 |
mov cr4, rax; ret; |
payload() |
1. dummy (AAAAAAAAAA...)
- BOF 가 터지는 상황에서 커널 스택의 return address 부분에 payload를 맞추기 위해 dummy값을 삽입한다.
- "A"의 개수는 총 32개. 즉 dummy 값은 32byte이다.
2. cr4 overwrite [ pop rax; ret; , 0x6f0 , mov cr4,rax; ret; ]
- cr4 레지스터를 SMEP 제어 비트를 제거한 값으로 덮는 부분이다.
- pop rax; ret; 어셈블리는 rax에 0x6f0을 넣기 위한 가젯이다.
- 0x6f0은 초기의 cr4 레지스터 값인 0x1006f0에 SMEP 제어 비트를 제거한 값이다.
- mov cr4, rax; ret; 어셈블리는 cr4 레지스터를 0x6f0으로 덮기 위한 가젯이다.
3. payload()
- ret2usr 기법으로 작성한 payload 함수를 호출한다.
- payload() 함수는 commit_creds(pre... -> swapgs -> context준비 -> iretq 순서로 구성되어 있다.
7. ./start.sh 를 실행해보자.
start.sh를 실행한 후, exp를 실행한 결과이다.
user권한에서 root권한을 획득 한 것을 볼 수 있다.
전체적인 흐름
커널공간 : test.c , 유저공간 : exp.c
커널 공간 misc_register(&test_driver) --> 유저공간 fd=open("/dev/test", O_RDWR)
--> 유저공간 write(fd, rop, sizeof(rop)) --> 커널공간 test_write()
--> 커널공간 copy_from_user(ptr, buf, count) --> 커널공간 memcpy(arr, ptr, count)
cr4 overwrite 최종 정리
이 기법은 kernel ROP와 같이 SMEP를 우회하는 기법이며, 제한적인 상황에서 21번째의 SMAP 제어 비트를 제거하여 SMAP도 우회가 가능하다.
커널 취약점을 이용해 rip control이 가능할 때, ROP payload를 구성한 뒤 해당 ROP payload로 rip를 제거하면 권한 상승이 가능하다.
만약 BOF와 같이 payload를 삽입한 후 rsp가 자동으로 맞춰지는 상황이 아닌, 단순히 rip control만 가능한 상황에서는 kernel stack pivotin 기법을 추가해야 한다.
'리눅스 커널 해킹' 카테고리의 다른 글
#18 struct cred overwrite 기법 (2) | 2022.08.26 |
---|---|
#17 kernel stack pivoting 기법 (0) | 2022.08.25 |
#15 kernel ROP 기법 (0) | 2022.08.23 |
#14 ret2usr 기법 (0) | 2022.08.22 |
#13 KPTI 우회 (0) | 2022.08.21 |