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

We have an ELF and we have to find the flag.


First of all, let’s check a few things on the binary:

magnussen@funcMyLife:~/tartetatin$ ./TarteTatin test

magnussen@funcMyLife:~/tartetatin$ strings TarteTatin
NzTfdvs4Q4ttx1seGCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0

Ok, so no response from the program after the execution, there’s some interesting strings, but we don’t know how they’re generated, let’s check the binary.

magnussen@funcMyLife:~/tartetatin$ radare2 -d Tartetatin
Process with PID 673 started...
= attach 673 673
bin.baddr 0x559d5cbc5000
Using 0x559d5cbc5000
asm.bits 64
[0x7ff5fdea0090]> aaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze len bytes of instructions for references (aar)
[x] Analyze function calls (aac)
[x] Use -AA or aaaa to perform additional experimental analysis.
[x] Constructing a function name for fcn.* and sym.func.* functions (aan)
= attach 673 673
[0x7ff5fdea0090]> s main
[0x559d5cbc57a4]> pdf
            ;-- main:
/ (fcn) main 145
|   main ();
|           ; var int local_30h @ rbp-0x30
|           ; var int local_8h @ rbp-0x8
|              ; DATA XREF from 0x559d5cbc568d (entry0)
|           0x559d5cbc57a4      55             push rbp
|           0x559d5cbc57a5      4889e5         mov rbp, rsp
|           0x559d5cbc57a8      4883ec30       sub rsp, 0x30           ; '0'
|           0x559d5cbc57ac      64488b042528.  mov rax, qword fs:[0x28] ; [0x28:8]=-1 ; '(' ; 40
|           0x559d5cbc57b5      488945f8       mov qword [local_8h], rax
|           0x559d5cbc57b9      31c0           xor eax, eax
|           0x559d5cbc57bb      488b15ce0820.  mov rdx, qword [obj.stdin] ; loc.stdin ; [0x559d5cdc6090:8]=0
|           0x559d5cbc57c2      488d45d0       lea rax, qword [local_30h]
|           0x559d5cbc57c6      be20000000     mov esi, 0x20           ; 32
|           0x559d5cbc57cb      4889c7         mov rdi, rax
|           0x559d5cbc57ce      e87dfeffff     call sym.imp.fgets      ; char *fgets(char *s, int size, FILE *stream)
|           0x559d5cbc57d3      488d45d0       lea rax, qword [local_30h]
|           0x559d5cbc57d7      4889c7         mov rdi, rax
|           0x559d5cbc57da      e89bffffff     call sym.transform
|           0x559d5cbc57df      488d45d0       lea rax, qword [local_30h]
|           0x559d5cbc57e3      ba10000000     mov edx, 0x10           ; 16
|           0x559d5cbc57e8      488d35910820.  lea rsi, qword str.NzTfdvs4Q4ttx1se ; obj.pass_enc ; 0x559d5cdc6080 ; "NzTfdvs4Q4ttx1se"
|           0x559d5cbc57ef      4889c7         mov rdi, rax
|           0x559d5cbc57f2      e849feffff     call sym.imp.memcmp     ; int memcmp(const void *s1, const void *s2, size_t n)
|           0x559d5cbc57f7      85c0           test eax, eax
|       ,=< 0x559d5cbc57f9      751f           jne 0x559d5cbc581a
|       |   0x559d5cbc57fb      488d3d1e0820.  lea rdi, qword str.Vdkk ; obj.flag_enc ; 0x559d5cdc6020 ; "Vdkk\x1fcnmd \x1fSgd\x1fek`f\x1fhr9\x1fEBRBz72e30320b000/51c//2cc/102be713c55e66/`/ad02/4d1702e04cc654/2`80c|"
|       |   0x559d5cbc5802      e873ffffff     call sym.transform
|       |   0x559d5cbc5807      488d3d120820.  lea rdi, qword str.Vdkk ; obj.flag_enc ; 0x559d5cdc6020 ; "Vdkk\x1fcnmd \x1fSgd\x1fek`f\x1fhr9\x1fEBRBz72e30320b000/51c//2cc/102be713c55e66/`/ad02/4d1702e04cc654/2`80c|"
|       |   0x559d5cbc580e      e80dfeffff     call sym.imp.puts       ; int puts(const char *s)
|       |   0x559d5cbc5813      b801000000     mov eax, 1
|      ,==< 0x559d5cbc5818      eb05           jmp 0x559d5cbc581f
|      |`-> 0x559d5cbc581a      b800000000     mov eax, 0
|      |       ; JMP XREF from 0x559d5cbc5818 (main)
|      `--> 0x559d5cbc581f      488b4df8       mov rcx, qword [local_8h]
|           0x559d5cbc5823      6448330c2528.  xor rcx, qword fs:[0x28]
|       ,=< 0x559d5cbc582c      7405           je 0x559d5cbc5833
|       |   0x559d5cbc582e      e8fdfdffff     call sym.imp.__stack_chk_fail ; void __stack_chk_fail(void)
|       `-> 0x559d5cbc5833      c9             leave
\           0x559d5cbc5834      c3             ret

So there’s two interesting objects: obj.pass_enc & obj.flag_enc, and a function called transform.

So basically, the program takes an input, transforms it and compares it with pass_enc, if they matches, it transforms the flag_enc string and prints it.

Let’s see what the transform function does.

[0x559d5cbc57a4]> s sym.transform
[0x559d5cbc577a]> pdf
/ (fcn) sym.transform 42
|   sym.transform ();
|           ; var int local_8h @ rbp-0x8
|              ; CALL XREF from 0x559d5cbc57da (main)
|              ; CALL XREF from 0x559d5cbc5802 (main)
|           0x559d5cbc577a      55             push rbp
|           0x559d5cbc577b      4889e5         mov rbp, rsp
|           0x559d5cbc577e      48897df8       mov qword [local_8h], rdi
|       .-> 0x559d5cbc5782      488b45f8       mov rax, qword [local_8h]
|       :   0x559d5cbc5786      488d5001       lea rdx, qword [rax + 1] ; 1
|       :   0x559d5cbc578a      488955f8       mov qword [local_8h], rdx
|       :   0x559d5cbc578e      0fb610         movzx edx, byte [rax]
|       :   0x559d5cbc5791      83c201         add edx, 1
|       :   0x559d5cbc5794      8810           mov byte [rax], dl
|       :   0x559d5cbc5796      488b45f8       mov rax, qword [local_8h]
|       :   0x559d5cbc579a      0fb600         movzx eax, byte [rax]
|       :   0x559d5cbc579d      84c0           test al, al
|       `=< 0x559d5cbc579f      75e1           jne 0x559d5cbc5782
|           0x559d5cbc57a1      90             nop
|           0x559d5cbc57a2      5d             pop rbp
\           0x559d5cbc57a3      c3             ret

