Me pregunto si alguien ha propuesto, evaluado o implementado previamente la siguiente medida para reforzar los sistemas contra sobrecargas de búfer basadas en el montón: básicamente, apilar canarios, pero aplicados antes de punteros de función en objetos almacenados en el montón en lugar de antes de regresar Direcciones almacenadas en la pila.
Considera una estructura como
struct whatever {
int blah;
char buf[256];
void (*fp)(); // a function pointer
}
Observe que si hay una saturación que escribe más allá del final del campo buf
, será posible sobrescribir el campo de puntero de función fp
.
Un compilador podría defenderse plausiblemente de esto introduciendo un canario, un valor aleatorio secreto, almacenado entre el búfer y el puntero de función. Básicamente, el compilador transformaría el diseño de la estructura a
struct whatever {
int blah;
char buf[256];
unsigned int canary; // inserted by compiler; not exposed to source code
void (*fp)(); // a function pointer
}
Por ejemplo, el compilador podría organizar escribir el campo canary
con un valor secreto global cada vez que el programa escriba en fp
, y podría verificar que el valor de canary
permanezca sin cambios cada vez que el programa lea de fp
.
Esto es básicamente el análogo de los canarios de pila, pero ahora nos centramos en proteger los punteros de función en el montón en lugar de direcciones de retorno en la pila. Parece una idea natural.
¿Alguien ha propuesto esto antes? ¿Alguien ha hecho un prototipo o evaluado el costo de rendimiento de hacer algo como esto? ¿Existen barreras no obvias para la implementación (más allá del hecho de que requiere cambios para los compiladores, al igual que lo hacen los canarios de pila)?
Investigación que he hecho: soy consciente de la idea de insertar páginas de guarda entre objetos en el montón, pero eso es diferente (protege contra los desbordamientos del montón que van más allá de los límites de un solo objeto, mientras que estoy hablando sobre algo que proteger contra los desbordamientos de pila que permanecen dentro de la región de un solo objeto de pila). Estoy familiarizado con Cruiser y ContraPolice , que coloca canarios entre objetos en el montón, pero que también se enfoca en desbordamientos de objetos cruzados en lugar de desbordamientos dentro de objetos. También estoy familiarizado con el uso de pila de archivos o el cifrado de puntero para proteger los metadatos de malloc, pero, una vez más, no protege contra los desbordamientos dentro de los objetos y está diseñado para proteger los metadatos de malloc en lugar de los punteros de función.