Solution de botanicmagic pour Tarte Tatin

intro reverse linux x86/x64

3 janvier 2025

J’ai utilisé Hopper Disassembler pour résoudre ce challenge.

Dans la fenêtre “labels”, figurent 2 références intéressantes :

0x201020 flag_enc
0x201080 pass_enc

On a alors :

                                      flag_enc:
0x0000000000201020                        db  0x56 ; 'V'                        ; DATA XREF=main+87, main+99
0x0000000000201021                        db  0x64 ; 'd'
0x0000000000201022                        db  0x6b ; 'k'
0x0000000000201023                        db  0x6b ; 'k'
0x0000000000201024                        db  0x1f ; '.'
0x0000000000201025                        db  0x63 ; 'c'
0x0000000000201026                        db  0x6e ; 'n'
0x0000000000201027                        db  0x6d ; 'm'
0x0000000000201028                        db  0x64 ; 'd'
0x0000000000201029                        db  0x20 ; ' '
0x000000000020102a                        db  0x1f ; '.'
0x000000000020102b                        db  0x53 ; 'S'
0x000000000020102c                        db  0x67 ; 'g'
0x000000000020102d                        db  0x64 ; 'd'
0x000000000020102e                        db  0x1f ; '.'
0x000000000020102f                        db  0x65 ; 'e'
0x0000000000201030                        db  0x6b ; 'k'
0x0000000000201031                        db  0x60 ; '`'
0x0000000000201032                        db  0x66 ; 'f'
0x0000000000201033                        db  0x1f ; '.'
0x0000000000201034                        db  0x68 ; 'h'
0x0000000000201035                        db  0x72 ; 'r'
0x0000000000201036                        db  0x39 ; '9'
0x0000000000201037                        db  0x1f ; '.'
0x0000000000201038                        db  0x45 ; 'E'
0x0000000000201039                        db  0x42 ; 'B'
0x000000000020103a                        db  0x52 ; 'R'
0x000000000020103b                        db  0x42 ; 'B'
0x000000000020103c                        db  0x7a ; 'z'
0x000000000020103d                        db  0x37 ; '7'
0x000000000020103e                        db  0x32 ; '2'
0x000000000020103f                        db  0x65 ; 'e'
0x0000000000201040                        db  0x33 ; '3'
0x0000000000201041                        db  0x30 ; '0'
0x0000000000201042                        db  0x33 ; '3'
0x0000000000201043                        db  0x32 ; '2'
0x0000000000201044                        db  0x30 ; '0'
0x0000000000201045                        db  0x62 ; 'b'
0x0000000000201046                        db  0x30 ; '0'
0x0000000000201047                        db  0x30 ; '0'
0x0000000000201048                        db  0x30 ; '0'
0x0000000000201049                        db  0x2f ; '/'
0x000000000020104a                        db  0x35 ; '5'
0x000000000020104b                        db  0x31 ; '1'
0x000000000020104c                        db  0x63 ; 'c'
0x000000000020104d                        db  0x2f ; '/'
0x000000000020104e                        db  0x2f ; '/'
0x000000000020104f                        db  0x32 ; '2'
0x0000000000201050                        db  0x63 ; 'c'
0x0000000000201051                        db  0x63 ; 'c'
0x0000000000201052                        db  0x2f ; '/'
0x0000000000201053                        db  0x31 ; '1'
0x0000000000201054                        db  0x30 ; '0'
0x0000000000201055                        db  0x32 ; '2'
0x0000000000201056                        db  0x62 ; 'b'
0x0000000000201057                        db  0x65 ; 'e'
0x0000000000201058                        db  0x37 ; '7'
0x0000000000201059                        db  0x31 ; '1'
0x000000000020105a                        db  0x33 ; '3'
0x000000000020105b                        db  0x63 ; 'c'
0x000000000020105c                        db  0x35 ; '5'
0x000000000020105d                        db  0x35 ; '5'
0x000000000020105e                        db  0x65 ; 'e'
0x000000000020105f                        db  0x36 ; '6'
0x0000000000201060                        db  0x36 ; '6'
0x0000000000201061                        db  0x2f ; '/'
0x0000000000201062                        db  0x60 ; '`'
0x0000000000201063                        db  0x2f ; '/'
0x0000000000201064                        db  0x61 ; 'a'
0x0000000000201065                        db  0x64 ; 'd'
0x0000000000201066                        db  0x30 ; '0'
0x0000000000201067                        db  0x32 ; '2'
0x0000000000201068                        db  0x2f ; '/'
0x0000000000201069                        db  0x34 ; '4'
0x000000000020106a                        db  0x64 ; 'd'
0x000000000020106b                        db  0x31 ; '1'
0x000000000020106c                        db  0x37 ; '7'
0x000000000020106d                        db  0x30 ; '0'
0x000000000020106e                        db  0x32 ; '2'
0x000000000020106f                        db  0x65 ; 'e'
0x0000000000201070                        db  0x30 ; '0'
0x0000000000201071                        db  0x34 ; '4'
0x0000000000201072                        db  0x63 ; 'c'
0x0000000000201073                        db  0x63 ; 'c'
0x0000000000201074                        db  0x36 ; '6'
0x0000000000201075                        db  0x35 ; '5'
0x0000000000201076                        db  0x34 ; '4'
0x0000000000201077                        db  0x2f ; '/'
0x0000000000201078                        db  0x32 ; '2'
0x0000000000201079                        db  0x60 ; '`'
0x000000000020107a                        db  0x38 ; '8'
0x000000000020107b                        db  0x30 ; '0'
0x000000000020107c                        db  0x63 ; 'c'
0x000000000020107d                        db  0x7c ; '|'
0x000000000020107e                        db  0x00 ; '.'
0x000000000020107f                        db  0x00 ; '.'
                                      pass_enc:
