Solution de botanicmagic pour Password Manager

intro reverse linux x86/x64

19 janvier 2025

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.