ELF, PIE ASLR и все что между ними, особенно в Linux

Хорошо, поэтому, прежде чем задавать мой вопрос, я хотел бы рассказать о некоторых технических деталях, которые я хочу убедиться, что я правильно понял:

Позиционно-независимый исполняемый файл - PIE, это код, который можно было бы выполнить независимо от того, в какой адрес памяти он загружен, верно?

ASLR ------ Рандомизация размещения адресного пространства, в значительной степени заявляет, что для того, чтобы сохранить адреса статичными, мы бы каким-то образом их рандомизировали,

Я читал, что конкретно в системах на базе Linux и Unix. Реализация ASLR возможна независимо от того, является ли наш код PIE, если это PIE, все переходы, вызовы и смещения являются относительными, следовательно, у нас нет проблем. изменяется и адреса редактируются независимо от того, является ли код исполняемым или общим объектом....

Хорошо.... теперь это заставляет меня задать несколько вопросов

  1. Если ASLR можно реализовать в кодах, которые не являются PIE и являются исполняемыми файлами, а НЕ ОБЩИМИ / УДАЛЕННЫМИ ОБЪЕКТАМИ (Я ЗНАЮ, КАК ОТНОСИТЕЛЬНО РАБОТАЕТ В СООТВЕТСТВУЮЩИХ ОБЪЕКТАХ!!!!), как это делается?, Формат elf не должен содержать ни одного раздела, в котором говорится где внутри разделов кода есть функции, чтобы загрузчик ядра мог их модифицировать, верно? ASLR должен быть функциональностью ядра, так как, например, может быть исполняемый файл, содержащий, например, эти инструкции

    код псевдо:

    inc_eax:
     add eax, 5
     ret
    
    main:
     mov eax, 5
     mov ebx, 6
     call ABSOLUTE_ADDRES{inc_eax}
    

    как загрузчик исполняемого файла ядра мог бы знать, как изменить адреса, если они не хранятся в какой-либо перемещаемой таблице в файле elf и не являются относительными для загрузки исполняемого файла в некоторый случайный адрес?

  2. Допустим, я ошибаюсь, и для реализации ASLR у вас должен быть исполняемый файл PIE, все сегменты являются относительными, как можно скомпилировать код ООП C++ и заставить его работать, например, если у меня есть какой-то экземпляр класса, использующий указатель на виртуальную таблицу в ее структуре, и эта виртуальная таблица должна содержать абсолютные адреса, поэтому я не смог бы скомпилировать чистый PIE для программ на C++, использующих виртуальные таблицы времени выполнения, и снова ASLR невозможен.... я сомневаюсь, что виртуальные таблицы будут содержать относительные адреса, и для каждого вызова какой-либо виртуальной функции будут разные виртуальные таблицы...

  3. Мой последний и наименее важный вопрос касается ELF и PIE, есть ли какой-то особый способ обнаружения исполняемого файла ELF - это PIE? Я знаком с форматом ELF, поэтому сомневаюсь, что есть способ, но я могу ошибаться в любом случае если нет способа, как загрузчик ядра узнает, является ли наш исполняемый файл PIE, следовательно, он может использовать ASLR на нем

У меня все это запутано в моей голове, и я буду рад, если кто-нибудь сможет мне здесь помочь, заранее спасибо

1 ответ

Ваш вопрос, кажется, мешанина путаницы и недопонимания.

Независимый от позиции исполняемый файл - PIE, это код, который можно было бы выполнить независимо от того, в какой адрес памяти он загружен, верно?

Почти. PIE двоичный файл обычно не может быть загружен в память по произвольному адресу, так как его PT_LOAD сегменты будут иметь некоторые требования к выравниванию (например, 0x400 или 0x10000). Но он может быть загружен и будет работать правильно, если загружен в память по адресу, удовлетворяющему требованиям выравнивания.

ASLR ------ Рандомизация размещения адресного пространства, в значительной степени заявляет, что для того, чтобы сохранить адреса статичными, мы бы каким-то образом их рандомизировали,

Я не могу разобрать вышеизложенное каким-либо осмысленным способом.

ASLR - это метод рандомизации различных частей адресного пространства, чтобы сделать атаки "известного адреса" более сложными.

Обратите внимание, что ASLR предшествует PIE двоичные файлы, и ни в коем случае не требует PIE, Когда ASLR был представлен, он рандомизировал размещение стека, кучи и разделяемых библиотек. Размещение (неPIEОсновной исполняемый файл не может быть рандомизирован.

ASLR считается успешным, и поэтому распространяется также на поддержку PIE основной двоичный файл, который на самом деле является специально созданной общей библиотекой (и имеет ET_DYN тип файла).

  1. call ABSOLUTE_ADDRES{inc_eax} как загрузчик исполняемого ядра ядра знает, как изменить адреса, если они не хранятся в какой-либо перемещаемой таблице

Просто: на x86 нет инструкции call ABSOLUTE_ADDRESS - все звонки относительны.

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

PIE двоичный файл требует перемещения, как и общая библиотека. Виртуальные столы в PIE двоичные файлы работают точно так же, как они работают в общих библиотеках: ld-linux.so.2 обновления GOT (глобальная таблица смещений) перед передачей управления PIE двоичный файл.

3... есть ли какой-то особый способ обнаружить исполняемый файл ELF PIE

Просто: PIE Для двоичного файла установлен тип файла ELF ET_DYN (неPIE бинарный будет иметь тип ET_EXEC). Если вы бежите file a.out на PIE исполняемый файл, вы увидите, что это "общая библиотека".

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