solucion - desbordamiento de pila
El desbordamiento del búfer apareció antes de lo esperado (2)
Primero, su ensamblaje es de 32 bits. La EBP guardada y la dirección de retorno son de 4 bytes cada una.
En segundo lugar, la variable de buffer
no comienza en la parte superior de la pila (ESP); comienza en ebp-0x10. Que está a 20 bytes de distancia de la dirección de retorno. 0x10 es 16 bytes, luego 4 más para el EBP guardado.
Estoy tratando de tomar el control del desbordamiento de la pila. Primero, aquí hay un ejemplo del código C que compilé en una x32 VM Linux ( gcc -fno-stack-protector -ggdb -o first first.c
),
#include "stdio.h"
int CanNeverExecute()
{
printf("I can never execute/n");
return(0);
}
void GetInput()
{
char buffer[8];
gets(buffer);
puts(buffer);
}
int main()
{
GetInput();
return(0);
}
Luego, depurador (intel flavor): volcado de código de ensamblador para la función GetInput
:
0x08048455 <+0>: push ebp
0x08048456 <+1>: mov ebp,esp
0x08048458 <+3>: sub esp,0x28
0x0804845b <+6>: lea eax,[ebp-0x10]
Aquí podemos ver que sub esp, 0x28 reserva 40 bytes para una variable de búfer (¿verdad?). CanNeverExecute
función CanNeverExecute
se encuentra en la dirección 0x0804843c
. Por lo tanto, para ejecutar la función CanNeverExecute
, necesito poner 40 bytes en la variable del buffer, luego voy a 8 bytes para el puntero base almacenado y luego 8 bytes del puntero de retorno que quiero cambiar.
Entonces, necesito una cadena de 48 símbolos ASCII más /x3c/x84/x04/x08
al final (dirección de la función CanNeverExecute
). Eso es en teoría Pero en la práctica solo necesito 20 bytes antes de la dirección del puntero de retorno:
~/hacktest $ printf "12345678901234567890/x3c/x84/x04/x08" | ./first
12345678901234567890..
I can never execute
Illegal instruction (core dumped)
¿Por qué necesita solo 20 bytes en lugar de 48? ¿Dónde está mi error?
Si toma una parte más grande del desmontaje, verá:
08048445 <GetInput>:
8048445: 55 push %ebp
8048446: 89 e5 mov %esp,%ebp
8048448: 83 ec 28 sub $0x28,%esp
804844b: 8d 45 f0 lea -0x10(%ebp),%eax
804844e: 89 04 24 mov %eax,(%esp)
8048451: e8 9a fe ff ff call 80482f0 <gets@plt>
8048456: 8d 45 f0 lea -0x10(%ebp),%eax
8048459: 89 04 24 mov %eax,(%esp)
804845c: e8 9f fe ff ff call 8048300 <puts@plt>
8048461: c9 leave
8048462: c3 ret
ebp se guarda, esp se mueve a ebp, luego 40 se resta de esp (marco de la pila, como usted escribió), pero el puntero al búfer se pasa a través de un registro eax, y eax se carga con ebp-0x10!
lea -0x10(%ebp),%eax
Por lo tanto, solo necesita 20 bytes para desbordar el búfer (16 reservados + 4 para el puntero base almacenado en el sistema de 32 bits)