본문 바로가기

WarGame/Exploit-Exercises

[Exploit-Exercises | protostar] Stack 4 :: RET 조작을 통한 Standard Buffer Overflow


Stack 4의 소스코드는 다음과 같습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
 
void win()
{
  printf("code flow successfully changed\n");
}
 
int main(int argc, char **argv)
{
  char buffer[64];
 
  gets(buffer);
}
cs


buffer 변수만이 선언되어 있고, 입력 크기를 지정하지 않는 gets() 함수의 취약점으로 인해 BOF가 발생합니다. win() 함수를 호출하면 문제가 풀리게 되는데, Stack 3과 같이 Function Pointer도 없고 함수를 호출할 코드가 존재하지 않습니다. 따라서 함수의 리턴 주소를 담고 있는 RET 영역을 조작하여 main() 함수가 종료되고 Return 될 때 win() 함수가 호출되도록 만들어야 합니다.


Step 1. GDB를 이용하여 buffer가 메모리에 할당된 영역을 정확하게 파악해야 합니다. 앞선 문제에서도 말했지만 C 코드단에서 보이는 크기와 실제 메모리에 할당되는 크기는 다릅니다. 또, 그 차이는 OS 마다 다릅니다.

get() 함수 호출 바로 다음을 Break Pointer로 잡고 run시킨 후, 메모리를 살펴 보면 다음과 같이 buffer의 크기가 72 Bytes라는 것을 확인할 수 있습니다. (SFP의 시작주소는 $ebp의 시작주소를 파악하면 되고, RET의 시작주소는 SFP 다음 4 Byte에 위치합니다.)




Step 2. 메모리 구조를 그림으로 표현하면 다음과 같습니다.



Step 3. 다음과 같이 GDB를 이용하여 RET에 덮어쓸 win() 함수의 시작주소를 파악합니다.




Step 4. 이제 다음과 같은 payload를 통해서 buffer에서 부터 SFP까지 A문자를 입력하고 RET 영역에 win() 함수의 시작주소를 집어 넣으면 main() 함수가 종료 될 때 win() 함수를 호출하게 됩니다.