¿La gente simplemente pone las direcciones de memoria en la pila (probablemente no)?
Sí, ponen direcciones de memoria de pila para llamar (invocadas por las instrucciones ret) y espacio vacío (para ser consumidas por las instrucciones emergentes en el camino) y las variables necesarias como argumentos para funciones llamadas vía ret.
digamos que tienes una aplicación vulnerable, que permite al atacante
para sobrescribir la pila. Algo como:
int function2(arg1,arg2){
char *buffer[10];
printf("Crash me now:\n");
return gets(buffer);
}
int main(int argv,char **args){
function2(arg1,args[0]);
}
- y tiene habilitado DEP, lo que evita que el atacante ponga el
Shellcode directamente para apilar y ejecutar desde allí
- estás dentro de alguna función vulnerable como se pone
Esta es tu pila a partir de ESP como cuando estás en la función de obtención:
local_var1_of_gets
local_var2_of_gets
saved_EBP_of_function2
saved_return_to_function2
arg1_to_function2
arg2_tofunction2
local_buffer_of_function2
local_var2_of_function2
saved_EBP_of_main
saved_return_to_main
local_var1_of_main
local_var2_of_main
saved_EBP_of_entry0
saved_return_to_entry0
argv_to_function_main
args[0]_to_function_main
Así que tú:
- escribe más caracteres que luego se asignan en el búfer en function2
- sobrescribe la dirección "saved_return_to_main" con la dirección del primer gadget
- a medida que la función get llamará "abandonar" (para abrir la EBP almacenada, que tendrá que adivinar cuando se sobrescriba) y ret (para mostrar la dirección en el primer gadget y saltar a ella)
- a partir de ahí, estás por tu cuenta, qué gadgets pones juntos
En realidad, los exploits generalmente apuntan al puntero SEH (ya que es más fácil acertar ese en lugar de adivinar el EBP) y pasar a ROP desde allí.
¿Por qué no DEP impide la llamada de funciones desde una pila no ejecutable?
Porque lo que pones en la pila son solo datos. El código real a ejecutar está en el segmento de texto, referenciado solo como una dirección para regresar desde la estructura de la pila cuando se llama la instrucción "ret".
Excelente demostración de Stephen Sims / SANS SEC660
enlace