Допустим, бинарник — это PIC, как его загрузить в память и выполнить точку входа? Я делаю это, чтобы познакомиться с ELF, поэтому execve
не разрешено.
Как загрузить и выполнить двоичный исполняемый файл ELF вручную?
Ответы (1)
Вот основные шаги:
- Прочтите заголовки программы, чтобы найти директивы LOAD и определить общую длину отображений, которые вам понадобятся, в страницах.
- Сопоставьте директиву LOAD с наименьшим адресом с общей длиной (которая может быть больше, чем длина файла), позволяя
mmap
назначить вам адрес. Это позволит зарезервировать непрерывное виртуальное адресное пространство. - Сопоставьте директивы remining LOAD поверх частей этого сопоставления, используя
MAP_FIXED
. - Используйте заголовки программы, чтобы найти вектор
DYNAMIC
, который, в свою очередь, даст вам адрес вектора(ов) перемещения. - Примените переезды. Предполагая, что ваш двоичный файл был двоичным файлом PIE со статической привязкой, он должен полностью состоять из
RELATIVE
перемещений (просто добавляя адрес базовой загрузки), что означает, что вам не нужно выполнять поиск символов или что-то необычное. Создайте стек записи программы ELF, состоящий из следующей последовательности значений размером системного слова в массиве в стеке:
ARGC ARGV[0] ARGV[1] ... ARGV[ARGC-1] 0 ENVIRON[0] ENVIRON[1] ... ENVIRON[N] 0 0
(Для этого шага требуется ASM!) Наведите указатель стека на начало этого массива и перейдите к адресу точки входа загруженной программы (который можно найти в заголовках программы).
person
R.. GitHub STOP HELPING ICE
schedule
02.07.2011
Э-э, я думал, что смысл кода, не зависящего от позиции, в том, что он не имеет перемещений - у него есть глобальная таблица смещений или что-то в этом роде.
- person Random832; 02.07.2011
@ Random832, смогу ли я реализовать загрузчик и выполнить двоичный файл, если это не PIC?
- person Je Rog; 02.07.2011
@ Random832: У вас всегда есть вероятность перемещения данных. Как еще может работать
static int x, *y=&x;
? И, конечно же, в ПТ полно переездов. Единственный способ избежать каких-либо перемещений — избежать каких-либо глобальных данных.
- person R.. GitHub STOP HELPING ICE; 02.07.2011
@R..: Я не думаю, что статически связанный исполняемый файл, отличный от PIE, нуждается в каком-либо перемещении.
- person ninjalj; 02.07.2011
@R..: вы также должны передать массив
auxv
в программу.
- person ninjalj; 02.07.2011
@ninjalj, когда
auxv
полезен?
- person Je Rog; 02.07.2011
@Je Rog: как правило, почти никогда.
- person ninjalj; 02.07.2011
Я говорил о позиционно-независимом коде. Очевидно, что статическая связанная программа с фиксированным адресом не нуждается в перемещении.
- person R.. GitHub STOP HELPING ICE; 02.07.2011
И что касается
auxv
: последний 0 в моем примере стека был нулевой длины auxv
. Передача нетривиального auxv
может быть хорошей идеей, но вы не можете просто скопировать тот, который дал вам ядро; вы должны изменить его, чтобы он соответствовал адресу загрузки, адресу заголовка программы и т. д. для новой программы.
- person R.. GitHub STOP HELPING ICE; 03.07.2011
@R.., я не понимаю одну из спецификаций: почему
loadable process segments must have congruent values for p_vaddr and p_offset, modulo the page size
?
- person Je Rog; 07.07.2011
Отображение виртуальной памяти осуществляется на уровне страниц (на самом деле это определение страницы). Таким образом, если бы
p_vaddr
и p_offset
не были конгруэнтны по модулю размера страницы, не было бы никакого способа удовлетворить LOAD
с помощью mmap
. Сегмент придется полностью скопировать на новые анонимные страницы.
- person R.. GitHub STOP HELPING ICE; 07.07.2011
@R.., Как соотносятся ч/б сегменты и участки, пересекаются ли они?
- person Je Rog; 13.07.2011
main
. - person zneak   schedule 02.07.2011