La técnica ret2libc (y la programación orientada al retorno (ROP)) se basa en sobrescribir la pila para crear un nuevo marco de pila que llama a la función del sistema. Este artículo de wikipedia explica los marcos de pila con gran detalle: enlace
El marco de pila determina el orden en que se escriben la función de llamada y los parámetros:
function address
return address
parameters
Entonces, en tu ejemplo, quieres llamar a system()
con cmdstring
y regresar a la función exit()
cuando la llamada system()
vuelva. Entonces escribes el siguiente marco de pila:
system_addr
exit_addr
cmdstring_addr
Si elimina la dirección de salida, cambie el marco de pila a lo siguiente:
system_addr
cmdstring_addr
existingdataonstack_aka_junk
Así que ahora estás llamando a system()
con un argumento de dirección de correo no deseado e intentas volver a ingresar a la cadena de comandos una vez que la función se complete. Es por eso que falla. Puede reemplazar la dirección exit()
con otros datos, como 0x41414141
, lo que causará un segfault
una vez que se complete la llamada system()
. O puede reemplazarlo con la dirección de una ubicación pop pop ret
y luego escribir más marcos de pila debajo. Esto es ahora una carga útil ROP
. Este es un ejemplo básico de cómo se vería en la pila:
system_addr
poppopret_addr
cmdstring_addr
printf_addr
exit_addr
addr_of_string_to_printf
Esto le permitiría imprimir algo como You got hacked
antes de salir.