Cyber Apocalypse 2023
Shattered Tablet
Solved by Starry-Lord
This challenge gave an ELF file so after basic identification, I tried to run it. When you run the file the tablet asks for an input and returns “no, not that”:
I decided to fire up ghidra, hopefully looking for what the expected input could be, what it would be compared against or anything relevant. Sure enough, by checking the main function, I found this code “explicitly” showing it was expecting the flag as input.
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_30._7_1_ == 'p') && (local_48._1_1_ == 'T')) && (local_48._7_1_ == 'k')) &&
((local_28._4_1_ == 'd' && (local_40._3_1_ == '4')))) &&
((local_38._4_1_ == 'e' && ((local_40._2_1_ == '_' && ((char)local_48 == 'H')))))) &&
(local_28._2_1_ == 'r')) &&
((((local_28._3_1_ == '3' && (local_30._1_1_ == '_')) && (local_48._2_1_ == 'B')) &&
(((local_30._5_1_ == 'r' && (local_48._3_1_ == '{')) &&
((local_30._2_1_ == 'b' && ((local_48._5_1_ == 'r' && (local_40._5_1_ == '4')))))))))) &&
(((local_30._6_1_ == '3' &&
(((local_38._3_1_ == 'v' && (local_40._4_1_ == 'p')) && (local_28._1_1_ == '1')))) &&
(((local_30._3_1_ == '3' && (local_38._1_1_ == 'n')) &&
(((local_48._4_1_ == 'b' && (((char)local_28 == '4' && (local_40._1_1_ == 'n')))) &&
((char)local_38 == ',')))))))) &&
((((((((char)local_40 == '3' && (local_48._6_1_ == '0')) && (local_38._7_1_ == 't')) &&
((local_40._7_1_ == 't' && ((char)local_30 == '0')))) &&
((local_40._6_1_ == 'r' && ((local_28._5_1_ == '}' && (local_38._5_1_ == 'r')))))) &&
(local_38._6_1_ == '_')) && ((local_38._2_1_ == '3' && (local_30._4_1_ == '_')))))) {
puts("Yes! That\'s right!");
}
else {
puts("No... not that");
}
return 0;
}
From this code we can understand that chars get reassembled following the order of the undefined8 locals to form the flag. It starts at ((char)local_48 == ‘H’) and local_28.5_1 == ‘}’ is where it ends, so after a bit of tidying we could retrieve the following string:
HTB{br0k3n_4p4rt,n3ver_t0_b3_r3p41r3d}
((char)local_48 == 'H')
(local_48._1_1_ == 'T'))
(local_48._2_1_ == 'B'))
(local_48._3_1_ == '{'))
local_48._4_1_ == 'b'
((local_48._5_1_ == 'r'
(local_48._6_1_ == '0'))
(local_48._7_1_ == 'k'))
...