Solution de timruff pour Tarte Tatin

intro reverse linux x86/x64

24 mars 2026

Table des matières

Contexte

On doit retrouver un mot de passe et on a un fichier qui s’appelle “TarteTaTin”.

Analyse

$ file TarteTatin 
TarteTatin: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=847e4e7a7a412e8815994c665c5208c71b0f1836, not stripped
$ chmod +x ./TarteTatin 
$ ./TarteTatin 
mot de passe     

On regarde quel type de fichier c’est avec la commande “file”, on voit que le fichier est un binaire ELF 64bit pour architecture x86-64 pour GNU/Linux.
On le rend exécutable avec la commande “chmod +x”.
On exécute le binaire et on saisit le un mot de passe, il ne se passe rien.

bool main(void) 

{
  int iVar1;
  long in_FS_OFFSET;
  char local_38 [40];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  fgets(local_38,0x20,stdin);
  transform(local_38);
  iVar1 = memcmp(local_38,&pass_enc,0x10);
  if (iVar1 == 0) {
    transform(&flag_enc);
    puts((char *)&flag_enc);
  }
  if (local_10 == *(long *)(in_FS_OFFSET + 0x28)) {
    return iVar1 == 0;
  }
                    /* WARNING: Subroutine does not return */
  __stack_chk_fail();
}

On va regarder le code source décompilé de la fonction “main” avec Ghidra.

fgets(local_38,0x20,stdin);
transform(local_38);

Ici on a la saisie du mot de passe avec fgets et on remarque que la taille maximale du mot de passe est de 32 (0x20) octets.
On rentre dans une fonction de nom “transform”, qui prend comme arguments notre mot de passe.

void transform(char *param_1)

{
  char *pcVar1;
  char *local_10;
  
  local_10 = param_1;
  do {
    pcVar1 = local_10 + 1;
    *local_10 = *local_10 + '\x01';
    local_10 = pcVar1;
  } while (*pcVar1 != '\0');
  return;
}

Voici la fonction “transform” décompilée analysons là.
Cette fonction fait une boucle “do while”, jusqu’au caractère fin de chaîne de notre saisie ‘\0’.
Dans cette boucle on parcourt chaque caractère de la chaîne et on incrémente de 1 chaque caractère. Une fois la boucle terminée on retourne la chaîne modifiée. Pour retrouver le résultat inverse il suffit juste de décrémenter de 1 chaque caractère.

iVar1 = memcmp(local_38,&pass_enc,0x10);

On retourne dans notre fonction main.
On va comparer la saisie qui a été transformée avec un mot de passe encodé.
On remarque que la comparaison de chaîne se fait sur 16 (0x10) caractères.
Regardons le mot de passe encodé.

                             pass_enc                                        XREF[2]:     Entry Point(*), main:001007e8(*)  
        00301080 4e              db         4Eh
        00301081 7a              ??         7Ah    z
        00301082 54              ??         54h    T
        00301083 66              ??         66h    f
        00301084 64              ??         64h    d
        00301085 76              ??         76h    v
        00301086 73              ??         73h    s
        00301087 34              ??         34h    4
        00301088 51              ??         51h    Q
        00301089 34              ??         34h    4
        0030108a 74              ??         74h    t
        0030108b 74              ??         74h    t
        0030108c 78              ??         78h    x
        0030108d 31              ??         31h    1
        0030108e 73              ??         73h    s
        0030108f 65              ??         65h    e

On a le mot de passe encodé en hexadécimal on peut maintenant le décoder.

Solution

# Données chiffrées (valeurs hexadécimales)
pass_enc = [
    0x4e, 0x7a, 0x54, 0x66, 0x64, 0x76, 0x73, 0x34,
    0x51, 0x34, 0x74, 0x74, 0x78, 0x31, 0x73, 0x65
]

# Décodage : chaque valeur est un code ASCII, on soustrait 1 pour retrouver le caractère original
decoded_chars = []
for valeur in pass_enc:
    code_original = valeur - 1
    caractere = chr(code_original)
    decoded_chars.append(caractere)

# Construction de la chaîne finale
mot_de_passe = ''.join(decoded_chars)

# Affichage du résultat
print(mot_de_passe)

On écrit le programme qui soustrait de 1 sur chaque caractère sur le mot de passe encodé.

$ python3 ./decode.py 
MySecur3P3ssw0rd
$ ./TarteTatin 
MySecur3P3ssw0rd
Well done! The flag is: FCSC{XXX}