Ok, so it’s pretty simple, the function takes a string and for each character it adds one to the ASCII value, it’s a simple ROT1.

Let’s take our two objects and decrypt them.

# coding: utf-8

password = b"NzTfdvs4Q4ttx1se"
flag = b'Vdkk\x1fcnmd \x1fSgd\x1fek`f\x1fhr9\x1fEBRBz72e30320b000/51c//2cc/102be713c55e66/`/ad02/4d1702e04cc654/2`80c|'

clear_password = ''
clear_flag = ''

for value in password:
    clear_password += chr(value - 1)

for value in flag:
    clear_flag += chr(value + 1)

print("Password: {}".format(clear_password))
print("Flag: {}".format(clear_flag))

Our password was already transformed, so we have to decrypt it, but our flag wasn’t transform, so we have to transform it to find the plain flag.

So we subtract 1 to each character in the pass and we add 1 to each character in our flag.

magnussen@funcMyLife:~/tartetatin$ ./exploit.py
Password: MySecur3P3ssw0rd
Flag: Well done! The flag is: FCSC{83f41431c111062d003dd0213cf824d66f770a0be1305e2813f15dd76503a91d}

This was a nice introduction to the reverse challenges.

Thanks to the FCSC team, this was an awesome CTF, I’ve learned a lot and had a lot of fun. Congratulation for the organization, see you next year!