ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • LEVEL 11
    WARGAME/FTZ 2018. 4. 24. 17:13
    level11

    FTZ LEVEL11


    [Summary]

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

    [Sourcecode]

    1.  #include <stdio.h>
    2.  #include <stdlib.h>
    3.
    4.  int main( int argc, char *argv[] )
    5.  {
    6.          char str[256];
    7.
    8.          setreuid( 3092, 3092 );
    9.          strcpy( str, argv[1] );
    10.         printf( str );
    11. }
    

    [Analysis]

    • 먼저, 소스코드를 통해 프로그램의 흐름을 대략적으로 파악(정적분석)한 뒤 프로그램을 실행(동적분석)시켜보며 분석 할 것이다.
    • setuid 가 설정되어 있으면 gdb 가 동작하지 않기 때문에 tmp 디렉토리에 cp 명령을 이용하여 복사한다.
    • attackme 소스코드를 보면 인자(argv[1]) 하나를 전달받아 str 배열에 복사한 후 str 을 출력한다.
    • 여기서 취약점이 두 곳에서 발생한다. 한 곳은 9라인 취약한함수 strcpy 를 사용하여 Buffer Overflow 가 발생하고, 다른 한 곳은 10라인 printf 함수에 포맷 스트링을 지정해주지 않아 Format String Bug 가 발생한다.
    • 필자는 BOF(Buffer Overflow) 를 이용하여 level12 의 권한을 획득할 것이므로 FSB(Format String Bug) 는 추후에 작성할것이다.
    • 대략적으로 프로그램을 파악한뒤, 이제 gdb 를 통해 디버깅(동적분석) 을 할 것이다.
    • gdb 에 attackme 프로그램을 올린 뒤, disassemble main(disas main 가능) 명령을 통해 main 함수(Entry Point, EP) 를 disassemble 하고, ret(main+75) 에 BreakPoint(BP) 를 건다.
    • ret 에 BP 를 거는 이유는 strcpy 를 통해 str 배열에 복사가 되고, 출력을 시킨 후 프로그램이 끝나기 직전 상태의 스택을 보기 위함이다.
    • 대충 페이로드를 계산하면, str 배열이 256 바이트이고, sfp 4바이트, RET 4바이트이다.
    • 즉, {str 배열 + sfp ( 260바이트 )} 에 쉘코드를 넣고 {RET 주소 ( 4바이트 )} 에 str 배열 주소를 덮어씌우면 main 함수가 return 하고 쉘코드가 위치한 str 배열로 점프하면 쉘을 획득할수 있다.
    • 그러나, gdb 를 이용해 테스트을 해보면 RET 주소까지 덮여있지 않은것을 볼 수있다.
    • 이것은 각 시스템마다 메모리를 할당하는 단위가 있는데 단위를 맞춰주기 위해서 256 바이트를 정확하게 맞혀서 할당하는것이 아니라 조금 넉넉하게 264바이트를 할당한 것이다.
    • 예를들어, 이 시스템은 메모리를 할당할 때 단위가 24바이트이다. 그러면 256 바이트를 할당하기 위해서 8바이트 패딩을 넣고 총 (24 * 11 = 264) 바이트를 할당하는 것이다.
    • 마지막으로, str 의 (시작)주소를 알아내고, {str(264바이트) + sfp(4바이트) + RET(4바이트)} 에 맞게 페이로드를 작성하면 exploit 을 성공 할 것이다.


    • Segmentation Fault 이유는 간단하다. 다시 gdb 를 이용해 str 의 주소를 확인해보면 달라져있다.
    • 이것은 ASLR 이라는 메모리 보호기법인데, 메모리 주소가 항상 고정적이면 해커가 그 주소만 알아내면 쉘코드를 넣기도 쉽고 페이로드 작성하기도 훨씬 수월하여 이를 보호하기 위해 스택주소를 랜덤하게 할당하는 기법이다.
    • ASLR 을 우회하기 위해서는 attackme 프로그램에서 로드되는 스택 메모리를 사용하지 않고 다른 공간을 할용해야한다.
    • gdb 를 이용해 스택의 가장 높은주소로 가보면 시스템의 환경변수와 함께 메모리에 로드되어 있습니다. 또한, 매 실행마다 그 환경변수의 주소 값은 변하지 않는다.
    • 환경변수들의 주소값이 변하지 않는 이유는 정확하게는 모르겠지만, 사용자가 사용할 수 있는 스택의 범위는 정해져있고, 환경변수들은 가장 높은 주소에 위치해 있어 가장 먼저 로드되고 스택은 거꾸로 자라기 때문에 상대적으로 낮은주소에 있는 코드영역이나 데이터영역에 있는 주소값들이 랜덤하게 변하는것으로 추측 된다.
    • 그렇다면, 환경변수에 쉘코드를 넣고 RET 주소에 쉘코드가 위치한 환경변수의 주소값을 넣으면 exploit 을 할 수 있다.



    [Exploit]

    ./attackme $(python -c 'print "A"*268 + "\x1f\xfc\xff\xbf"')
    


    [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 12  (0) 2018.04.26
Designed by Tistory.