Pumpkin Stand
3 minutes to read
We are given a 64-bit binary called pumpkin_stand
:
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
RUNPATH: b'./glibc/'
Reverse engineering
If we load the binary in Ghidra, we will see this decompiled C code for main
:
void main() {
long in_FS_OFFSET;
short option;
short amount;
FILE *fp;
undefined8 local_48;
undefined8 local_40;
undefined8 local_38;
undefined8 local_30;
undefined8 local_28;
undefined8 local_20;
undefined8 canary;
canary = *(undefined8 *) (in_FS_OFFSET + 0x28);
setup();
banner();
option = 0;
amount = 0;
while (true) {
while (true) {
while (true) {
while (true) {
menu();
__isoc99_scanf("%d", &option);
printf("\nHow many do you want?\n\n>> ");
__isoc99_scanf("%d", &amount);
if (0 < amount) break;
printf("%s\n[-] You cannot buy less than 1!\n", &DAT_0010134a);
}
pumpcoins = pumpcoins - amount * (short) *(undefined4 *) ((long) &values + (long) (int) option * 4);
if (-1 < pumpcoins) break;
printf("\nCurrent pumpcoins: [%s%d%s]\n\n", &DAT_00100e80, (ulong) (uint) (int) pumpcoins);
printf("%s\n[-] Not enough pumpcoins for this!\n\n%s", &DAT_0010134a, &DAT_00100e78);
}
if (option != 1) break;
printf("\nCurrent pumpcoins: [%s%d%s]\n\n", &DAT_00100e80, (ulong) (uint) (int)pumpcoins);
puts("\nGood luck crafting this huge pumpkin with a shovel!\n");
}
if (9998 < pumpcoins) break;
printf("%s\n[-] Not enough pumpcoins for this!\n\n%s", &DAT_0010134a, &DAT_00100e78);
}
local_48 = 0;
local_40 = 0;
local_38 = 0;
local_30 = 0;
local_28 = 0;
local_20 = 0;
fp = fopen("./flag.txt", "rb");
if (fp != NULL) {
fgets((char *) &local_48, 0x30, fp);
printf("%s\nCongratulations, here is the code to get your laser:\n\n%s\n\n", &DAT_00100ee3, &local_48);
/* WARNING: Subroutine does not return */
exit(0x16);
}
puts("Error opening flag.txt, please contact an Administrator!\n");
/* WARNING: Subroutine does not return */
exit(1);
}
Basically, the program provides this menu:
$ nc 134.122.106.203 32141
##&
(#&&
##&&
,*. #%%& .*,
.&@@@@#@@@&@@@@@@@@@@@@&@@&@#@@@@@@(
/@@@@&@&@@@@@@@@@&&&&&&&@@@@@@@@@@@&@@@@,
@@@@@@@@@@@@@&@&&&&&&&&&&&&&@&@@@@@@&@@@@@@
#&@@@@@@@@@@@@@@&&&&&&&&&&&&&&@@@@@@@@@@@@@@,
.@@@@@#@@@@@@@@#&&&&&&&&&&&&&&&&@@@@@@@@@@@@@&
&@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&&@@@@@@@@@&@@@@@
@@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@@
.@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@
(@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@.
@@@@@@@@@@@@@@&&&&&&&&&&&&&&&@@@@@@@@@@@@@@
,@@@@@@@@@@@@@&&&&&&&&&&&&&@@@@@@@@@@@@@
@@@@@@@@@@@@@&&&&&&&&&@@@@@@@@@@@@/
Current pumpcoins: [1337]
Items:
1. Shovel (1337 p.c.)
2. Laser (9999 p.c.)
>>
We see that we have 1337 pumpcoins. To find the flag, we need to earn at least 9999 pumpcoins.
Spotting the vulnerability
The vulnerability is in these lines of code:
// ...
menu();
__isoc99_scanf("%d", &option);
printf("\nHow many do you want?\n\n>> ");
__isoc99_scanf("%d", &amount);
if (0 < amount) break;
printf("%s\n[-] You cannot buy less than 1!\n", &DAT_0010134a);
}
pumpcoins = pumpcoins - amount * (short) *(undefined4 *) ((long) &values + (long) (int) option * 4);
// ...
Notice that all variables are type short
(pumpcoins
, option
and amount
), that is 2-byte variables. This is the balance update formula: pumpcoins = pumpcoins - amount * option * 4
.
We are not able to enter negative values for amount
, but we are allowed for option
. Therefore, we can find such values that will result in more than 9999 pumpcoins. This is called Integer Overflow vulnerability, since large negative values wrap around and convert into positive values.
Flag
This way we can get the flag:
$ nc 134.122.106.203 32141
##&
(#&&
##&&
,*. #%%& .*,
.&@@@@#@@@&@@@@@@@@@@@@&@@&@#@@@@@@(
/@@@@&@&@@@@@@@@@&&&&&&&@@@@@@@@@@@&@@@@,
@@@@@@@@@@@@@&@&&&&&&&&&&&&&@&@@@@@@&@@@@@@
#&@@@@@@@@@@@@@@&&&&&&&&&&&&&&@@@@@@@@@@@@@@,
.@@@@@#@@@@@@@@#&&&&&&&&&&&&&&&&@@@@@@@@@@@@@&
&@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&&@@@@@@@@@&@@@@@
@@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@@
.@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@
(@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@.
@@@@@@@@@@@@@@&&&&&&&&&&&&&&&@@@@@@@@@@@@@@
,@@@@@@@@@@@@@&&&&&&&&&&&&&@@@@@@@@@@@@@
@@@@@@@@@@@@@&&&&&&&&&@@@@@@@@@@@@/
Current pumpcoins: [1337]
Items:
1. Shovel (1337 p.c.)
2. Laser (9999 p.c.)
>> -1
How many do you want?
>> 2
Congratulations, here is the code to get your laser:
HTB{1nt3g3R_0v3rfl0w_101_0r_0v3R_9000!}