지난번에 함수의 호출과 복귀에 대해 설명했으니 이번엔 가장 기초적인 Pwnable 기법인 'Return to Shellcode' 에 대해 포스팅 하겠습니다. Return to Shellcode란 함수의 기존 Return Address를 Shellcode가 있는 주소로 덮어씌워 함수가 종료되고 복귀할때 Shellcode로 복귀시켜 쉘코드 명령을 실행하게 하는 기법입니다.
함수의 호출과 복귀에 대해서 알고 계신다면 대충 어떤 기법인지 감이 오실겁니다. 만약 함수의 호출과 복귀에 대해서 잘 모르신다면 이전에 제가 올린 포스팅('함수의 호출과 복귀')를 한번 읽고 오신다면 이해하기 훨씬 편하실겁니다. 모든 함수가 똑같지 않지만 일반적인 함수의 Stack은 아래와 같습니다.
SFP(Stack Frame Pointer)를 기준으로 아래 부분은 해당 함수의 Stack 영역이라고 보면되고 보통 해당 영역에는 지역 변수와 매개 변수가 저장됩니다. 그런데 만약 공격자가 정해진 (지역/매개)변수의 크기 보다 훨씬 많은 데이터를 삽입하려고 한다면 어떻게 될까요? 예를 들어서 char 형 4칸짜리 배열이 있는데 입력을 ABCD 가 아닌 ABCDEFGH를 입력한다면? ABCD는 배열에 제대로 저장되지만 뒤에 있는 EFGH는 SFP를 덮어 씌우게 됩니다. 간단한 예제 프로그램을 하나 짜보고 확인해 보겠습니다.
#include <stdio.h>
#include <string.h>
int main()
{
char a[4];
strcpy(a,"ABCDEFGH");
}
단순히 char형 배열에 정해진 사이즈보다 큰 사이즈를 넣어주는 프로그램입니다. 다만 이대로 컴파일해서 실행할 경우 Stack smashing detected 라는 에러 메세지를 뱉어내며 프로그램이 종료되게 됩니다. 이는 SSP(Stack Smashing Protector)라는 기능으로 말 그대로 스택 오버 플로우를 방지해주는 기능입니다. 이에 대한 자세한 내용은 나중에 보호기법을 소개하는 포스팅을 작성할때 하도록하고 지금 당장은 원활한 실습을 위해 해당 기능을 꺼주고 컴파일 하겠습니다.
$gcc -o test test.c -fno-stack-protector -g
컴파일 후 바로 pwndbg를 이용해 분석해봤습니다. strcpy의 실행이 종료된 후 rbp 값을 보면 a 배열에 미처 담지 못하고 넘어온 EFGH가 들어가 있는것을 확인할 수 있습니다. 결국 Stack 영역에 정해진 변수의 사이즈보다 더 큰 데이터를 입력할 수 있다면 이를 이용해 Return Address를 조작할 수 있게 된다는 겁니다. 결국 공격자는 메모리 어딘가에 Shellcode를 삽입하고 함수의 Return Address를 Shellcode가 있는 위치의 주소로 덮어 씌워서 함수가 종료됐을때 공격자가 삽입한 Shellcode를 실행하게 유도할 수 있습니다! :)
간단 요약
'Pwnable > Tech' 카테고리의 다른 글
OOB(Out Of Boundary) (0) | 2020.06.14 |
---|---|
함수의 호출과 복귀 (0) | 2019.08.09 |