ABOUT ME

Contact.
Email:yj.anthonyjo@gmail.com
Introduce : CS Student.

Today
-
Yesterday
-
Total
-
  • 메모리 보호기법 - SSP(Stack Smashing Protector)
    보안/포너블(Pwn) 2021. 7. 2. 03:22
    반응형

    gcc 4.1부터 stack overflow를 방지하기 위해 생겨난 메모리 보호기법이다.

    stack overflow가 발생하면 stack smashing detected가 뜨면서 프로그램이 종료된다.

    SSP관련 gcc 옵션은 다음과 같다.

    • -fno-stack-protector : SSP미적용.
    • -fstack-protector-all : 지역변수로 char배열이 있는 함수 뿐만이 아니라, 모든 함수에 SSP를 적용.

    SSP의 기능으로는 3가지가 있다.

    예제와 같이 알아보자.

     #include<stdio.h>
     int func(char *a){
        int tmep=65;
        char buf[10];
        scanf("%s", buf);
     }
     void main(){
        int a=2;
        func("12345");
     }

    아래 소스코드는 다음 옵션을 주고 컴파일하였다. 32비트 기준으로 컴파일하였다.

    -fno-stack-protector의 유무이다.

    gcc -m32 -mpreferred-stack-boundary=2 -z execstack -no-pie -o

    func함수에서의 stack상황에 대한 설명.

    ebp-0x04에 대해서는 다음 포스트를 참고하자.

    https://pmandocom.tistory.com/83

     

    printf, scanf등의 호출은 포함하는 함수에서의 push ebx(레지스터)

    간혹 컴파일된 어셈블리어를 보고 분석하다보면 다음과 같은 상황을 마주하게된다. 어떤 함수(func1)에서 분명히 선언한 지역변수는 4바이트 짜리 한개 밖에 없는데, 어셈으로 보면 해당 지역변

    pmandocom.tistory.com

    1. 로컬 변수 재배치

    char형 배열의 스택 오버플로우로 인한 지역변수의 값 오버라이팅(맞는 표현인지는 모르겠다..)을 방지한다.

    char형 배열을 지역변수 중 가장 높은 지역에 위치시킨다. stack주소를 관리하는 방법은 high->low이지만 값이 들어가는 것은 low->high이다. 따라서, 가장 높은 지역에 위치시킨다면 더이상 침범할 지역변수가 없어지게된다.

    위 stack그림을 참고하면 이해하기가 쉽다.

     

    buf배열이 오버플로우가 발생하더라도 temp는 오버라이팅에서 안전하다.

    여기서 혹 ret, sfp등이 보호되지 않는다고 생각할 수도 있겠지만, 이는 3번기능인, canary로써 제어된다.

    어셈블리어로 해당 부분을 살펴보자.

    int temp가 먼저 선언된 C코드와 다르게, char buf[10]이 먼저 선언(주소관리방향을 고려하였을 때)되었다.

    즉, 더 높은 주소에 위치하여있다.

     

    2. 로컬 변수전에 포인터 배치

    실인자(argu)로 push된 값의 오버라이팅(위 예제를 기준으로 조금 더 명확히 말하면 주소값이다.)을 방지하기 위한 기능이다.

    위 그림을 보면, push된 값을 ebp-0x1c가 가지고 있는 것을 알 수 있다.

    push값인 ebp+0x08을 바로 사용하지 않고, 이 ebp-0x1c를 사용한다. 이를 통해 매개변수의 데이터를 보존한다.

     

    추기적으로, 인자로 전달된 값이 "12345"는 .rodata segment에 담겨있다. 이 값을 담고 있는 주소(32bit)를 가지고 있으면된다.

    "12345"의 주소
    maintenance info sections명령어 결과.

     

    이를 어셈블리어로 살펴보자.

    ebp+8에 있는 값(실인자값)을 ebp-1c에 할당하는 것을 알 수 있다. 이를 통해 실인자 오버라이팅을 방지한다.

     

    3. canary삽입

    char형 배열에서 오버플로우가 발생하였는지 확인한다.

    만약 오버플로우가 발생하였다면, stack-smashing-detected메시지를 띄우고 프로그램을 종료한다.

    이 canary의 방식은 3가지가 있다.

    첫째, Random Canaries.canary값을 랜덤하게 생성하여, 바뀌지 않음을 확인하는 방식이다. 일반적으로 exploit으로 canary값을 읽는 것은 불가능하다고 알려져있다. 따라서 공격자는 이 값을 확인할 수 없다. 사실상 불가능하다.●둘째, Terminator Canaries. canary데이터에 문자열의 끝을 나타내는 문자들(NULL(0x00), CR(0x0d), LF(0x0a), EOF(0xff))을 포함한다. 따라서 이 canary를 우회하려면 문자열을 종료시켜야한다. 이 방법을 통해 canary이상으로 문자열 복사 등이 진행되지 않도록한다.셋째, Random XOR Canariescanary값을 모든 제어데이터 또는 일부의 제어데이터를 사용해 xor scramble하여 생성한다.

     

    그리고 예제의 어셈블리어 결과로 보자면, random 방식을 이용한 것을 알 수 있다.

    xor명령어를 통해 값이 변경되었는지를 확인한다.

    반응형

    댓글

Designed by Tistory.