La administración de memoria de Linux usa bandejas (listas de doble enlace) para administrar los fragmentos libres. La macro de desvinculación que se proporciona a continuación elimina un fragmento de un contenedor, suponiendo que obtiene un puntero P a un elemento del contenedor.
Aquí hay algunas preguntas:
¿Cómo se podría usar la función de desvinculación para sobrescribir una ubicación de memoria arbitraria con un valor arbitrario? ¿Por qué se puede llamar a desvincular cuando se libera un trozo? Describe un ataque doble libre explotando desvincular!
#define unlink(P, BK, FD) {
FD = P -> fd;
BK = P -> bk;
FD -> bk = BK;
BK -> fd = FD;
}
Por lo tanto, siempre que haya un elemento en la lista de enlaces dobles, tal que FD = P -> fd = BK = P -> bk
no se puede eliminar de la lista usando unlink
. Esta situación se da cuando un elemento se ha agregado a la lista de doble enlace a través de free(P)
dos veces. Ahora solo podemos escribir un valor arbitrario en fd
y bk
, de manera que cuando aplicamos free(P)
nuevamente, FD -> bk = BK
da como resultado fd -> bk = bk
. Esta última línea significa que asignamos un valor arbitrario bk
a la dirección de chunk P
+ el Offset de fd
que sería de 24 bytes en una arquitectura de 64 bits. Bueno, espero entender esto correctamente. ¿Cómo escribiría a fd
y bk
? Tendría que asignar un valor a P
y saber que el trozo se parece a esta figura: (solo el offset difiere en una arquitectura de 64 bits, creo):
¿Y qué dirías? ¿Por qué se puede llamar a desvincular cuando se libera un trozo? Liberar un fragmento significa que estamos agregando una entrada a la lista de doble libre. Sin vincular, sin embargo, elimina un elemento de la lista de doble enlace. Unlink, por lo tanto, solo se puede llamar en este contexto para fusionar dos trozos de memoria liberados, ¿verdad?
No lo sé, ¿puede alguien ayudarme a obtener más información sobre todo este mecanismo de doble ataque? Creo que esto es tan difícil de entender.