Подтвердить что ты не робот

Добавление раздела в файл ELF

Мне нужно добавить произвольный раздел в файл ELF. Я не могу использовать код GPL в этой программе, поэтому BFD не может быть и речи. Я могу использовать libelf/gelf для чтения разделов, но документация для них довольно скудна, и я не могу понять, как добавить раздел. Кто-нибудь знает, как это сделать? Я бы предпочел написать собственный код ELF.

4b9b3361

Ответ 1

Вот несколько (возможно) связанных ответов в этом вопросе об заголовках файлов ELF. В принятом ответе упоминалось использование objcopy для добавления разделов в файл ELF, а BSD bintools утверждает, что имеет лицензированную BSD реализацию objcopy, который может удовлетворить ваши потребности.

Ответ 2

Я знаю, что это старый вопрос, но я нашел рабочий пример, который помог мне применить его к моему проекту. (Если кто-то наткнется на этот вопрос)

взято из Sourceware Mail Archiv

$ echo 'int main() { puts ("Hello world"); }' | gcc -x c - -c -o hello.o

$ echo "this is my special data" >mydata

$ objcopy --add-section .mydata=mydata \
          --set-section-flags .mydata=noload,readonly hello.o hello2.o

$ gcc hello2.o -o hello

$ ./hello
Hello world

$ objdump -sj .mydata hello

Ответ 3

Следующие ссылки могут быть полезны:

  • Учебник libelf by Example" содержит раздел о создании новых объектов ELF.
  • проект elftoolchain содержит подробные страницы с описанием libelf API.

Ответ 4

взгляните на ELFsh, который теперь является частью проекта ERESI http://www.eresi-project.org/ У них есть много документации и прохладное использование их инструментов.

Ответ 5

Не пробовал (пока) сам, но вы можете посмотреть на функцию elf_newscn в libelf

Ответ 6

Вы можете посмотреть на этот код:

#include "packer.h"

extern uint64_t     loader_size;
extern uint64_t     infos_size;
extern void     entry_loader(void);

static Elf64_Shdr   new_section = {
  .sh_name = (uint32_t)0,
  .sh_type = (uint32_t)SHT_PROGBITS,
  .sh_flags = (uint64_t)SHF_EXECINSTR | SHF_ALLOC,
  .sh_addr = (Elf64_Addr)0,
  .sh_offset = (Elf64_Off)0,
  .sh_size = (uint64_t)0,
  .sh_link = (uint32_t)0,
  .sh_info = (uint32_t)0,
  .sh_addralign = (uint64_t)16,
  .sh_entsize = (uint64_t)0,
};

uint64_t        entry_addr, entry_size, key;

static int32_t  create_section(t_elf *elf, uint16_t last_section, uint16_t last_ptload)
{
  Elf64_Shdr    *new_shdrs;
  uint8_t   **new_sects;
  uint8_t   *loader;

  elf->elf_header->e_shnum += 1;

  if (!(new_shdrs = realloc(elf->section_header, sizeof(Elf64_Shdr) * elf->elf_header->e_shnum))) {
    perror("realloc");
    return (-1);
  }

  if (!(new_sects = realloc(elf->section_data, sizeof(uint8_t *) * elf->elf_header->e_shnum))) {
    perror("realloc");
    return (-1);
  }

  elf->section_header = new_shdrs;
  elf->section_data = new_sects;

  new_section.sh_offset = elf->prog_header[last_ptload].p_offset + elf->prog_header[last_ptload].p_memsz;
  new_section.sh_addr = elf->prog_header[last_ptload].p_vaddr + elf->prog_header[last_ptload].p_memsz;
  new_section.sh_size = loader_size;

  if (!(loader = malloc(loader_size))) {
    perror("malloc");
    return (-1);
  }

  memcpy(loader, (void *)entry_loader, loader_size);

  memcpy(loader + loader_size - 24, &key, sizeof(uint64_t));
  memcpy(loader + loader_size - 16, &entry_addr, sizeof(uint64_t));
  memcpy(loader + loader_size - 8, &entry_size, sizeof(uint64_t));

  memmove(new_shdrs + last_section + 2, new_shdrs + last_section + 1, sizeof(Elf64_Shdr) * (elf->elf_header->e_shnum - last_section - 2));
  memmove(new_sects + last_section + 2, new_sects + last_section + 1, sizeof(uint8_t *) * (elf->elf_header->e_shnum - last_section - 2));

  memcpy(new_shdrs + last_section + 1, &new_section, sizeof(Elf64_Shdr));
  new_sects[last_section + 1] = loader;

  return (0);
}

Код не очень сложен для понимания, но если вы хотите узнать контекст или то, как этот раздел вставлен в elf, вы можете взглянуть на оригинальную реализацию этой функции в упаковщике sebastiencs:

https://github.com/sebastiencs/Packer_ELF/blob/master/src/insert_section.c