← 목록으로

Stack Canary: 원리와 우회 방법

[Pwn] Pwnable · 작성: 2026-07-19 19:31:03 · 조회 5

Stack Canary(스택 카나리)는 스택 버퍼 오버플로우로 리턴 주소가 덮이는 걸 막기 위한 보호 기법이다. 이름은 탄광에서 유독가스를 미리 감지하려고 데려간 카나리아 새에서 따왔다 — "뭔가 잘못됐다"를 미리 알려주는 역할이다.

원리

함수 프롤로그(시작 부분)에서 지역 변수 바로 앞, 리턴 주소 바로 뒤에 랜덤 값을 하나 심어두고, 함수가 끝나기 직전(에필로그)에 그 값이 그대로인지 검사한다.

[ 지역 변수 buf ]
[ Canary ]        <- 여기 값이 바뀌면 오버플로우가 있었다는 뜻
[ saved RBP ]
[ 리턴 주소 ]

버퍼 오버플로우로 리턴 주소까지 덮으려면 필연적으로 카나리 위치도 지나가야 하므로, 카나리 값이 바뀌면 프로그램은 리턴하기 전에 __stack_chk_fail을 호출해서 강제 종료한다. 즉 정확한 카나리 값을 모르면 오버플로우 자체는 되어도 익스플로잇으로 이어지지 않는다.

우회 방법

1. 카나리 값 자체를 leak

Format String 취약점이나 별도의 읽기 취약점으로 카나리 값을 먼저 알아낸 뒤, 그 값을 그대로 페이로드에 포함시켜 검사를 통과시킨다. 카나리는 항상 널바이트(0x00)로 시작하는데, 이건 printf류 문자열 출력 함수가 널바이트에서 멈추기 때문에 문자열 형태로 흘러나가는 걸 막기 위한 설계다.

2. 카나리를 건드리지 않는 오버플로우

구조체 안에 취약한 버퍼와 함수 포인터가 같이 있는 경우처럼, 스택 레이아웃에 따라 카나리를 지나지 않고도 원하는 값을 덮을 수 있는 경로가 있다면 그쪽을 노린다.

3. Thread Local Storage(TLS) 자체를 공격

카나리 값은 TLS에 저장되는데, 별도의 임의 쓰기(arbitrary write) 취약점이 있다면 TLS에 저장된 마스터 카나리 값 자체를 덮어써서 이후 모든 함수의 검사를 무력화하는 방법도 있다 (상당히 고급 기법).

실전 확인

$ checksec ./vuln
Canary : Enabled

gdb에서 카나리 위치를 직접 확인하려면:

pwndbg> canary
Canary        : 0x4a1b2c3d4e5f6700

카나리가 있으면 항상 "이걸 먼저 leak할 방법이 있는가"부터 찾는 게 순서다. 다음 글에서 다루는 NX 우회(ROP)와 결합해서 쓰는 경우가 대부분이다.

Pwnable 카테고리의 글 (4/14)

  1. 메모리 구조 기초: 스택, 힙, 레지스터부터 이해하기
  2. 스택 버퍼 오버플로우: 가장 기본적인 메모리 손상 공격
  3. Format String 취약점: printf가 위험해지는 순간
  4. Stack Canary: 원리와 우회 방법
  5. NX/DEP 우회와 Return-to-libc
  6. ASLR과 정보 유출(Leak)
  7. ROP (Return-Oriented Programming) 완전 정복
  8. 힙 익스플로잇 기초: Use-After-Free와 Double Free
  9. pwntools 실전 활용법
  10. UDF(User-Defined Function) 기반 DB 권한 상승: 원리부터 실전까지
  11. Pass-the-Hash / Pass-the-Ticket: 원리와 실전
  12. eBPF 기반 지속성(Persistence) 기법
  13. Full RELRO 환경에서의 GOT Overwrite와 우회
  14. ret2dlresolve: 심볼 정보 없이 임의 함수 호출하기
← Format String 취약점: printf가 위험해지는 순간 NX/DEP 우회와 Return-to-libc →