Stack Overflow vs Stack Buffer Overflow
자라나는 방향의 차이
Stack Overflow vs Stack Buffer Overflow
블로그 글 스타일을 변경하고 AI 생성 이미지를 실험적으로 도입중입니다. 관련 내용은 이전 글을 참조해주시면 감사합니다.
요약
| 스택 오버플로 | 스택 버퍼 오버플로 | |
|---|---|---|
| 무엇이 넘치나 | 스택 전체 | 스택 위의 배열 하나 |
| 넘치는 방향 | 아래 (낮은 주소) | 위 (높은 주소) |
| 원인 | 깊은 재귀, 큰 지역 변수 | 범위 밖 쓰기, 길이 미확인 복사 |
| 결과 | OS가 즉시 감지해 크래시 | 조용히 데이터 손상, 나중에 크래시 |
| 보안 문제 | 거의 없음 | 대표적인 취약점 |
방향
- 스택은 높은 주소 → 낮은 주소로 자람
- 배열 인덱스는 낮은 주소 → 높은 주소로 증가
- 이 방향 차이가 두 문제를 가르는 핵심
스택 오버플로
- 스택 전체가 최대 크기를 넘는 것
- 스택은 0번지까지가 아니라 정해진 한계까지만 자람
- 원인
- 너무 깊은 재귀
- 큰 지역 배열 (
int a[10000000];)
- 한계를 넘어 가드 페이지를 건드리면 발생
가드 페이지
- Windows: 커밋된 영역 바로 아래에 붙어서 스택과 함께 이동
- 최대 크기만큼 reserve, 필요한 만큼만 commit
- 가드 페이지 접근 시 OS가 커밋하고 가드를 한 칸 아래로 옮김
- 예약 영역 끝에서 더 못 옮기면 스택 오버플로
- Linux pthread 스택: 맨 아래 경계에 고정, 접근 시
SIGSEGV - 큰 지역 배열은 가드 페이지를 건너뛸 수 있어서 컴파일러가 스택 프로브(MSVC
__chkstk)를 삽입
스택 버퍼 오버플로
- 스택 위 배열 하나의 범위를 넘어 쓰는 것
- 스택 공간이 남아 있어도 발생
- 배열은 위로 넘치므로 이미 쌓인 데이터를 덮음
- 저장된 레지스터 → 복귀 주소 → 호출한 함수의 프레임 순
- 가드 페이지는 반대쪽이라 막지 못함
- 원인
- 범위 검사 없는 쓰기, off-by-one (
i <= N) strcpy,sprintf,gets등 길이 미확인 함수memcpy크기 오류
- 범위 검사 없는 쓰기, off-by-one (
- 증상
- 쓰는 순간이 아니라 return 시점에 크래시
- 콜스택이 깨져 보임
- VS Debug 빌드의 “Stack around the variable … was corrupted”
- 방어
- 스택 카나리 (
/GS,-fstack-protector) - ASLR, DEP
- 경계를 지키는 도구 (
std::array,std::vector,std::string)
- 스택 카나리 (
scanf
scanf("%s", buf)는 버퍼 크기를 모르고 길이 제한 없이 씀%[^\n]도 동일,gets는 같은 이유로 표준에서 삭제- VS C4996 경고의 이유,
_CRT_SECURE_NO_WARNINGS는 경고만 끌 뿐 - 해결
scanf("%15s", buf)(널 문자 자리 1칸 제외)scanf_s("%s", buf, 16)(MSVC)fgets(buf, sizeof(buf), stdin)
scanf("%d", &n)은 오버플로 없음, 단&누락 시 다른 메모리 손상
int 배열
- 타입 무관, 스택의 모든 배열에서 발생 (int는 한 칸당 4바이트 손상)
- 입력받은 개수만큼 배열에 넣는 코드에서 흔한 실수
- 함수 매개변수
int a[]는 실제로 포인터sizeof(a)는 포인터 크기(8)- 길이를 몰라 범위 초과가 쉬움
- C는 길이를 함께 전달, C++은
std::array,std::vector,std::span
오류 코드
- 둘 다 C++ 예외가 아님 →
try/catch로 못 잡음 - Windows
- 스택 오버플로:
0xC00000FD /GS감지 스택 버퍼 오버플로:0xC0000409- 감지 못 하고 망가진 주소로 점프: 보통
0xC0000005 0xC00000FD는 SEH로 잡을 수는 있으나 복구가 어려움0xC0000409는 SEH도 거치지 않고 즉시 종료,__fastfail공용 코드라 다른 원인일 수도 있음- “Run-Time Check Failure #2”는 예외 코드가 아니라
/RTC메시지
- 스택 오버플로:
정리
- 스택 오버플로: 스택 전체가 아래로 넘침, 재귀·큰 지역 변수, 가드 페이지로 즉시 감지
- 스택 버퍼 오버플로: 배열 하나가 위로 넘침, 복귀 주소 손상, 보안 취약점
- 핵심은 스택은 아래로, 배열 인덱스는 위로
- 전역 배열은 스택이 아니므로 어느 쪽도 아님
This post is licensed under CC BY 4.0 by the author.

