일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 29 | 30 |
31 |
- BOF
- system hacking
- MDP
- Image Processing
- Computer Architecture
- 백준
- rao
- BAEKJOON
- llm을 활용 단어장 앱 개발일지
- Flutter
- 파이토치 트랜스포머를 활용한 자연어 처리와 컴퓨터비전 심층학습
- BFS
- MATLAB
- 영상처리
- Got
- C++
- ARM
- ML
- Stream
- Kaggle
- DART
- PCA
- Dreamhack
- bloc
- study book
- Widget
- fastapi를 사용한 파이썬 웹 개발
- FastAPI
- pytorch
- Algorithm
- Today
- Total
Bull
[System Hacking] Return To Library(RTL) with ROPgadget 본문
[System Hacking] Return To Library(RTL) with ROPgadget
Bull_ 2024. 4. 10. 17:07개념
Return To Library(RTL)는 NX를 우회하는 공격 기법으로 널리 알려져있다.
NX로 인해 공격자가 버퍼에 주입한 셸 코드를 실행하기는 어렵지만, 스택 버퍼 오버플로우 취약점으로 반환 주소를 덮는 것은 여전히 가능하다.
프로세스에 실행 권한이 있는 메모리 영역은 일반적으로 바이너리의 코드 영역과 바이너리가 참조하는 라이브러리의 코드 영역이다.
Return-to-Libc: 공격자는 특정 libc 함수의 주소를 리턴 주소로 설정합니다.
가장 일반적인 목표는 system 함수로의 실행 흐름을 변경하는 것이며, 이를 통해 임의의 시스템 명령을 실행할 수 있다.
예를 들어, 공격자는 system("/bin/sh") 호출을 통해 셸을 획득할 수 있다.
Dreamhack 실습코드
// Name: rtl.c
// Compile: gcc -o rtl rtl.c -fno-PIE -no-pie
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
const char* binsh = "/bin/sh";
int main() {
char buf[0x30];
setvbuf(stdin, 0, _IONBF, 0);
setvbuf(stdout, 0, _IONBF, 0);
// Add system function to plt's entry
system("echo 'system@plt'");
// Leak canary
printf("[1] Leak Canary\n");
printf("Buf: ");
read(0, buf, 0x100);
printf("Buf: %s\n", buf);
// Overwrite return address
printf("[2] Overwrite return address\n");
printf("Buf: ");
read(0, buf, 0x100);
return 0;
}
1. “/bin/sh”를 코드 섹션에 추가
const char* binsh = "/bin/sh";
문자열 "/bin/sh"를 프로그램의 코드 섹션에 저장한다.
ASLR이 적용되어도, PIE가 비활성화되어 있으면 프로그램의 코드 세그먼트와 데이터 세그먼트의 주소는 실행할 때마다 동일하게 유지된다.
"/bin/sh" 문자열의 메모리 주소가 고정되어 있음을 의미하며, 이 주소는 나중에 system 함수를 호출할 때 인자로 사용될 수 있다.
2. system 함수를 PLT에 추가
system("echo 'system@plt'");
이 코드는 system 함수를 호출함으로써 해당 함수의 주소를 Procedure Linkage Table(PLT)에 추가한다.
함수의 주소가 한 번 PLT에 추가되면, 해당 함수는 ASLR에 영향을 받지 않는 고정된 주소를 통해 호출할 수 있다.
이러한 방법은 Return to PLT 공격에 사용된다.
ROPgadget
리턴 가젯 찾는 방법
설치
$ python3 -m pip install ROPgadget --user
가젯 찾기
$ ROPgadget --binary ./rtl --re "pop rdi"
Gadgets information
============================================================
0x0000000000400853 : pop rdi ; ret
찾아야할 가젯
addr of ("pop rdi; ret") <= return address
addr of string "/bin/sh" <= ret + 0x8
addr of "system" plt <= ret + 0x10
system("bin/sh")를 실행하는 ROP gagdet이다.
가젯의 의미는 알겠는데 해당 흐름에 대해 이해가 가질 않았었다.
우선 GPT를 통해 내가 이해한 바를 표를 통해 정리하였다.
일단 "실행흐름", "SP(Stack Pointer)" 두 가지로 나눈 후 표를 보면 어느 정도 이해가 될 것이다.
순서 | 스택 포인터(SP) 위치 | 실행 중인 명령(실행 흐름) | 설명 |
1 | 스택에 데이터를 배치하기 전 | N/A | 공격자는 스택에 다음 데이터를 순서대로 배치: "pop rdi; ret" 가젯의 주소, /bin/sh의 주소, system 함수의 주소. |
2 | "pop rdi; ret" 가젯 주소 | 실행 흐름 변경 중 | 실행 흐름이 "pop rdi; ret" 가젯으로 이동한다. 이 시점에서 SP는 "pop rdi; ret" 가젯의 다음 위치인 /bin/sh의 주소를 가리킨다. |
3 | /bin/sh의 주소 | "pop rdi" 실행 | "pop rdi" 명령이 실행되어 SP가 가리키는 값(/bin/sh의 주소)을 rdi 레지스터로 로드한다. SP는 이제 system 함수의 주소를 가리킨다. |
4 | system 함수의 주소 | "ret" 실행 | "ret" 명령이 실행되어 SP가 가리키는 값(즉, system 함수의 주소)을 프로그램 카운터(PC)로 로드하고, 실행 흐름이 system 함수로 이동한다. |
5 | system 함수 실행 | system("/bin/sh") 호출 | rdi에 로드된 /bin/sh의 주소가 system 함수의 인자로 사용되어 쉘이 실행된다. |
정리하자면,
스택 포인터가 /bin/sh를 가리킬 때 pop rdi가 실행. 스택 포인터가 system을 가리킬 때 ret이 실행. |
그리니까, "addr of ("pop rdi; ret") <= return address"는 실행흐름이 변경된거고,
실행 흐름이 변경된 상태에서 그 아래에 "/bin/sh"와 "system()"은 스택에 해당 주소가 올라가게 되는 것이다.
위와 같은 방법을 통해 가젯으로 구성된 페이로드를 작성하고, 페이로드로 반환 주소를 덮으면 셸을 획득할 수 있다.
여기서 한가지 주의할 점은, system 함수로 rip가 이동할 때, 스택은 반드시 0x10단위로 정렬되어 있어야 한다.
system 함수 내부에 있는 movaps 명령어 때문인데,
이 명령어는 스택이 0x10단위로 정렬되어 있지 않으면 Segmentation Fault를 발생시킨다.
참고자료
[DreamHack 강의]
[출처]: https://dreamhack.io/lecture/courses/83
'Computer Science > System Hacking' 카테고리의 다른 글
[System Hacking] PLT & GOT 간단하게 이해하기 (0) | 2024.05.17 |
---|---|
[System Hacking] Format String Bug (FSB) (0) | 2024.04.18 |
[System Hacking] PLT & GOT (0) | 2024.04.10 |
[System Hacking] NX & ASLR (0) | 2024.04.09 |
[System Hacking] Stack Canary (0) | 2024.04.06 |