Stack Buffer Overflow
스택에 위치한 버퍼에 버퍼의 크기보다 많은 데이터가 입력되어 발생하는 버그
*stack overflow : 스택 영역이 너무 많이 확장되면서 발생하는 버그
Buffer (버퍼)
데이터가 목적지로 이동되기 전에 보관되는 임시 저장소
데이터가 처리되는 속도가 다른 두 장치 > 버퍼 : 완충작용을 해줌
- 버퍼가 가득 찰 때까지 유실되는 데이터 없이 통신 가능
- 속도가 다른 두 장치에서 안정적으로 목적지에 도돨하도록 함
→ 데이터가 저장될 수 있는 모든 단위를 의미
ex) 스택 지역 변수 : 스택 버퍼 / 힙 지역 변수 : 힙 버퍼
*버퍼링 : 송신 측의 전송 속도가 느림 → 수신 측의 버퍼가 채워질 때까지 대기
Buffer Overflow (버퍼 오버플로우)
버퍼가 넘치는 것을 의미함
발생 시 문제 : 뒤에 있는 버퍼의 값들이 조작될 수 있음
데이터 변조
// Name: sbof_auth.c
// Compile: gcc -o sbof_auth sbof_auth.c -fno-stack-protector
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//맞는지 확인하는 함수
int check_auth(char *password) {
int auth = 0;
char temp[16];
strncpy(temp, password, strlen(password));
//temp에 password를 복사
//password > 16 바이트 >> buffer overflow 발생
if(!strcmp(temp, "SECRET_PASSWORD")) //버퍼의 문자열과 "SECRET_PASSWORD" 비교
auth = 1; // 같으면 auth 1반환
return auth;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: ./sbof_auth ADMIN_PASSWORD\n");
exit(-1);
}
if (check_auth(argv[1]))
printf("Hello Admin!\n");
else
printf("Access Denied!\n");
}
> sbof_auth.c : 비밀번호를 확인하는 프로그램
check_auth 함수
- return : auth - password가 맞는다면 1, 아니면 0을 반환
- temp[16] : password를 저장하는 버퍼
코드 설명)
strncpy(temp, password, strlen(password));
> temp에 password의 값을 password의 길이만큼 복사함
> password의 길이가 temp의 크기인 16바이트보다 크더라도 전부 복사 : 스택 버퍼 오버플로우 발생
if(!strcmp(temp, "SECRET_PASSWORD"))
auth = 1;
> temp의 값이 "SECRET_PASSWORD"과 같으면 auth = 1 반환
main 함수
- check_auth의 반환값이 참(0을 제외한 모든 숫자)이면 비밀번호가 맞다고 판단함
[ Stack buffer overflow가 발생하는 경우 ]
: password가 전부 복사되어 auth의 스택 영역까지 침범하는 경우
<check_auth 함수의 stack 구조>
0x00 0x01 0x02 0x03 | 0x04 0x05 0x06 0x07 | 0x08 0x09 0x0a 0x0b | 0x0c 0x0d 0x0e 0x0f | 0x10 0x11 0x12 0x13 |
temp | temp | temp | temp | auth |
0 0 0 0 |
- temp와 auth는 연속된 스택에 저장되어 있음
- password가 16바이트보다 커서 auth에 침범 → auth는 0이 아님 > 참
데이터 유출(인포릭)
// Name: sbof_leak.c
// Compile: gcc -o sbof_leak sbof_leak.c -fno-stack-protector
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main(void) {
char secret[16] = "secret message";
char barrier[4] = {};
char name[8] = {};
memset(barrier, 0, 4);
printf("Your name: ");
read(0, name, 12);
printf("Your name is %s.", name);
}
> secret message를 숨기고 있는 프로그램
read(0, name, 12);
> 12바이트를 입력받아 name에 저장함
> name의 buffer크기는 8바이트 이므로 12바이트를 넘기면 stack buffer overflow가 발생
[ Stack buffer overflow가 발생 ]
: name 배열이 secret 배열을 덮어쓴다
< main 함수의 stack 구조 >
- name이 12바이트 이상 → Stack Buffer Overflow 발생
- name의 범위가 secret 까지 확장되어 덮어씌워짐
- name 출력 > secret 배열까지 name으로 인식되어 출력됨
실행 흐름 조작
RIP, EIP를 내가 원하는 가젯에 놓을 수 있는 것 *시스템해킹의 중요 목표
// Name: sbof_ret_overwrite.c
// Compile: gcc -o sbof_ret_overwrite sbof_ret_overwrite.c -fno-stack-protector
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char buf[8];
printf("Overwrite return address with 0x4141414141414141: ");
gets(buf);
return 0;
}
> return address 를 조작하여 실행 흐름을 조작
gets(buf)
> 사용자가 입력한 문자열 전부 입력받기
> 8바이트를 넘어가면 return address 에 도달 → stack buffer overflow 발생
[ Stack buffer overflow가 발생 ]
: return address에 원하는 값을 쓸 수 있음
reference
- Dreamhack SystemHacking > Memory Corruption : Stack Buffer Overflow
'Hacking > Pwnable' 카테고리의 다른 글
[Mitigation] NX (0) | 2024.08.25 |
---|---|
[Mitigation] Stack Canary (0) | 2024.08.24 |
gdb를 pwntools와 디버깅하기 (0) | 2024.07.26 |
[Exploit] ShellCode(2) - execve shell code (1) | 2024.01.27 |
[Exploit] ShellCode(1) - orw shell code (1) | 2024.01.26 |