¿Cómo protege ASLR los puntos de entrada de libc?

2

ASLR aleatoriza las direcciones del código ejecutable del proceso, la pila, el montón y las bibliotecas. Esto es para dificultar la vida de un atacante, ya que no pueden codificar las direcciones en el código en múltiples instancias.

¿Pero cómo ayuda esto con las bibliotecas del sistema? Nunca se descargan. Cada proceso usa libc, por ejemplo, y por lo tanto la dirección de prinf nunca cambia. ¿Cómo me ayuda esto si estoy codificando la dirección de printf? Esto no cambia a menos que la máquina se reinicie.

Tengo ASLR habilitado -

# cat /proc/sys/kernel/randomize_va_space 
2

Aquí hay un código de ejemplo -

unsigned long getEBP ( void )
{
    asm("movl %ebp, %eax");
}

int main(void)
{
    int (*p)(const char*, ...) = &printf;
    printf("printf address = %p \n", p);
    (*p)("printf address = %p\n", &printf);
    printf ("EBP:%x\n" ,getEBP ());
}

Y la salida a través de múltiples ejecuciones -

# ./a.out 
  printf address = 0x4003c0 
  printf address = 0x4003c0 
  EBP:6a71d300

# ./a.out 
  printf address = 0x4003c0 
  printf address = 0x4003c0 
  EBP:93e5c100

Vea que el EBP está cambiando como debería pero no la dirección de printf.

¿Qué me estoy perdiendo?

EDITAR: Compilar con -fPIC no ayudó en mi máquina virtual RHEL.

# ./a.out 
  printf address = 0x3047a4f0f0 
  printf address = 0x3047a4f0f0 
  EBP:7aaac900

# ./a.out 
  printf address = 0x3047a4f0f0 
  printf address = 0x3047a4f0f0
  EBP:632eca20

Si las llamadas libc son de hecho aleatorias como la respuesta dice a continuación, ¿cómo se implementa? libc en sí no se vuelve a cargar, por lo que la dirección real de printf no cambia, ¿cómo se puede aleatorizar?

    
pregunta stflow 02.01.2018 - 20:01
fuente

2 respuestas

1

Actualización:

vea enlace

Compile el binario utilizando -fPIE o -fPIC -pie -fPIE :

enlace

Binario compilado con banderas por defecto:

user01@user01 ~/test $ ./test_ASLR 
printf address = 0x400420 
printf address = 0x400420
EBP:9af703c0
user01@user01 ~/test $ ./test_ASLR 
printf address = 0x400420 
printf address = 0x400420
EBP:8411e900
user01@user01 ~/test $ ./test_ASLR 
printf address = 0x400420 
printf address = 0x400420
EBP:28f8e50

Binario compilado con -pie -fPIE flags:

user01@user01 ~/test $ ./test_ASLR 
printf address = 0x7f8227963340 
printf address = 0x7f8227963340
EBP:19e01ad0
user01@user01 ~/test $ ./test_ASLR 
printf address = 0x7fecb2baa340 
printf address = 0x7fecb2baa340
EBP:9c8148e0
user01@user01 ~/test $ ./test_ASLR 
printf address = 0x7f5d00edb340 
printf address = 0x7f5d00edb340
EBP:32b3c6d0
    
respondido por el SYS_V 02.01.2018 - 20:30
fuente
0

Cuando compila con indicadores predeterminados, la mayoría del tiempo .text segmento permanece en direcciones constantes y GOT se llena con una lista de punteros para las funciones utilizadas en el programa que se resuelven a medida que se encuentran. Ahora, como en este caso GOT estuvo en un lugar constante, el compilador lo colocó directamente en call . Un ejemplo:

0x8048446 <main+35>    call   printf@plt                    <0x80482f0>

Esto no significa que la ubicación real de printf no fue aleatoria. Si esta fue la primera llamada a printf en el programa _dl_runtime_resolve llenará los valores apropiados. De lo contrario debería verse algo como esto

pwndbg> x/xi 0x80482f0
0x80482f0 <printf@plt>: jmp    DWORD PTR ds:0x804a00c
pwndbg> telescope 0x804a00c
00:0000│   0x804a00c (_GLOBAL_OFFSET_TABLE_+12) —▸ 0xf7e38670 (printf) ◂— call   0xf7f0eb09

Esta es la ubicación real de printf en libc. En casos normales, &printf apunta al printf@plt , que solo es un salto para el printf real en libc.

Ahora para -pie -fPIE el &printf apunta al printf real en libc. Este indicador solo agrega ASLR a las secciones que fueron constantes anteriormente. Las bibliotecas eran cargado en desplazamientos aleatorios en ambos casos.

    
respondido por el sudhackar 03.01.2018 - 09:22
fuente

Lea otras preguntas en las etiquetas