본문으로 바로가기

[Protostar] Stack0 풀이, write-up

category Wargame/Protostar 2019. 1. 5. 11:58

Protostar --- Stack0



Stack0의 힌트이다.


This level introduces the concept that memory can be accessed outside of its allocated region, how the stack variables are laid out, and that modifying outside of the allocated memory can modify program execution.


해석해보면 아래와 같다.


이번 level은 메모리가 할당된 부분 밖(여기선 outside of array) 에서 접근 할 수 있다는 것을 소개한다.

어떻게 stack에 변수가 할당되는지, 할당된 부분 밖의 메모리를 변형하는 것은 프로그램의 실행을 변형할 수 있다는 것을 소개한다.



Stack0의 소스코드는 아래와 같다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
 
int main(int argc, char **argv)
{
  volatile int modified;
  char buffer[64];
 
  modified = 0;
  gets(buffer);
 
  if(modified != 0) {
      printf("you have changed the 'modified' variable\n");                        
  } else {
      printf("Try again?\n");
  }
}
cs



volatile keyword는 volatile로 선언된 변수를 사용할 때 최적화에서 제외하여 항상 메모리에 접근하도록 하는 함수이다.

소스코드를 보면 우리가 정상적인 방식으로 gets() 함수를 이용하면 항상 "Try again?\n" 문자열을 만난다.

하지만 우리는 modified를 변경시켜 "you have changed the 'modified' variable\n"을 만나야 한다.

따라서 modified 변수를 확인할 때, 최적화 하지 않고, 직접 메모리로부터 값을 얻어오기 위해 volatile keyword를 사용한다.


volatile keyword로 4byte 정수형 modified를 선언한다.

char array buffer를 64 byte 선언한다.

modified 변수를 0으로 초기화 하고, gets() 함수를 통해 사용자로부터 buffer에 입력을 받는다.

gets() 함수는 insecure한 함수이고, overflow를 check하지 않기 때문에 여기서 취약점이 발생한다.



1
2
3
4
5
6
7
int main(int argc, char **argv)                                                    
{
  volatile int modified;
  char buffer[64];
 
  modified = 0;
  gets(buffer);
cs



modified != 0 이면 즉, modified가 변경되면 "you have changed the 'modified' variable\n"을 출력하고

modified ==0 이면 즉, modified가 변경되지 않으면 "Try again?\n"을 출력한다.



1
2
3
4
5
6
    if(modified != 0) {
          printf("you have changed the 'modified' variable\n");                    
      } else {
          printf("Try again?\n");
      }
}
cs



소스 분석을 끝냈으니 실행 과정을 확인하기 위해 아래와 같이 입력하면 overflow가 발생하는 것을 알 수 있다.





처음 실행은 간단히 test를 위해 4byte를 입력하였고, 두 번째 실행은 A를 약100번 입력하였더니 원하는 문자열을 만날 수 있었다.


정확히 분석해보기 위해 gdb를 통해 stack0를 확인해보자.





gdb를 통해 stack의 구조를 그려보면 아래와 같이 그릴 수 있다.

실제 우리가 변수를 할당하더라도 컴파일러는 stack에 접근하기 위한 최적화를 위해 dummy를 추가로 삽입할 수 있다.







즉, modified를 변경시키기 위해 최소 76바이트를 초과해서 입력해야한다.




완료!!!


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

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