eli_ez3r
eli_ez3r
eli_ez3r
전체 방문자
오늘
어제
  • 분류 전체보기 (202)
    • 0x01 끄적끄적 :) (57)
      • Network (5)
      • Security (14)
      • Reversing (2)
      • Forensic (5)
      • Operation System (10)
      • Development (10)
      • Solution (7)
      • 보안 상식 (3)
    • 0x02 Study :) (127)
      • Pwnable (59)
      • Webhacking (56)
      • Reversing (11)
      • Machine Learning (1)
    • 0x03 ETC :) (16)
      • IT Unpacking (5)
      • IT Information (1)
      • Enjoy (4)
      • Etc (6)
    • Admin :) (0)
      • 0x01 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

  • github.io 블로그 개설

인기 글

태그

  • hacker
  • 과정
  • 문제풀이
  • 공격
  • 메모리
  • hacking
  • 문제
  • 해킹
  • webhacking.kr
  • pwnable
  • Up
  • hakcing
  • 설명
  • LOB
  • 스쿨
  • 패스워드
  • 암호
  • 오버플로우
  • attack
  • buffer
  • web
  • school
  • 해커
  • LEVEL
  • hack
  • write
  • overflow
  • BOF
  • password
  • 풀이

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
eli_ez3r

eli_ez3r

[해커스쿨] FTZ level18 풀이과정
0x02 Study :)/Pwnable

[해커스쿨] FTZ level18 풀이과정

2017. 1. 12. 10:23


2017/01/12 - [Study :)/FTZ] - [해커스쿨] FTZ level17 풀이과정


#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);
}

그동안의 hint와 길이적으로 차이가 나는 힌트이다... 뜨허억.


천천히 읽어보니 check 변수에 0xdeadbeef 가 있으면 shellout()함수를 실행시키면서 권한 상승이 일어난다. 그럼 끝 아닌가...? 일단.. 결론..

int main()
{
  char string[100];
  int check;
  int x = 0;
  int count = 0;
  fd_set fds;
  printf("Enter your command: ");
  fflush(stdout);
  while(1)
    {
      //
    }
}

변수 선언 부분을 보니... string, check, x, count 순으로 선언되었다.

이말은 즉, string배열을 이용해서 check값에 값을 넣지 넣지 못한다는것.


왜냐고? 

메모리에는 stack으로 쌓이기 때문에, string배열이 먼저 쌓이고, 그 위에 check변수가 쌓이게 된다.

그러기 때문에 아무리 string배열을 Buffer OverFlow 시켜도... check변수는 건들지도 못한다는 거지..


그래도 이해 안되는 사람들을 위해.. 



위 사진 처럼 메모리 구조가 되기 때문에, string에 아무리 값을 넣어도 SFP와 RET에 값을 넣는건 가능해도, 그 위로 값을 넣긴 힘들다. 따라서 다른 방법을 찾기 위해 코드를 좀 더 살펴보자.

while(1)
    {
      if(count >= 100)
        printf("what are you trying to do?\n");
      if(check == 0xdeadbeef)
        shellout();
      else
        {
         ////생략
        }
    }
}

무한 루프를 돌리고, count가 100이상이 되면 "what are you trying to do?"라는 문자를 출력한다.

check변수의 값이 "0xdeadbeef"면 shellout()함수를 실행시킨다.

if(check == 0xdeadbeef)
        shellout();
        else{
          FD_ZERO(&fds); //변수선언부에서 선언한 소켓구조체인 fds를 초기화한다.
          FD_SET(STDIN_FILENO,&fds); //소켓구조체에 STDIN 즉, 표준출력 넘버를 셋팅한다.

          if(select(FD_SETSIZE, &fds, NULL, NULL, NULL) >= 1){
/* select는 여러개의 fd구조체를 모니터링하는 함수이다. FD_SETSIZE는 1024로 1024개의 소켓구조체를 
모니터링 하며, 다른 인자들은 NULL로 넣고 두번째 인자인 입력에 &fds를 주어 fds구조체에 '입력'되는 
이벤트에만 true값이 셋되어 fi문 안으로 들어간다. 즉, 표준입력을 입력해야 if문 안으로 들어갈 수 있다.*/
            
              if(FD_ISSET(fileno(stdin),&fds)){
/* FD_ISSET은 fds구조체가 stdin으로 전달되는 적절한 fd정보를 가지고 있는지 확인하는 부분이다.
즉, fds에 위에서 FD_SET으로 설정한 파일디스크립터 넘버가 저장되어 있는지 검사하는 부분이다.*/ 
                
                  read(fileno(stdin),&x,1); //표준출력으로부터 1Byte만큼 읽어온다.
                  switch(x)
                    {
                      .....
                    }
                }
            }
        }
}

자, 이제 switch 부분을 살펴보자.

switch(x)
{
        case '\r':
        case '\n':
                printf("\a");
        break;
        case 0x08:
                count--;
                printf("\b \b");
        break;
        default:
                string[count] = x;
                count++;
        break;
}

표준출력으로 가져온 1Byte값이 '\r', '\n'이면 비프음('\a') 울리고 종료된다.

1Byte값이 "0x08"인 경우 count값이 감소된다. 

dafault값으로 string[count]값에 x값을 넣고, count값을 증가시킨다.

여기서 중요한 부분은 count값을 감소시킨다는 것이다.

앞에서 string배열에 값을 넣어서 check값을 변경 할 수 없다고 하였는데, string[-4]라는 값을 넣으면 메모리상에서 위로(낮은주소) 올라 갈 수 있지 않을까?

check값은 string배열 바로 위에 있으므로, 4바이트 올라가서 값을 "0xdeadbeef"를 넣으면 될 것 같다.

즉, "0x08"값을 4번 입력하고 "0xdeadbeef"값을 넣어보자.



저작자표시 비영리 변경금지 (새창열림)
    '0x02 Study :)/Pwnable' 카테고리의 다른 글
    • [해커스쿨] FTZ level20 풀이 과정 (Final)
    • [해커스쿨] FTZ level19 풀이과정
    • [해커스쿨] FTZ level17 풀이과정
    • [해커스쿨] FTZ level16 풀이과정
    eli_ez3r
    eli_ez3r

    티스토리툴바