Contact CTF writeups Notes

[PicoCTF 2018] - misc - Store

This is one of my writeups for PicoCTF 2018

Problem

We started a little store, can you buy the flag? Connect with 2018shell3.picoctf.com 60893.

Hint :

  1. Two's compliment can do some weird things when numbers get really big!

Solution

When we connect to the "store", we are given a balance of 1100$ and the possibility to buy two "item" : "I Can't Believe its not a Flag!" for 1000$ and "Real Flag" for 100000$. Looks like the goal here is to find a way to "buy" the flag.

We have access to the store source code :

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int con;
    con = 0;
    int account_balance = 1100;
    while(con == 0){

        printf("Welcome to the Store App V1.0\n");
        printf("World's Most Secure Purchasing App\n");

        printf("\n[1] Check Account Balance\n");
        printf("\n[2] Buy Stuff\n");
        printf("\n[3] 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("Current Auctions\n");
            printf("[1] I Can't Believe its not a Flag!\n");
            printf("[2] Real Flag\n");
            int auction_choice;
            fflush(stdin);
            scanf("%d", &auction_choice);
            if(auction_choice == 1){
                printf("Imitation Flags cost 1000 each, how many would you like?\n");

                int number_flags = 0;
                fflush(stdin);
                scanf("%d", &number_flags);
                if(number_flags > 0){
                    int total_cost = 0;
                    total_cost = 1000*number_flags;
                    printf("\nYour total cost is: %d\n", total_cost);
                    if(total_cost <= account_balance){
                        account_balance = account_balance - total_cost;
                        printf("\nYour new balance: %d\n\n", account_balance);
                    }
                    else{
                        printf("Not enough funds\n");
                    }


                }




            }
            else if(auction_choice == 2){
                printf("A genuine Flag costs 100000 dollars, and we only have 1 in stock\n");
                printf("Enter 1 to purchase");
                int bid = 0;
                fflush(stdin);
                scanf("%d", &bid);

                if(bid == 1){

                    if(account_balance > 100000){
                        printf("YOUR FLAG IS:\n");
                        }

                    else{
                        printf("\nNot enough funds for transaction\n\n\n");
                    }}

            }
        }
        else{
            con = 1;
        }

    }
    return 0;
}

We can see that the cost to buy "fake flags" is calculated by total_cost = 1000*number_flags and the deducted from the account balance by account_balance = account_balance - total_cost. So if we can somehow order a negative quantity, we will be credited 1000*negative quantity !

Well the number of flags we want to order is a signed integer (int number_flags = 0;) and no validation is performed on the input. That means we can overflow the integer.

If we pass a quantity of 2147483547, we get just enough to buy the flag, and that displays it : picoCTF{numb3r3_4r3nt_s4f3_dee04605}.