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

+ Recent posts