FCSC 2020 - Intro - Tarte Tatin

Table des matières :

Votre mission : trouver le mot de passe qui affiche le flag.

SHA256(TarteTatin) = 16697d877a69f2d06f286e32a0c1e8fc01eff25c366ef200eee47cc5ab81f96e

Résolution

Tout d’abord testons un peu notre binaire pour comprendre ce qu’il fait.

bash$ ./TarteTatin
TestString

Il n’y a pas de sortie. Procédons maintenant au désassemblage.

Désassemblage

Commençons par regarder la fonction main :

gdb-peda$ file TarteTatin
gdb-peda$ disas main
Dump of assembler code for function main:
   0x00005555555547a4 <+0>:   push   rbp
   0x00005555555547a5 <+1>:   mov    rbp,rsp
   0x00005555555547a8 <+4>:   sub    rsp,0x30
   0x00005555555547ac <+8>:   mov    rax,QWORD PTR fs:0x28
   0x00005555555547b5 <+17>:  mov    QWORD PTR [rbp-0x8],rax
   0x00005555555547b9 <+21>:  xor    eax,eax
   0x00005555555547bb <+23>:  mov    rdx,QWORD PTR [rip+0x2008ce] # 0x555555755090 <stdin@@GLIBC_2.2.5>
   0x00005555555547c2 <+30>:  lea    rax,[rbp-0x30]
   0x00005555555547c6 <+34>:  mov    esi,0x20
   0x00005555555547cb <+39>:  mov    rdi,rax
   0x00005555555547ce <+42>:  call   0x555555554650 <fgets@plt>
   0x00005555555547d3 <+47>:  lea    rax,[rbp-0x30]
   0x00005555555547d7 <+51>:  mov    rdi,rax
   0x00005555555547da <+54>:  call   0x55555555477a <transform>
   0x00005555555547df <+59>:  lea    rax,[rbp-0x30]
   0x00005555555547e3 <+63>:  mov    edx,0x10
   0x00005555555547e8 <+68>:  lea    rsi,[rip+0x200891]        # 0x555555755080 <pass_enc>
   0x00005555555547ef <+75>:  mov    rdi,rax
   0x00005555555547f2 <+78>:  call   0x555555554640 <memcmp@plt>
   0x00005555555547f7 <+83>:  test   eax,eax
   0x00005555555547f9 <+85>:  jne    0x55555555481a <main+118>
   0x00005555555547fb <+87>:  lea    rdi,[rip+0x20081e]        # 0x555555755020 <flag_enc>
   0x0000555555554802 <+94>:  call   0x55555555477a <transform>
   0x0000555555554807 <+99>:  lea    rdi,[rip+0x200812]        # 0x555555755020 <flag_enc>
   0x000055555555480e <+106>: call   0x555555554620 <puts@plt>
   0x0000555555554813 <+111>: mov    eax,0x1
   0x0000555555554818 <+116>: jmp    0x55555555481f <main+123>
   0x000055555555481a <+118>: mov    eax,0x0
   0x000055555555481f <+123>: mov    rcx,QWORD PTR [rbp-0x8]
   0x0000555555554823 <+127>: xor    rcx,QWORD PTR fs:0x28
   0x000055555555482c <+136>: je     0x555555554833 <main+143>
   0x000055555555482e <+138>: call   0x555555554630 <__stack_chk_fail@plt>
   0x0000555555554833 <+143>: leave  
   0x0000555555554834 <+144>: ret    
End of assembler dump.
gdb-peda$

Nous allons placer un breakpoint juste après la sortie de la fonction transform pour comprendre ce qu’elle fait :

   0x00005555555547d7 <+51>:	mov    rdi,rax
   0x00005555555547da <+54>:	call   0x55555555477a <transform>
=> 0x00005555555547df <+59>:	lea    rax,[rbp-0x30]
   0x00005555555547e3 <+63>:  mov    edx,0x10

Plaçons donc le breakpoint à l’adresse 0x00005555555547df :

gdb-peda$ breakpoint * 0x00005555555547df

Nous allons également placer un breakpoint juste avant l’appel à la fonction <memcmp@plt> pour regarder le contenu des zones mémoire qui vont être comparées. La fonction memcmp compare les données pointées par les adresses mémoire stockées dans les registres RSI et RDI. Nous voyons que les données à comparer sont chargées juste avant l’appel à memcmp dans les registres RSI et RDI.

   0x5555555547e8 <main+68>:	lea    rsi,[rip+0x200891]        # 0x555555755080 <pass_enc>
