일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Kaggle
- MATLAB
- llm을 활용 단어장 앱 개발일지
- Stream
- Computer Architecture
- C++
- bloc
- system hacking
- BAEKJOON
- rao
- 파이토치 트랜스포머를 활용한 자연어 처리와 컴퓨터비전 심층학습
- Flutter
- 영상처리
- Dreamhack
- PCA
- study book
- MDP
- 백준
- Widget
- Got
- BOF
- FastAPI
- DART
- Algorithm
- BFS
- Image Processing
- ARM
- fastapi를 사용한 파이썬 웹 개발
- pytorch
- ML
- Today
- Total
Bull
[System Hacking] Return Address Overwrite 본문
Return Address Overwrite
Return Address Overwrite는 공격자가 프로그램의 실행 흐름을 조작하기 위해 사용하는 기법 중 하나이다.
이 기법은 주로 버퍼 오버플로우 취약점을 이용하여 실행된다.
버퍼 오버플로우란 프로그램이 데이터를 저장하기 위해 할당받은 메모리 영역(버퍼)을 초과하여 데이터를 쓸 때 발생하는 보안 취약점을 말한다.
char buf[0x30];
scanf("%s", buf);
buf에 0x28만큼 스택에 할당되었다고 하자.
그런데 scanf는 크기를 얼마나 받을 지 정해놓지 않았기때문에 buf에 0x30보다 많이 넣으면 오버플로우가 일어난다.
이렇게 인덱스의 값이 배열의 크기보다 커지는 현상을 Index Out Of Bound (OOB)라고 하며 OOB취약점이라고 부른다.
$ ./rao
Input: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[1] 1828520 segmentation fault (core dumped) ./rao
만약 이렇게 실행을 한 후 버퍼오버 플로우를 발생시키면,
Segmentation fault라는 에러가 출력되며, 프로그램이 비정상적으로 종료된다.
이는 프로그램이 잘못된 메모리 주소에 접근했다는 의미이며, 프로그램에 버그가 발생했다는 신호이다.
(core dumped)는 코어파일(core)을 생성했다는 뜻이다.
여기서 코어파일이 생기지 않으면 다음 링크를 통해 해결할 수 있다.
https://codcost.tistory.com/47
리눅스 core파일 생성 안될 때
잘 알려진 방법인 ulimit -c unlimited 로 해결되지 않을 때, echo "core.%e.%p" > /proc/sys/kernel/core_pattern ulimit -c unlimited 를 순서대로 해주면 된다. 출처 https://dreamhack.io/forum/qna/1740
codcost.tistory.com
Ubuntu 20.04 버전 이상은 /var/lib/apport/coredump에 저장된다.
gdb rao -c core.1828876
코어 파일은 gdb를 통해 분석할 수 있다.
분석 과정은 생략하고 이론적 배경만 적어보겠다.
다음과 같이 SFP에 스택 프레임 주소가 들어간다.
즉 scanf를 실행한 후에 SFP에 원래 주소를 저장하고 있다가 buf를 채우면 SFP에 있던 주소로 다시 돌아가야 하는데 이 주소를 변형시킬 수 있는 것이다.
아래는 기본 x86-64: SYSV의 호출 규약이다.
──────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────
0x555555555178 <callee+79> add rax, rdx
0x55555555517b <callee+82> mov qword ptr [rbp - 8], rax
0x55555555517f <callee+86> mov rax, qword ptr [rbp - 8]
0x555555555183 <callee+90> pop rbp
► 0x555555555184 <callee+91> ret <0x5555555551bc; caller+55>
↓
즉, rbp는 SFP라 생각하고 ret되는 부분에 반환되는 함수 주소를 조작할 수 있는 것이다.
만약에 get_shell()이라는 함수로 쉘을 획득할 수 있다고 치자.
void get_shell(){
char *cmd = "/bin/sh";
char *args[] = {cmd, NULL};
execve(cmd, args, NULL);
}
pwndbg> print get_shell
$1 = {<text variable, no debug info>} 0x4006aa <get_shell>
그리고 gdb를 통해 get_shell을 주소를 알아냈다.
그러면 이제 buf의 값을 다음과 같이 채워주면 scanf()가 종료되면서 ret 되는 주소를 다음과 같이 바꿀 수 있다.
페이로드는 이렇게 작성할 수 있다.
b'A'*0x30 + b'A'*0x8 + b'\xaa\x06\x40\x00\x00\x00\x00\x00'
참고자료
[DreamHack 강의]
[출처]: https://dreamhack.io/lecture/courses/58
'Computer Science > System Hacking' 카테고리의 다른 글
[System Hacking] PLT & GOT (0) | 2024.04.10 |
---|---|
[System Hacking] NX & ASLR (0) | 2024.04.09 |
[System Hacking] Stack Canary (0) | 2024.04.06 |
[System Hacking] Shell Code 및 syscall (2) | 2024.03.31 |
[pwntools] 함수 및 모듈 정리 (0) | 2023.09.27 |