오늘은 컴파일러에서 버퍼오버플로우를 탐지/차단하기 위해 삽입하는 카나리에 대해 알아보겠습니다.
저희가 저번에 스택 버퍼 오버플로우를 공부하면서 스택카나리를 비활성화시키는 명령어를 사용했었습니다.


왼쪽은 카나리 삽입전, 오른쪽은 카나리 삽입 후입니다.
저희가 스택 버퍼 오버플로우를 시도 할 때 버퍼와 SFP를 덮어버리고 RET을 변경하여 원하는 코드를 실행할 수 있게 되는 방식이었는데 Canary라는 임의의 값을 삽입하고, 해당 값의 변조 여부를 확인해서 변조가 됐을시 프로세스를 종료하는 방식으로 버퍼오버플로우를 차단합니다.
먼저 간단한 카나리 확인용 코드를 작성해보겠습니다.
#include <unistd.h>
int main(){
char buf[8];
read(0,buf,32);
return 0;
}
위의 코드를 canary.c로 저장했습니다.
스택버퍼오버플로우에서 공부했듯 해당 코드는 버퍼에 일정 크기 이상의 입력을 받으면 리턴주소가 덮이고 공격받을 수 있는 코드입니다.
먼저 스택카나리를 끈 뒤 컴파일해보겠습니다.
gcc -l canary.c -fno-stack-protector -o no_canary
그 다음 실행시켜준 뒤 입력을 길게 넣어보겠습니다

Segmentation fault가 발생하게 됩니다.
이번엔 스택카나리를 킨 뒤 컴파일해보겠습니다.
gcc -o canary canary.c
실행시켜준 뒤 마찬가지로 입력을 넣어주면

아까와는 다르게 stack smashing detected라는 문구가 뜨면서 강제 종료됩니다.
그럼 no_canary와 canary를 어셈블리어로 변환해서 분석해보겠습니다.

코드 그대로 32바이트의 입력공간을 만들고 read()함수를 실행시킵니다.

위의 코드와 비교해보시면
0x0000000000001175 <+12>: mov rax,QWORD PTR fs:0x28
0x000000000000117e <+21>: mov QWORD PTR [rbp-0x8],rax
0x0000000000001182 <+25>: xor eax,eax 0x000000000000119f <+54>: mov rdx,QWORD PTR [rbp-0x8]
0x00000000000011a3 <+58>: sub rdx,QWORD PTR fs:0x28
0x00000000000011ac <+67>: je 0x11b3 <main+74>
0x00000000000011ae <+69>: call 0x1060 <__stack_chk_fail@plt>총 7줄이 추가된 것을 알 수 있습니다.
쉽게 이해해서 랜덤값을 rax에 저장한 뒤 그 값이 rbp-0x8에 저장됩니다
그리고 메인이 진행되다가 마지막 부분에 rdx에 rbp-0x8에 저장된 값과 맨처음 랜덤값을 가져온 fs:0x28의 값이 동일한지 확인해서 같으면 main으로 je(jump equal)을 진행하는 방식입니다.
fs:28은 랜덤 난수값으로 채워지는 세그먼트 레지스터입니다.
gdb로 프로세스를 실행시키고 명령어를 입력하면 fs:28값을 확인할 수 있습니다.
x/gx $fx_base+0x28
그리고 디버거로 ni를 입력해가면서 한줄씩 실행하다보면

RAX값에 해당 난수가 들어가는 것을 볼 수 있습니다.
만약에 카나리값에 대한 변조가 없이 실행흐름을 이어간다면

해당 분기 rdx값에

0이 들어가서 프로세스가 정상 종료 되고

다음과 같이 버퍼의 크기보다 입력을 길게 넣어서 카나리 값이 변조될경우

rdx에 0이 아닌 다른 값이 들어가

__stack_chk_fail이 뜨면서 프로세스가 종료됩니다.
canary를 우회하는 방법은 실행 도중 스택 카나리 값을 읽어와서 데이터를 덮어쓰거나, 부분적인 덮어쓰기를 통해서 카나리를 우회하는 방법이 있습니다.
다음 포스팅에서 스택 카나리를 우회하는 방법에 대해서 알아보겠습니다.
읽어주셔서 감사합니다.
'취약점분석 > Pwnable' 카테고리의 다른 글
| [Pwnable] ssp_001 write up (0) | 2025.09.24 |
|---|---|
| [Pwnable] 스택 카나리 - 2 (Canary Leak) (0) | 2025.09.22 |
| [Pwnable] 스택 버퍼 오버플로우 (1) | 2025.06.30 |
| [Pwnable] Shellcraft와 셸코드 문제 풀이(shell_basic) (0) | 2025.06.19 |
| [Pwnable] 셸코드 바이트코드 추출 (0) | 2025.06.19 |