관리 메뉴

개발자비행일지

모의해킹 시스템해킹 리눅스 RET Overwrite-1 본문

▶ 모의해킹 공부

모의해킹 시스템해킹 리눅스 RET Overwrite-1

Cyber0946 2020. 2. 20. 17:15

https://dreamhack.io/learn/2#10

# 해당내용은 아래 사이트에서 제공해주는 자료를 따라하면서 개인 복습용으로 정리한 내용입니다. 

 

로그인 | DreamHack

 

dreamhack.io

Introduction to RET Overwrite Exploitation

이 장에서는 스택 버퍼 오버플로우 취약점을 공격하는 방법에 대해 배워보도록 한다. 

메모리 보호 기법이 없는 경우부터 시작하여, 메모리 보호 기법의 등장과 우회 방법에 대해 순서대로 

알아본다. 

스택버퍼 오버플로우 취약점이 있을 때에는 주로 스택의 리턴 주소를 덮는 공격을 하며, 리턴 주소는 함수가 끝나고 돌아갈 이전 함수의 주소로, 스택에 저장된 리턴 주소를 다른 값으로 바꾸면 실행 흐름을 조작 가능하다. 

RET Overwrite Exploitation에서는 리턴 주소를 덮어 실행 흐름을 조작해 공격자가 원하는 코드를 실행하는 방법에 대해 배울 수 있다. 

스택버퍼 오버플로우 

다음의 예제 코드를 컴파일 한다. 

이때, 컴파일 옵션은 다음과 같다. 

gcc -o example1 example1.c -fno-stack-protector -z execstack -mpreferred-stack-boundary=2 -m32

예제의 프로그램의 메인에서는 argv[1[을 vuln의 함수의 인자로 전달한다. 

vuln 함수에서는 src 버퍼를 buf 버퍼에 strcpy 함수를 이용해 복사한다. 

strcy 함수는 피복사 버퍼에 대해서 길이 검증을 않하기 때문에, 프로그램의 첫 번째 인자에 buf 배열의 크기보다 긴 문자열을 넣으면 스택 버퍼 오버플로우가 발생한다. 

이때의 vuln 함수의 메모리 구조는 다음과 같다. x86 아키텍처 호출 규약에 의해 vuln 함수가 호출되면 vuln 함수의 인자인 src 문자열 포인터가 스택에 먼저 쌓이고, 이후 vuln함수의 리턴 주소, 함수의 프롤로그에서 ebp 레지스터를 저장한 다음 지역 변수의 공간을 할당한다.

취약점이 존재하는 vuln 함수에 브레이크포인트를 설정한 후 첫 번째 인자와 함께 example1 바이너리를 실행해보자, 위에서 소스코드를 기반으로 유추했던 스택 구조와 동일한지 브레이크포인트를 활용해서 스택 메모리를 관찰해 보자, 먼저 b 명령으로 vuln 함수의 시작 주소를 브레이크 포인트로 설정하고

r aaaabbbbccccdddd를 실행한다.

그 다음 스택에 어떤 값이 들어 있는지 x/2wx를 통해서 워드 단위로 2워드를 보면, vuln함수가 돌아갈 리턴 주소와, vuln 함수에 들어갈 함수 인자가 들어간다고 유추한 것이 맞는지 확인 할 수 있다. 

먼저 (gdb) x/2wx $esp 이걸로 스택을 확인하면

0xbffff640: 0x08048494 0xbffff851 임을 알 수 있고 

그 다음 (gdb) x/i 0x08048494 명령어로

0x8048494 <main+30>: add $0x4,%esp

vuln의 돌아갈 주소가 먼저 들어 감을 알 수 있다. 그 다음 

(gdb) x/s 0xbffff851 명령어로 

메모리를 보면, 첫 4 바이트는 vuln 함수의 리턴 주소이고 다음 4 바이트는 vuln 함수의 인자인 argv[1]의 주소임을 알 수 있다.

이제 스택의 구조는 파악했다. 

스택 버퍼 오버플로우 

이제 strcpy함수가 실행되기 직전에 브레이크포인트를 설정해 인자들을 살펴보겠다. 

이제 strcpy 함수가 실행되기 직전에 브레이크포인트를 설정해 인자들을 살펴보겠습니다.

스택을 살펴보면 첫 번째 인자인 buf 주소와 두 번째 인자인 argv[1]의 주소가 저장되어 있는 것을 볼 수 있습니다.

 

strcpy 함수를 실행해 보겠습니다.

strcpy 함수의 첫 번째 인자인 buf(0xffffd4fc)  argv[1] 의 문자열이 복사된 것을 볼 수 있다.

argv[1]에 buf의 길이인 32 바이트보다 긴 문자열을 주었기 때문에 vuln의 리턴 주소가 저장된 0xffffd520 너머까지 argv[1] 문자열이 복사된 것을 확인할 수 있다.

버퍼의 구조는 위와 같다. 

x86 아키텍처의 ret 명령어는 esp 레지스터가 가리키고 있는 주소에 저장된 값으로 점프하는 명령어이기 때문에, vuln 함수가 리턴함수 수행전 esp 레지스터가 가리키고 있는 주소에는 위의 그림의 마지막 값인 0x6a6a6a6a가 저장되어 있어야 한다. 이후 ret 명령어가 실행되면 eip 레지스터는 0x6a6a6a6a가 된다. 

스택 버퍼 오버플로우 취약점을 통해 프로그램 실행 흐름이 조작되었습니다. eip 레지스터를 임의의 값으로 바꿀 수 있기 때문에 원하는 주소의 코드를 실행할 수 있는데, Linux Exploitation은 로컬 환경의 타겟을 대상으로 하기 때문에 익스플로잇 최종 목표는 프로그램의 실행 흐름을 조작하여 /bin/sh 혹은 셸 바이너리를 실행하여 권한을 탈취하는 것이 최종 목표이다. 셸은 커맨드 라인의 명령어, 혹은 스크립트를 받아 서버에서 그에 맞는 기능을 실행시켜주는 프로그램입니다. 이렇듯 프로그램의 흐름을 조작해 셸을 실행하는 이유는, 권한 상승이나 본래의 프로그램이 의도치 않은 행위를 하기 위해서 이다. 취약점이 존재하는 바이너리를 익스플로잇하여 셸 프로그램을 실행하면 해당 바이너리 권한의 셸을 획득하여 서버에 임의의 명령어를 실행할 수 있게 된다.