0x0000000000201080                        db  0x4e ; 'N'                        ; DATA XREF=main+68
0x0000000000201081                        db  0x7a ; 'z'
0x0000000000201082                        db  0x54 ; 'T'
0x0000000000201083                        db  0x66 ; 'f'
0x0000000000201084                        db  0x64 ; 'd'
0x0000000000201085                        db  0x76 ; 'v'
0x0000000000201086                        db  0x73 ; 's'
0x0000000000201087                        db  0x34 ; '4'
0x0000000000201088                        db  0x51 ; 'Q'
0x0000000000201089                        db  0x34 ; '4'
0x000000000020108a                        db  0x74 ; 't'
0x000000000020108b                        db  0x74 ; 't'
0x000000000020108c                        db  0x78 ; 'x'
0x000000000020108d                        db  0x31 ; '1'
0x000000000020108e                        db  0x73 ; 's'
0x000000000020108f                        db  0x65 ; 'e'

Et donc une référence dans la fonction main :

int main() {
    var_8 = *0x28;
    // Récupère la string var_30
    fgets(&var_30, 0x20, *__TMC_END__);
    // transforme la chaine
    transform(&var_30);
    // compare la chaîne utilisateur avec le bon mot de passe (pass_enc)
    rax = memcmp(&var_30, pass_enc, 0x10);
    // si elles sont identiques
    if (rax == 0x0) {
            // transforme la chaîne flag_enc
            transform(flag_enc);
            // affichage de la chaîne flag_enc transformée
            puts(flag_enc);
            rax = 0x1;
    }
    else {
            rax = 0x0;
    }
    rcx = var_8 ^ *0x28;
    if (rcx != 0x0) {
            __stack_chk_fail();
    }
    return rax;
}

Donc le flag est affiché si l’entrée utilisateur est conforme au mot de passe. Voici la fonction transform :

int transform(void * ) {
    var_8 = arg_0;
    // Parcours la chaine jusqu'à la fin (0x00)
    do {
            rax = var_8;
            // incrémente la position dans la chaine 
            var_8 = rax + 0x1;
            // transforme le caractère actuel (position rax)
            // stocke à la même position la valeur ordinale du caractère +1 
            // Ex : si c'est "A" (65), on stockera "B" (66)
            *(int8_t *)rax = (*(int8_t *)rax & 0xff) + 0x1;
            // caractère suivant pour test de sortie de boucle
            rax = *(int8_t *)var_8 & 0xff;
    } while (rax != 0x0);
    return rax;
}

Ce code en Python donne :

def transform(thestring):
    return ''.join(chr(x + 1) for x in thestring)

Si on l’applique à flag_enc :

# Chaîne codée
flag_enc = [
    0x56, 0x64, 0x6B, 0x6B, 0x1F, 0x63, 0x6E, 0x6D, 0x64, 0x20, 0x1F, 0x53,
    0x67, 0x64, 0x1F, 0x65, 0x6B, 0x60, 0x66, 0x1F, 0x68, 0x72, 0x39, 0x1F,
    0x45, 0x42, 0x52, 0x42, 0x7A, 0x37, 0x32, 0x65, 0x33, 0x30, 0x33, 0x32,
    0x30, 0x62, 0x30, 0x30, 0x30, 0x2F, 0x35, 0x31, 0x63, 0x2F, 0x2F, 0x32,
    0x63, 0x63, 0x2F, 0x31, 0x30, 0x32, 0x62, 0x65, 0x37, 0x31, 0x33, 0x63,
    0x35, 0x35, 0x65, 0x36, 0x36, 0x2F, 0x60, 0x2F, 0x61, 0x64, 0x30, 0x32,
    0x2F, 0x34, 0x64, 0x31, 0x37, 0x30, 0x32, 0x65, 0x30, 0x34, 0x63, 0x63,
    0x36, 0x35, 0x34, 0x2F, 0x32, 0x60, 0x38, 0x30, 0x63, 0x7C ]

# Décodage
def transform(thestring):
    return ''.join(chr(x + 1) for x in thestring)

print(f"{transform(flag_enc)}")

Cela donne :

Well done! The flag is: FCSC{83f41431c111062d003dd0213cf824d66f770a0be1305e2813f15dd76503a91d}

On peut trouver le mot de passe en inversant la méthode transform :

# Chaîne codée (Vive Canal)
pass_enc = [0x4e, 0x7a, 0x54, 0x66, 0x64, 0x76, 0x73, 0x34, 0x51, 0x34, 0x74, 0x74, 0x78, 0x31, 0x73, 0x65]
# Décodage
decoded = ''.join(chr(x - 1) for x in pass_enc)
print(f"{decoded}")

Cela donne :

MySecur3P3ssw0rd