Shattered Tablet
4 minutos de lectura
Se nos proporciona un binario llamado tablet
:
$ file tablet
tablet: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=71ad3ff9f7e5fbf0edc75446337a0a68deb7ecd6, for GNU/Linux 3.2.0, not stripped
Descompilación
Si lo abrimos en Ghidra, veremos esta función main
:
/* WARNING: Could not reconcile some variable overlaps */
undefined8 main(void)
{
undefined8 local_48;
undefined8 local_40;
undefined8 local_38;
undefined8 local_30;
undefined8 local_28;
undefined8 local_20;
undefined8 local_18;
undefined8 local_10;
local_48 = 0;
local_40 = 0;
local_38 = 0;
local_30 = 0;
local_28 = 0;
local_20 = 0;
local_18 = 0;
local_10 = 0;
printf("Hmmmm... I think the tablet says: ");
fgets((char *)&local_48,0x40,stdin);
if (((((local_28._2_1_ == '4') && (local_38._4_1_ == '3')) && (local_28._4_1_ == 'r')) &&
((((local_48._1_1_ == 'T' && (local_38._5_1_ == 'v')) &&
((local_48._6_1_ == '0' && ((local_28._7_1_ == '}' && (local_28._6_1_ == 'd')))))) &&
(local_30._7_1_ == 'r')))) &&
((((((local_30._5_1_ == '3' && ((char)local_40 == '3')) && (local_38._6_1_ == 'e')) &&
((local_28._3_1_ == '1' && (local_48._5_1_ == 'r')))) &&
(((char)local_48 == 'H' && (((char)local_28 == '3' && (local_38._2_1_ == '.')))))) &&
(((((local_40._5_1_ == '4' &&
(((((local_48._3_1_ == '{' && (local_40._2_1_ == '_')) && ((char)local_38 == '.')) &&
((local_48._4_1_ == 'b' && (local_48._7_1_ == 'k')))) && (local_40._7_1_ == 't')))) &&
(((local_40._6_1_ == 'r' && (local_38._3_1_ == 'n')) &&
((local_30._1_1_ == 't' &&
(((local_38._1_1_ == '.' && (local_40._1_1_ == 'n')) && (local_30._6_1_ == '_')))))))) &&
(((local_30._2_1_ == '0' && ((char)local_30 == '_')) && (local_40._4_1_ == 'p')))) &&
((((local_38._7_1_ == 'r' && (local_30._4_1_ == 'b')) &&
((local_28._1_1_ == 'p' &&
(((local_48._2_1_ == 'B' && (local_30._3_1_ == '_')) && (local_40._3_1_ == '4')))))) &&
(local_28._5_1_ == '3')))))))) {
puts("Yes! That\'s right!");
}
else {
puts("No... not that");
}
return 0;
}
Parece un poco extraño, pero podemos decirle a Ghidra que local_48
es en realidad de tipo char[64]
y cambiar el nombre de la variable a data
(además, formatear un poco el código):
int main() {
char data[64];
data._0_8_ = 0;
data._8_8_ = 0;
data._16_8_ = 0;
data._24_8_ = 0;
data._32_8_ = 0;
data._40_8_ = 0;
data._48_8_ = 0;
data._56_8_ = 0;
printf("Hmmmm... I think the tablet says: ");
fgets(data, 0x40, stdin);
if (
(data[34] == '4') &&
(data[20] == '3') &&
(data[36] == 'r') &&
(data[1] == 'T') &&
(data[21] == 'v') &&
(data[6] == '0') &&
(data[39] == '}') &&
(data[38] == 'd') &&
(data[31] == 'r') &&
(data[29] == '3') &&
(data[8] == '3') &&
(data[22] == 'e') &&
(data[35] == '1') &&
(data[5] == 'r') &&
(data[0] == 'H') &&
(data[32] == '3') &&
(data[18] == '.') &&
(data[13] == '4') &&
(data[3] == '{') &&
(data[10] == '_') &&
(data[16] == '.') &&
(data[4] == 'b') &&
(data[7] == 'k') &&
(data[15] == 't') &&
(data[14] == 'r') &&
(data[19] == 'n') &&
(data[25] == 't') &&
(data[17] == '.') &&
(data[9] == 'n') &&
(data[30] == '_') &&
(data[26] == '0') &&
(data[24] == '_') &&
(data[12] == 'p') &&
(data[23] == 'r') &&
(data[28] == 'b') &&
(data[33] == 'p') &&
(data[2] == 'B') &&
(data[27] == '_') &&
(data[11] == '4') &&
(data[37] == '3')
) {
puts("Yes! That\'s right!");
} else {
puts("No... not that");
}
return 0;
}
Básicamente, el programa verifica cada carácter de la lista, así que podemos ordenar los caracteres y descubrir la string esperada:
(data[0] == 'H') &&
(data[1] == 'T') &&
(data[2] == 'B') &&
(data[3] == '{') &&
(data[4] == 'b') &&
(data[5] == 'r') &&
(data[6] == '0') &&
(data[7] == 'k') &&
(data[8] == '3') &&
(data[9] == 'n') &&
(data[10] == '_') &&
(data[11] == '4') &&
(data[12] == 'p') &&
(data[13] == '4') &&
(data[14] == 'r') &&
(data[15] == 't') &&
(data[16] == '.') &&
(data[17] == '.') &&
(data[18] == '.') &&
(data[19] == 'n') &&
(data[20] == '3') &&
(data[21] == 'v') &&
(data[22] == 'e') &&
(data[23] == 'r') &&
(data[24] == '_') &&
(data[25] == 't') &&
(data[26] == '0') &&
(data[27] == '_') &&
(data[28] == 'b') &&
(data[29] == '3') &&
(data[30] == '_') &&
(data[31] == 'r') &&
(data[32] == '3') &&
(data[33] == 'p') &&
(data[34] == '4') &&
(data[35] == '1') &&
(data[36] == 'r') &&
(data[37] == '3') &&
(data[38] == 'd') &&
(data[39] == '}')
Flag
Y aquí tenemos la flag:
HTB{br0k3n_4p4rt...n3ver_t0_b3_r3p41r3d}