Почему адреса функций glibc не рандомизированы, когда включена функция ASLR?

Пытаясь понять ASLR, я построил эту простую программу:

#include <stdio.h>
#include <stdlib.h>

int main() {
    printf("%p\n", &system);
    return 0;
}

ALSR, кажется, включен:

$ cat /proc/sys/kernel/randomize_va_space
2

и я использовал GCC для компиляции программы:

$ gcc aslrtest.c

Каждый раз, когда я запускаю эту программу, она печатает один и тот же адрес (0x400450).

Я ожидаю, что эта программа будет печатать разные адреса каждый раз, если glibc загружается по случайному адресу. Это удивляет меня, особенно если учесть, что предотвращение атак с возвратом в libc должно быть основной мотивацией для ASLR (в частности, system() вызов).

Я ошибаюсь, ожидая, что адрес system() должны быть рандомизированы? Или что-то не так с моей конфигурацией?

2 ответа

Решение

Любые ссылки на функцию из общей библиотеки, которая сделана из независимого от позиции объектного файла в основной программе, требуют записи PLT, через которую вызывающий абонент может выполнить вызов с помощью инструкции вызова, которая преобразуется в фиксированный адрес во время соединения, Это связано с тем, что объектный файл не был создан со специальным кодом (PIC), чтобы он мог поддерживать вызов функции по переменному адресу.

Всякий раз, когда такая запись PLT используется для функции в библиотеке, адрес этой записи PLT, а не исходный адрес функции, становится ее "официальным" адресом (как в вашем примере, где вы печатали адрес system). Это необходимо, потому что адрес функции должен просматриваться одинаково во всех частях программы на Си; это не разрешено языком для адреса system изменяться в зависимости от того, какая часть программы смотрит на него, поскольку это нарушит правило, согласно которому два указателя на одну и ту же функцию сравниваются как равные.

Если вы действительно хотите получить преимущества ASLR от атак, которые вызывают функцию с использованием известного фиксированного адреса, вам нужно собрать основную программу как PIE.

На самом деле printf("%p\n", &system); не печатает адреса libc, это на самом деле печатает system@plt адрес, который не рандомизирован ASLR

Но он действительно рандомизирует адрес libc, который в конечном итоге защищает от атаки ret2libc!!

Другие вопросы по тегам