- 한정된 메모리 안에서 stack 영역이 너무 많이 확장돼서 발생하는 버그
- Stack에 위치한 버퍼에 버퍼의 크기보다 많은 데이터가 입력되어 발생하는 버그
- 100ml 컵에 200ml 물을 받으면 넘치는 것과 같은 원리
- buffer 뒤에 데이터를 덮어 씌워서 중요한 데이터 변조가능
<example> 1. "https://twitter.com" > overflow => "https://example.evi" / 통신 조작 가능 2. 악성 데이터 감지 경고 프로그램 조건 변경 가능
2.1. Buffer?
- Buffer란 데이터가 목적지로 이동되기 전에 보관되는 임시 저장소
- 처리 속도가 다른 두 장치의 완충 작용을 함
<example> 데이터 입력 속도보다 데이터 처리 속도가 느린 프로그램이 있다고 가정하면 'abcdef' 입력 시 'adf'만 전달된다. 이를 해결하고자 Buffer라는 임시 저장소를 두고 간접적으로 데이터를 전달하게 하는 것이다.
- 실습자료(dreamhack)
//dreamhack 실습 자료 // 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)); //=> overflow 발생 지점 if(!strcmp(temp, "SECRET_PASSWORD")) 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"); }
- check_auth 함수에서 strncpy 함수를 통해 temp버퍼를 복사할때, 16byte가 아닌 인자로 전달된 password의 크기만큼 복사함 -> 오버플로우 발생
- main함수에 bp 걸고 실행
- check_auth에 bp걸고 step into
- temp = rdi = 0x7fffffffe020 = rbp-0x20
- temp의 버퍼는 구했으니 auth 변수 주소만 알면 된다
- eax에 rbp-4 넣어서 return 함,
- auth = rbp-4 = 0x7fffffffe03c
- 0x7fffffffe03c - 0x7fffffffe020 = 0x1c(28)
- 10진수로 29개만큼 채워넣으면 overflow가 된다!
### 성공!
실습자료(dreamhack) // 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); // => overflow 발생 지점 printf("Your name is %s.", name); }
- name에 설정된 버퍼는 8byte인데 read() 함수에서 12byte만큼 읽어옴 -> barrier라는 4byte null 배열을 덮어쓰면 secret 값을 읽어올 수 있음
* main 함수에 bp걸고 실행
- read buffer address = 0x7fffffffe024
- 0x7fffffffe024 ~ 0x7fffffffe030 - 1(e02f) 까지 덮으면 null byte없이 읽어들일 수 있음 -> 총 12byte
- 성공!!