Objcopy - Writable-текст не делает эльфийский двоичный текстовый раздел доступным для записи?
Я пытался сделать .text
раздел elf
двоичная запись с использованием objcopy --writable-text executable_name
, Команда выполняется нормально без каких-либо ошибок.
При проверке разрешения раздела через readelf
Я вижу, что текстовый раздел по-прежнему имеет только права на чтение и выполнение.
Проходя через objcopy
Упоминается, что страницы man для этой конкретной опции не имеют смысла для всех двоичных форматов. (Это причина, по которой я не могу это сделать?).
Кто-нибудь может указать, что мне здесь не хватает.
Спасибо
(Ubuntu x86_64 bit machine, GNU objcopy (GNU Binutils для Ubuntu) 2.22.90.20120924)
3 ответа
При просмотре man-страниц objcopy для этого конкретного параметра упоминается, что этот параметр не имеет смысла для всех двоичных форматов. (Это причина, по которой я не могу это сделать?).
Да.
При этом достаточно подробном описании специальных разделов формата ELF, вы видите, что .text
имеет SHF_ALLOC + SHF_EXECINSTR
атрибуты (для него выделено место и в нем есть исполняемый код), но не SHF_WRITE
(место может быть записано). Что вы спрашиваете objcopy
делать просто не подходит для ELF .text
разделы.
Сначала выполните это: objcopy --writable-text --set-section-flags .text=CONTENTS,ALLOC,LOAD,CODE
Затем objdump -x или readelf -a для просмотра таблицы разделов загрузки, которые обычно находятся после заголовка программы. Пожалуйста, смотрите справочную страницу для ELF. Для 32-битных исполняемых файлов, например:
Откройте двоичный файл с помощью hexedit и посмотрите на значение смещения файла 0x1C (часто 0x34), затем просмотрите байтовые структуры 0x20 (размер указан по смещению файла 0x2a), пока не найдете тот, который вы идентифицировали в предыдущем дампе, как содержащий Раздел текста. Длинное значение от второго до последнего будет равно 00000005 (05 00 00 00) и должно иметь добавленную запись, которая станет 00000007 (07 00 00 00). Теперь он будет работать, как и ожидалось, без каких-либо ограничений, таких как проблемы с общей библиотекой с -Wl, - omagic. Немного технический, но занимает несколько секунд.
Несмотря на это, этот однобитовый флаг вызвал бесчисленные проблемы, и никакие объяснения не прояснили этот маленький момент, который позволяет ему работать безупречно.
Кодовое решение может быть легко скомпилировано с GCC, чтобы сделать изменение, которое, вероятно, проще и лучше, если делать это регулярно:
#include <stdlib.h>
#include <stdio.h>
#include <elf.h>
int main(int argc, char** argv)
{
if (argc <= 1) return -1;
FILE* fp = fopen(argv[1], "r+");
Elf64_Ehdr teh;
fread(&teh, sizeof(teh), 1, fp);
fseek(fp, 0, SEEK_SET);
if (teh.e_ident[EI_CLASS] == ELFCLASS64) {
Elf64_Ehdr eh;
fread(&eh, sizeof(eh), 1, fp);
Elf64_Phdr* ph = malloc(eh.e_phnum * eh.e_phentsize);
Elf64_Shdr* sh = malloc(eh.e_shnum * eh.e_shentsize);
fseek(fp, eh.e_phoff, SEEK_SET);
fread(ph, eh.e_phentsize, eh.e_phnum, fp);
fseek(fp, eh.e_shoff, SEEK_SET);
fread(sh, eh.e_shentsize, eh.e_shnum, fp);
for (int i = 0; i < eh.e_phnum; i++) {
if (ph[i].p_vaddr <= eh.e_entry && ph[i].p_vaddr + ph[i].p_memsz > eh.e_entry) {
fseek(fp, eh.e_phoff + i * eh.e_phentsize + (unsigned int)&((Elf64_Phdr*)0)->p_flags, SEEK_SET);
ph[i].p_flags |= PF_W;
fwrite(&ph[i].p_flags, sizeof(ph[i].p_flags), 1, fp);
}
}
for (int i = 0; i < eh.e_shnum; i++) {
if (sh[i].sh_addr <= eh.e_entry && sh[i].sh_addr + sh[i].sh_size > eh.e_entry) {
fseek(fp, eh.e_shoff + i * eh.e_shentsize + (unsigned int)&((Elf64_Shdr*)0)->sh_flags, SEEK_SET);
sh[i].sh_flags |= SHF_WRITE;
fwrite(&sh[i].sh_flags, sizeof(sh[i].sh_flags), 1, fp);
}
}
free(ph);
free(sh);
} else {
Elf32_Ehdr eh;
fread(&eh, sizeof(eh), 1, fp);
Elf32_Phdr* ph = malloc(eh.e_phnum * eh.e_phentsize);
Elf32_Shdr* sh = malloc(eh.e_shnum * eh.e_shentsize);
fseek(fp, eh.e_phoff, SEEK_SET);
fread(ph, eh.e_phentsize, eh.e_phnum, fp);
fseek(fp, eh.e_shoff, SEEK_SET);
fread(sh, eh.e_shentsize, eh.e_shnum, fp);
for (int i = 0; i < eh.e_phnum; i++) {
if (ph[i].p_vaddr <= eh.e_entry && ph[i].p_vaddr + ph[i].p_memsz > eh.e_entry) {
fseek(fp, eh.e_phoff + i * eh.e_phentsize + (unsigned int)&((Elf32_Phdr*)0)->p_flags, SEEK_SET);
ph[i].p_flags |= PF_W;
fwrite(&ph[i].p_flags, sizeof(ph[i].p_flags), 1, fp);
}
}
for (int i = 0; i < eh.e_shnum; i++) {
if (sh[i].sh_addr <= eh.e_entry && sh[i].sh_addr + sh[i].sh_size > eh.e_entry) {
fseek(fp, eh.e_shoff + i * eh.e_shentsize + (unsigned int)&((Elf32_Shdr*)0)->sh_flags, SEEK_SET);
sh[i].sh_flags |= SHF_WRITE;
fwrite(&sh[i].sh_flags, sizeof(sh[i].sh_flags), 1, fp);
}
}
free(ph);
free(sh);
}
fflush(fp);
fclose(fp);
return 0;
}
В Debian я могу просто связать с -N, и это создает исполняемый файл с возможностью записи.text
итак: ld -N obj.o