Canaries

- 버퍼 오버 플로우를 모니터하기 위해 버퍼와 제어 데이터 사이에 설정 된 값

- 버퍼 오버플로가 발생 → canary 값이 손상, canaries 데이터의 검증에 실패하여, 오버플로에 대한 경고 출력, 손상된 데이터를 무효화 처리

 

< Types of canaries >

Terminator canaries

- canary의 값을 문자열의 끝을 나타내는 문자들을 이용해 생성

- 구성 : NULL (0x00), CR (0x0d), LF (0x0a) 및 EOF (0xff)

- 공격자는 Canaries의 값을 우회하기 위해 Return address를 쓰기 전 null 문자를 써야 한다.

  ≫ null 문자로 오버플로우를 방지한다. (strcpy()는 null문자의 위치까지 복사)

  공격자는 잠재적으로 canary를 알려진 값으로 겹쳐쓰고 정보를 틀린 값들로 제어한다.

 

 Random canaries

- canary의 값을 랜덤하게 생성한다. (일반적으로 익스플로잇을 통해 canary를 읽는 것은 논리적으로 불가능)

- 프로그램 초기 설정 시 전역 변수에 canary값이 저장된다.

   해당 메모리를 읽으려 시도 → segmentation fault + 프로그램 종료

- 공격자가 canary 값이 저장된 stack address를 알거나 스택의 값을 읽어올 수 있다면 값ㅇ르 확인할 수 있다.

 

 Random XOR canaries

- 모든 제어 데이터 or 일부를 사용해 XOR-scramble하여 canary 값을 생성한다.

   canary 값, 제어 데이터 오염 → canary 값 달라짐

- Random canaries와 동일한 취약점을 가지고 있다.

   공격자는 canary를 다시 인코딩하기 위해 original canary값, 알고리즘, 제어 데이터가 필요

 

 

< Example >

#include <stdio.h>
 
void main(int argc, char **argv)
{
    char Overflow[32];
     
    printf("Hello world!\n");
    gets(Overflow);
 
}

 

▶ canary 값 확인하기

 

- 사용자 값이 저장되는 영역은 0x7fffffffe180 이며 해당 영역에 코드에서 할당한 길이의 문자를 저장한다. ('A' * 32)

 

- 0x400610에서 rax 레지스터에 rbp - 0x8 영역에 저장된 값을 저장한다.

   rbp(0x7fffffffe1b0) - 0x8 = 0x7fffffffe1a8

   0x7fffffffe1a8 영역에 저장된 값 : 0x3a3b864735c7b300

- 0x400614에서 rax 레지스터에 저장된 값과 fs:0x28 레지스터에 저장된 값을 xor 연산한다.

- 0x40061d에서 rax 레지스터의 값이 0과 같으면 0x400624 영역으로 이동한다.

 

- 이렇게 프로그램이 종료된다.

 

▶ canary 값 덮어쓰기

- 사용자 입력 값으로 'A' * 40 + 'B' * 8 을 입력한다.

  ≫ 이로 인해 canary의 값이 0x4242424242424242(BBBBBBBB) 으로 변경됐다.

 

- 0x400610에서 rax 레지스터에 rbp - 0x8 영역에 저장된 값을 저장한다.

  rbp(0x7fffffffe1b0) - 0x8 = 0x7fffffffe1a8

   0x7fffffffe1a8 영역에 저장된 값 : 0x4242424242424242

 

- 0x400614에서 rax 레지스터에 저장된 값과 fs:0x28 레지스터에 저장된 값을 xor 연산한다.

- 0x40061d에서 rax 레지스터의 값이 0x61061c8ecf993242 이기 때문에 다음 코드 영역(0x40061f)으로 이동한다.

 

- 위와 같은 error메세지를 출력한다.

 

 

< Check the protection techniques of binary files >

checksec.sh

- not set canary : gcc -fstack-protector -o Canary_Do-not-set Canary.c

- set canary :gcc -o Canary Canary.c

 

< How to detect Canary in the "Checksec.sh" file >

Binary

 

- 'readelf' 명령어를 이용해 해당 파일의 심볼 테이블 정보를 가져와 Canary 설졍여부를 확인한다.

- 파일의 심볼 테이블에 "__stack_chk_fail"가 있으면 Canary가 적용되었다고 판단한다.

 

Process

 

- Binary의 확인 방식과 비슷하며, 전달되는 파일의 경로가 다음과 같이 다르다. (ex) /proc/<PID>/exe)

- 추가된 동작은 '/proc/<PID>/exe' 파일에 'Symbol table' 정보가 있는지 확인한다.

+ Recent posts