Nous utilisons Cutter pour ce challenge.
Une fois dans GDB, il faut ajouter un breakpoint sur la fonction main
:
(gdb) b main
Breakpoint 1 at 0x1169
puis on lance le programme :
(gdb) run
Starting program: /app/password-manager
Breakpoint 1, 0x000055f840ab1169 in main ()
Ensuite, on désassemble la fonction main
:
(gdb) disassemble main
Dump of assembler code for function main:
0x000055f840ab1165 <+0>: push %rbp
0x000055f840ab1166 <+1>: mov %rsp,%rbp
=> 0x000055f840ab1169 <+4>: sub $0x4b0,%rsp
0x000055f840ab1170 <+11>: movabs $0x491e1e4f4f194b1f,%rax # Séquence 0x491e1e4f4f194b1f
0x000055f840ab117a <+21>: movabs $0x4e481c1d4e191c1d,%rdx # Séquence 0x4e481c1d4e191c1d
0x000055f840ab1184 <+31>: mov %rax,-0x460(%rbp)
0x000055f840ab118b <+38>: mov %rdx,-0x458(%rbp)
0x000055f840ab1192 <+45>: movabs $0x4e12484f1818181a,%rax # Séquence 0x4e12484f1818181a
0x000055f840ab119c <+55>: movabs $0x4b1f491f1c181348,%rdx # Séquence 0x4b1f491f1c181348
0x000055f840ab11a6 <+65>: mov %rax,-0x450(%rbp)
0x000055f840ab11ad <+72>: mov %rdx,-0x448(%rbp)
0x000055f840ab11b4 <+79>: movabs $0x184c18131f1a1b1a,%rax # Séquence 0x184c18131f1a1b1a
0x000055f840ab11be <+89>: movabs $0x1b1b194b4b1e4e1e,%rdx # Séquence 0x1b1b194b4b1e4e1e
0x000055f840ab11c8 <+99>: mov %rax,-0x440(%rbp)
0x000055f840ab11cf <+106>: mov %rdx,-0x438(%rbp)
0x000055f840ab11d6 <+113>: movabs $0x4c1f49181d4b1f48,%rax # Séquence 0x4c1f49181d4b1f48
0x000055f840ab11e0 <+123>: movabs $0x131f4819131c4e1f,%rdx # Séquence 0x131f4819131c4e1f
0x000055f840ab11ea <+133>: mov %rax,-0x430(%rbp)
0x000055f840ab11f1 <+140>: mov %rdx,-0x428(%rbp)
0x000055f840ab11f8 <+147>: movl $0x5e525e04,-0x420(%rbp) # Séquence 0x5e525e04
0x000055f840ab1202 <+157>: movq $0x0,-0x4b0(%rbp)
0x000055f840ab120d <+168>: movq $0x0,-0x4a8(%rbp)
0x000055f840ab1218 <+179>: movq $0x0,-0x4a0(%rbp)
0x000055f840ab1223 <+190>: movq $0x0,-0x498(%rbp)
0x000055f840ab122e <+201>: movq $0x0,-0x490(%rbp)
0x000055f840ab1239 <+212>: movq $0x0,-0x488(%rbp)
0x000055f840ab1244 <+223>: movq $0x0,-0x480(%rbp)
0x000055f840ab124f <+234>: movq $0x0,-0x478(%rbp)
0x000055f840ab125a <+245>: movl $0x0,-0x470(%rbp)
0x000055f840ab1264 <+255>: movb $0x0,-0x46c(%rbp)
0x000055f840ab126b <+262>: lea 0xd96(%rip),%rdi # 0x55f840ab2008
0x000055f840ab1272 <+269>: call 0x55f840ab1030 <puts@plt> # affichage d'un message
0x000055f840ab1277 <+274>: mov 0x2dca(%rip),%rax # 0x55f840ab4048 <stdout@GLIBC_2.2.5>
0x000055f840ab127e <+281>: mov %rax,%rdi
0x000055f840ab1281 <+284>: call 0x55f840ab1050 <fflush@plt>
0x000055f840ab1286 <+289>: movl $0x0,-0x4(%rbp)
0x000055f840ab128d <+296>: jmp 0x55f840ab12b1 <main+332>
0x000055f840ab128f <+298>: mov -0x4(%rbp),%eax
0x000055f840ab1292 <+301>: cltq
0x000055f840ab1294 <+303>: movzbl -0x460(%rbp,%rax,1),%eax
0x000055f840ab129c <+311>: xor $0x2a,%eax # décode via XOR 0x2a sur chaque octet
0x000055f840ab129f <+314>: mov %eax,%edx
0x000055f840ab12a1 <+316>: mov -0x4(%rbp),%eax
0x000055f840ab12a4 <+319>: cltq
0x000055f840ab12a6 <+321>: mov %dl,-0x4b0(%rbp,%rax,1)
0x000055f840ab12ad <+328>: addl $0x1,-0x4(%rbp)
0x000055f840ab12b1 <+332>: cmpl $0x43,-0x4(%rbp) # taille
0x000055f840ab12b5 <+336>: jle 0x55f840ab128f <main+298> # tant qu'on n'est pas arrivé à la fin
0x000055f840ab12b7 <+338>: lea -0x4b0(%rbp),%rax # récupère la chaîne décodéé en rbp-0x4b0
0x000055f840ab12be <+345>: mov $0x0,%esi
0x000055f840ab12c3 <+350>: mov %rax,%rdi
0x000055f840ab12c6 <+353>: mov $0x0,%eax
0x000055f840ab12cb <+358>: call 0x55f840ab1060 <open@plt> # ouverture du fichier
0x000055f840ab12d0 <+363>: mov %eax,-0x8(%rbp)
0x000055f840ab12d3 <+366>: cmpl $0x0,-0x8(%rbp)
0x000055f840ab12d7 <+370>: jns 0x55f840ab12e5 <main+384>
0x000055f840ab12d9 <+372>: lea 0xd58(%rip),%rdi # 0x55f840ab2038
0x000055f840ab12e0 <+379>: call 0x55f840ab1030 <puts@plt> # affichage d'un message erreur si pbm
0x000055f840ab12e5 <+384>: lea -0x410(%rbp),%rcx
0x000055f840ab12ec <+391>: mov -0x8(%rbp),%eax
0x000055f840ab12ef <+394>: mov $0x80,%edx
0x000055f840ab12f4 <+399>: mov %rcx,%rsi
0x000055f840ab12f7 <+402>: mov %eax,%edi
0x000055f840ab12f9 <+404>: call 0x55f840ab1040 <read@plt> # lecture du fichier
0x000055f840ab12fe <+409>: mov %eax,-0xc(%rbp)
0x000055f840ab1301 <+412>: mov -0xc(%rbp),%eax
0x000055f840ab1304 <+415>: cltq
0x000055f840ab1306 <+417>: movq $0x0,-0x410(%rbp,%rax,8)
0x000055f840ab1312 <+429>: mov $0x0,%eax
0x000055f840ab1317 <+434>: leave
0x000055f840ab1318 <+435>: ret
End of assembler dump.
Donc, les séquences représentent un nom de fichier codé. Le nom est décodé octet par octet via une opération XOR 0x2a
. Le nom de fichier est stocké en rbp - 0x4b0
.
Pour avoir le nom du fichier décodé, on doit mettre un breakpoint à 0x000055f840ab12b7
:
(gdb) b *0x000055f840ab12b7
Breakpoint 2 at 0x55f840ab12b7
Puis on continue l’exécution du programme jusqu’à atteindre le 2ème breakpoint :
(gdb) continue
Continuing.
Welcome to my super secure password manager!
Breakpoint 2, 0x000055f840ab12b7 in main ()
Maintenant, pour avoir le nom du fichier, il faut afficher la mémoire en rbp - 0x4b0
:
(gdb) x/s ($rbp-0x4b0)
0x7ffe5b0af550: "5a3ee44c763d76bd0222eb8db9265c5a010592f24d4aa311b5a72c5f5d693b59.txt"
Nous avons maintenant le nom du fichier. Pour l’afficher :
(gdb) shell cat "5a3ee44c763d76bd0222eb8db9265c5a010592f24d4aa311b5a72c5f5d693b59.txt"
FCSC{da8ae129af8512620bc6c9a711392395fba426edc6713819c1baffe004024ff2}
Nous obtenons le flag.