본문으로 바로가기

[Protostar] Stack3 풀이, write-up

category Wargame/Protostar 2019. 1. 8. 14:06

Protostar --- Stack3



Stack3의 내용이다. (내용이 달라서 개인적으로 덧붙였다.)


We learn How to overwriting function pointers stored on the stack(as a prelude to overwriting the saved EIP)


해석해보면 다음과 같다.


우리는 stack 영역에 저장된 function pointer를 바꾸는 방법에 대해 배울 것이다.

이것은 saved EIP를 overwriting 하는 시초이다.


Stack3의 Hint는 다음과 같다.


both god and objdump is your friend you determining where the win() function lies in memory.


Stack3의 Hint를 해석해보면 다음과 같다.


gdb 그리고 objdump 모두 win() 함수가 어떤 메모리 위치에 있는지 결정하는데 도움을 주는 친구가 될거다.



stack3.c의 소스를 보자.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#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)
{
  volatile int (*fp)();
  char buffer[64];
 
  fp = 0;
 
  gets(buffer);
 
  if(fp) {
      printf("calling function pointer, jumping to 0x%08x\n", fp);                
      fp();
  }
}
cs



volatile keyword를 사용하여 int type function pointer *fp를 선언한다.

char type 64 byte array buffer를 선언한다.



1
2
3
4
int main(int argc, char **argv)                                                    
{
  volatile int (*fp)();
  char buffer[64];
cs



function pointer fp(함수의 주소)에 0을 대입한다.

gets() 함수를 통해 user로부터 buffer에 문자열을 입력받는다.



1
2
3
  fp = 0;
 
  gets(buffer);                                                                    
cs



만일 fp의 값(함수의 주소 값)이 0이 아니면 "calling function pointer, jumping to fp"를 출력하고 fp() 함수를 실행한다.

만일 fp가 0이면 아무것도 실행하지 않는다.



1
2
3
4
5
  if(fp) {
      printf("calling function pointer, jumping to 0x%08x\n", fp);                
      fp();
  }
}
cs



void의 return을 갖는 win() 함수를 선언한다.

win() 함수는 "code flow successfully changed\n"라는 문자열을 출력한다.



1
2
3
4
void win()
{
  printf("code flow successfully changed\n");                                    
}
cs



실행을 해보면 아래와 같다.

fp를 덮었다고 가정했을때와, fp를 덮지 못했을 때이다.





우리가 조작해야할 string pointer가 stack 영역 중 어디에 위치해 있는지 알기 위해 gdb를 통한 분석을 진행한다.





gdb를 통해 우리는 stack의 구조를 살펴 볼 수 있고, win()의 주소가 "0x0000000000401142"라는것을 확인할 수 있다.


gdb를 통해 stack의 구조(only main function)를 보면 아래와 같다.






fp의 조작을 위해 우리는 72 byte의 padding을 통해 fp에 접근할 수 있고, fp를 win()의 주소("0x0000000000401142")로 overwriting 하면 된다.





성공!!




참고로 쉽게 함수명을 알 때 함수의 주소를 아는 방법이 크게 두가지가 있다.


objdump -d <filename> | grep \<function name\>: -A <number of line>





gdb를 이용한 방법


print <function name>





'Wargame > Protostar' 카테고리의 다른 글

[Protostar] Stack5 풀이, write-up  (0) 2019.01.12
[Protostar] Stack4 풀이, write-up  (0) 2019.01.09
[Protostar] Stack2 풀이, write-up  (0) 2019.01.07
[Protostar] Stack1 풀이, write-up  (0) 2019.01.06
[Protostar] Stack0 풀이, write-up  (0) 2019.01.05