카테고리 없음
스택 카나리
qkrdldks04
2025. 5. 28. 14:04
스택 카나리(Stack Canary)
스택 카나리는 스택 버퍼 오버플로우(Stack Buffer Overflow) 공격을 방지하기 위한 보호 기법이다. 공격자가 버퍼를 넘쳐서 반환 주소를 덮는 것을 방지하기 위해, 함수의 프롤로그에서 스택 버퍼와 반환 주소 사이에 임의의 랜덤 값을 삽입하고 에필로그에서 이 값이 변조되었는지 확인한다.
작동원리

공격자가 반환 주소를 덮으려면, 반드시 그 앞에 있는 카나리 값을 먼저 덮어야 한다. 그러나 카나리 값은 임의(Random)이며, 매 실행 시 변경되므로 공격자가 이를 예측하기 어렵다. 만약 카나리 값이 변조되었다면, 프로그램은 즉시 __stack_chk_fail()을 호출하여 프로세스를 종료한다.
함수의 프롤로그와 에필로그
- 프롤로그: 함수 시작 시 실행
- 이전 함수의 rbp 저장
- 현재 함수의 스택 프레임 구성
- 카나리 값 삽입 (mov QWORD PTR [rbp-0x8], rax)
- 에필로그: 함수 종료 시 실행
- fs:0x28에 있는 카나리와 [rbp-0x8]의 값을 비교
- 다르면 __stack_chk_fail() 호출
정적 분석
-fno-stack-protector | 스택 카나리 비활성화 → 버퍼 오버플로우 시 Segmentation fault |
-fstack-protector 또는 -fstack-protector-all | 스택 카나리 활성화 → 카나리 값 변조 시 stack smashing detected 메시지 출력 후 종료 |
동적 분석
카나리는 TLS(Thread Local Storage) 영역에 저장되며, 해당 주소는 fs:0x28이다. GDB를 통해 다음과 같이 카나리 확인 가능
print /a $rax # rax에 담긴 주소를 확인 x/gx $rbp-0x8 # rbp 기준으로 카나리 값을 8바이트 단위로 출력
또한, arch_prctl 시스템 콜을 Catchpoint으로 설정하여 fs 레지스터 값을 추적할 수 있다
카나리 생성 및 구성
- 프로세스 시작 시 카나리는 TLS에 전역 변수로 저장된다.
- 각 함수는 프롤로그와 에필로그에서 이 값을 참조한다.
- 카나리는 실행마다 랜덤하게 설정되며 fs:0x28 위치에서 확인 가능하다.
- fs 레지스터 값은 arch_prctl() 시스템 콜을 통해 설정되므로, 이를 추적하면 카나리 접근이 가능해진다.
카나리 우회 방법
1) 무차별 대입 (Brute Force)
- 반복적으로 프로그램을 실행하며 카나리 값을 맞춰보는 방법
- ASLR, PIE 등이 꺼져있어야 가능함
2) TLS 직접 접근
- fs:0x28 주소에서 직접 카나리 값을 읽는 방법
- 보통은 우회가 어렵지만, TLS를 임의로 읽을 수 있는 취약점이 있으면 가능
3) 스택 카나리 릭 (Leak)
- 카나리 값을 유출할 수 있는 취약점(ex. 포맷 스트링 버그 등)을 이용하여 유출된 값을 기반으로 정확한 버퍼 오버플로우 공격 수행 가능