=> 0x5555555547ef <main+75>:	mov    rdi,rax
   0x5555555547f2 <main+78>:	call   0x555555554640 <memcmp@plt>

Plaçons donc le breakpoint à l’adresse 0x00005555555547ef :

gdb-peda$ breakpoint * 0x00005555555547ef

Maintenant nous allons lancer le programme dans GDB. Tapez la commande run, puis le programme se lance. Nous n’avons pas encore atteint de breakpoint donc le programme TarteTatin attend l’entrée utilisateur. Entrez un string que vous reconnaitrez en mémoire, par exemple ViveLesCrepes puis tapez entrée.

Nous avons atteint ici le premier breakpoint à l’adresse 0x00005555555547df situé après le retour de la fonction transform. La sortie de la fonction transform, située dans le regsitre RSI, est WjwfMftDsfqft. Nous pouvons aisément remarquer que chaque lettre de notre entrée transformée WjwfMftDsfqft est la lettre située juste après la lettre originale de notre entrée. En effet :

V => W
i => j
v => w
e => f
L => M
e => f
s => t
C => D
r => s
e => f
p => q
e => f
s => t

Continuons maintenant l’exécution du programme. Pour cela tapez continue pour continuer l’exécution jusqu’au prochain breakpoint.

Nous avons atteint ici le second breakpoint à l’adresse 0x00005555555547ef situé juste avant l’appel à la fonction <memcmp@plt>. Affichons donc le contenu des registres RSI et RDI :

gdb-peda$ x/s $rdi
0x7fffffffde80:	"WjwfMftDsfqft\v"

gdb-peda$ x/s $rsi
0x555555755080 <pass_enc>:	"NzTfdvs4Q4ttx1se"

Le registre rdi contient notre entrée utilisateur, et le registre rsi, contient le mot de passe encodé pass_enc dont la valeur est NzTfdvs4Q4ttx1se.

Nous écrivons un petit script python pour enlever 1 à chaque code caractère du pass_enc :

pass_enc = "NzTfdvs4Q4ttx1se"

pass_dec = ""
for c in pass_enc:
    pass_dec += chr(ord(c) - 1)

print('[+] pass_dec :',pass_dec)

Pour les habitués du python, la syntaxe des “list comprehensions” est plus rapide je trouve :

pass_enc = "NzTfdvs4Q4ttx1se"
pass_dec = ''.join([chr(ord(c) - 1) for c in pass_enc])
print('[+] pass_dec :',pass_dec)

Nous obtenons le mot de passe MySecur3P3ssw0rd, essayons le en entrée du binaire :

bash$ ./TarteTatin
MySecur3P3ssw0rd
Well done! The flag is: FCSC{83f41431c111062d003dd0213cf824d66f770a0be1305e2813f15dd76503a91d}

Le flag est FCSC{83f41431c111062d003dd0213cf824d66f770a0be1305e2813f15dd76503a91d}

BONUS - La technique forensics-like (Pour ceux qui n’aiment pas le désassemblage)

Nous allons extraire les strings présents dans le binaire :

bash$ strings -a TarteTatin
...
EBRBz72e30320b000/51c//2cc/102be713c55e66/`/ad02/4d1702e04cc654/2`80c|
NzTfdvs4Q4ttx1seGCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
...
transform
main
flag_enc
pass_enc
...

Un des strings attire l’oeil pour deux raisons, il est long, et il commence par EBRB :

EBRBz72e30320b000/51c//2cc/102be713c55e66/`/ad02/4d1702e04cc654/2`80c|

Les lettres EBRB sont les lettres juste avant les lettres de FCSC. Essayons donc d’enlever 1 aux codes caractères de ce string :

$ python3
Python 3.6.9 [GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> flag_enc = "EBRBz72e30320b000/51c//2cc/102be713c55e66/`/ad02/4d1702e04cc654/2`80c|"
>>> flag_dec = ''.join([chr(ord(c)+1) for c in flag_enc])
>>> print(flag_dec)
FCSC{83f41431c111062d003dd0213cf824d66f770a0be1305e2813f15dd76503a91d}
>>>

Et voilà nous avons le flag sans désassembler de binaire !

Le flag est FCSC{83f41431c111062d003dd0213cf824d66f770a0be1305e2813f15dd76503a91d}