-
메모리 보호기법 - 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
ebp-0x04에 대해서는 다음 포스트를 참고하자.
https://pmandocom.tistory.com/83
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)를 가지고 있으면된다.
이를 어셈블리어로 살펴보자.
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명령어를 통해 값이 변경되었는지를 확인한다.
반응형'보안 > 포너블(Pwn)' 카테고리의 다른 글
어셈으로보는 for, while, do-while. (0) 2021.07.02 printf, scanf등의 호출은 포함하는 함수에서의 push ebx(레지스터) (0) 2021.07.02