Crushing
Catégorie: Reverse Difficulté: easy Flag: HTB{4_v3ry_b4d_compr3ss1on_sch3m3}
Challenge
Description
Crushing is an Easy reversing challenge. Players will reverse engineer a 'compression' algorithm, then write a script to recover the original message.
Analyse du code
Dans le main
, on voit que l’on initialise un tableau de 256 éléments, tous à 0.
Ensuite on rentre dans un while, tant que getchar()
ne retourne pas -1
alors on appelle la fonction add_to_char_map
avec notre tableau, le caracètre récupéré et le numéro du tour de boucle auquel nous somme.
On comprend donc par le nom de la fonction que notre tableau est une map à laquelle on va ajouter l’index de notre char
int main(void) {
long i;
undefined8 *key;
undefined8 char_map [256];
int c;
long index;
key = char_map;
for (i = 0xff; i != 0; i = i + -1) {
*key = 0;
key = key + 1;
}
index = 0;
while( true ) {
c = getchar();
if (c == -1) break;
add_char_to_map((long)char_map,(byte)c,index);
index = index + 1;
}
serialize_and_output((long)char_map);
return 0;
}
On peut le confirmer en regardant la fonction add_to_char_map
qui fait bien ce que l’on imaginait
void add_char_to_map(long char_map,byte c,undefined8 index) {
undefined8 *node;
long char_map_entry;
// Récupère la case du tableau en fonction du char passé en paramètre, en gros char_map[c]
char_map_entry = *(long *)(char_map + (ulong)c * 8);
// Créé un tableau de 2 items
node = (undefined8 *)malloc(0x10);
// Le premier item est l'index de notre char
*node = index;
// La seconde est initialisé à 0, ce sera la référence à notre prochaine node
node[1] = 0;
// Si notre char_map[c] est vide, on ajoute la réf de notre node dedans
if (char_map_entry == 0) {
*(undefined8 **)((ulong)c * 8 + char_map) = node;
}
// Sinon on parcours node après node (c'est une liste chainée) pour arriver jusqu'à la dernière
else {
for (; *(long *)(char_map_entry + 8) != 0; char_map_entry = *(long *)(char_map_entry + 8)) {
}
// On ajoute la réf de notre nouvelle node à la dernière node
*(undefined8 **)(char_map_entry + 8) = node;
}
return;
}
Enfin, la fonction serialize_and_output
qui va récupérer pour chaque key de notre map, sa valeur associé (c’est à dire la liste chainée d’index) et écrire pour chacun :
Le nombre d’index à lire ensuite
Tous les index
void serialize_and_output(long char_map) {
long nodes_count;
void **first_node;
void *index;
int i;
for (i = 0; i < 0xff; i = i + 1) {
// Récupère la première node de la liste chainée
first_node = (void **)(char_map + (long)i * 8);
// Compte le nombre de node chainée
nodes_count = list_len((long *)first_node);
// Ecrit ce nombre
fwrite(&nodes_count,8,1,stdout);
// Pour chaque node, écrit la valeur qu'elle contient (c'est à dire l'index du char)
for (index = *first_node; index != (void *)0x0; index = *(void **)((long)index + 8)) {
fwrite(index,8,1,stdout);
}
}
return;
}
Il faut tout de même souligner que toutes les valeurs sont écrite en sur 8 bytes. Donc il faut le prendre en compte pour ne pas se tromper pendant la déserialisation
Script de résolution
from struct import unpack
message = bytearray(1000)
with open('message.txt.cz', 'rb') as f:
for char_code in range(256):
try:
to_read = unpack('Q', f.read(8))[0]
except Exception:
break
for _ in range(to_read):
index = unpack('Q', f.read(8))[0]
message[index] = char_code
print(message.decode())
Organizer 1: Hey, did you finalize the password for the next... you know?
Organizer 2: Yeah, I did. It's "HTB{4_v3ry_b4d_compr3ss1on_sch3m3}"
Organizer 1: "HTB{4_v3ry_b4d_compr3ss1on_sch3m3}," got it. Sounds ominous enough to keep things interesting. Where do we spread the word?
Organizer 2: Let's stick to the usual channels: encrypted messages to the leaders and discreetly slip it into the training manuals for the participants.
Organizer 1: Perfect. And let's make sure it's not leaked this time. Last thing we need is an early bird getting the worm.
Organizer 2: Agreed. We can't afford any slip-ups, especially with the stakes so high. The anticipation leading up to it should be palpable.
Organizer 1: Absolutely. The thrill of the unknown is what keeps them coming back for more. "HTB{4_v3ry_b4d_compr3ss1on_sch3m3}" it is then.
Dernière mise à jour
Cet article vous a-t-il été utile ?