Canary
스택의 반환 주소(Return Address)를 조작하는 공격 기법으로 부터 보호하기 위해 만들어졌다.
- 함수의 프롤로그에서 스택 버퍼와 반환 주소 사이에 임의의 값을 삽입
- 함수의 에필로그에서 해당 값의 변조를 확인
- -fno-stack-protector옵션으로 카나리를 해제할 수 있다.(활성화 : default라 따로 안해도 됨)
작동 원리
적용된 바이너리와 적용되지 않은 바이너리를 비교해보자.

함수 프롤로그
- mov rax, QWORD PRT fs:0x28
-canary 값을 생성해서 rax에 넣는다.
- Mov QWORD PTR [rbp-0x8], rax
- xor eax, eax
- lea rax, [rbp-0x10]
함수 에필로그
- Mov rcx, QWORD PRT [rbp-0x8]
- rcx=canary
- Xor rcx, QWORD PTR fs:0x28
- 프롤로그에서 만든 canary의 값이 변조 되었는지 확인
- Je 0x11b3 <main+74>
- 변조가 안 되어있다!! 그럼 정상 종료!!
- Call 0x1060 <__stack_chk_fail@plt>
- 변조 되었다. 강제 종료!!
Canary 생성 과정
-Canary 값은 프로세스가 시작될 때, TLS에 전역 변수로 저장하고, 각 함수마다 프롤로그와 에필로그에서 이 값을 참조한다.
- TLS의 주소 파악
- Fs는 TLS를 가리키므로 fs의 값을 알면 TLS의 주소를 알 수 있다.
그러나 리눅스에서 fs의 값은 특정 시스템 콜을 사용해야만 조회하거나 설정할 수 있다.
※gdb에서 다른 레지스터의 값을 출력하듯 info register fs나, print $fs와 같은 방식으로는 값을 알 수 없다.
- arch_prctl(int code, unsigned long addr) 시스템 콜에 중단점을 설정하여 fs가 어떤 값으로 설정되는지 조사해보자.
- arch_prctl(int code, unsigned long addr) -> fs값을 설정할 때 호출됨
catch 명령 : 특정 이벤트가 발생했을 때, 프로세스를 중지시키는 명령이다.
ㄴ>rsi의 값 : 0x7fffffffdc90
ㄴ>rdi의 값 : 0x3001 -> ARCH_SET_FS의 상숫값

ㄴ>rsi에 있던 주소 + 0x28에 canary값이 들어있어야 한다.
ㄴ>watch : 특정 주소에 값이 바뀌면 실행을 중단 시킨다.
ㄴ> ?? Canary값이 안들어있네....
'포너블 > 공부' 카테고리의 다른 글
FPO(Frame pointer Overflow) (0) | 2020.02.01 |
---|