ELF и overlay

ARCHANGEL

Посетитель
Мудрец
Сообщения
47
Реакции
467
Товарищи, пытаюсь написать код, который определит, есть ли у файла оверлей. Нужна поддержка именно ELF формата, для PE всё очевидно. Взял для просмотра кода библиотеку LIEF, там вроде всё тривиально:

overlay checking:
uint64_t Binary::eof_offset(void) const {
  uint64_t last_offset_sections = 0;

  for (Section* section : this->sections_) {
    if (section->type() != LIEF::ELF::ELF_SECTION_TYPES::SHT_NOBITS) {
      last_offset_sections = std::max<uint64_t>(section->file_offset() + section->size(), last_offset_sections);
    }
  }

  const uint64_t section_header_size = this->type() == LIEF::ELF::ELF_CLASS::ELFCLASS64 ? sizeof(typename ELF64::Elf_Shdr) : sizeof(typename ELF32::Elf_Shdr);
  const uint64_t segment_header_size = this->type() == LIEF::ELF::ELF_CLASS::ELFCLASS64 ? sizeof(typename ELF64::Elf_Phdr) : sizeof(typename ELF32::Elf_Phdr);

  const uint64_t end_sht_table =
      this->header().section_headers_offset() +
      this->sections_.size() * section_header_size;

  const uint64_t end_phdr_table =
      this->header().program_headers_offset() +
      this->segments_.size() * segment_header_size;

  last_offset_sections = std::max<uint64_t>({last_offset_sections, end_sht_table, end_phdr_table});

  const uint64_t last_offset_segments = this->last_offset_segment();
  const uint64_t last_offset          = std::max<uint64_t>(last_offset_sections, last_offset_segments);

  return last_offset;
}


bool Binary::has_overlay(void) const {
  return this->overlay_.size() > 0;
}
Вот только на практике скомпилил ELF, в котором никакого оверлея нет. LIEF тоже показывает, что оверлея нет. Взял XELFViewver от hors, там тоже никаких данных про оверлей нет, но после последней секции лежат какие-то данные, которые непонятно, к чему отнести. not_overlay_but_what.png
Как же правильно детектить эти оверлеи на линуксе в elf?
 

dermatolog

Посетитель
Ветеран
Сообщения
12
Реакции
4
После секции с названиями секций ".shstrtab" идут заголовки самих секций (Elf32_Shdr/Elf64_Shdr). Все что идет за ними можно считать оверлеем.
 

ARCHANGEL

Посетитель
Мудрец
Сообщения
47
Реакции
467
Чёрт возьми, да. Просто я затупил и не заметил, что оффсеты как заголовков секций, так и заголовков файлов могут быть в эльфе ЗА самими секциями. Собственно, для чего в LIEF и лежит такой код:

overlay smart detection:
const uint64_t end_sht_table =
      this->header().section_headers_offset() +
      this->sections_.size() * section_header_size;

  const uint64_t end_phdr_table =
      this->header().program_headers_offset() +
      this->segments_.size() * segment_header_size;

  last_offset_sections = std::max<uint64_t>({last_offset_sections, end_sht_table, end_phdr_table});
Но я не пойми куда смотрел, спасибо.
 

hors

Посетитель
Ветеран
Сообщения
46
Реакции
472
Тут философский вопрос что считать оверлеем в ELF файлах. В PE это все то что находится за секцией с самым большим значением смещение + физразмер и не грузится в виртуальную память. Можно ли по аналогии считать в ELF оверлеем все то, что находится в конце и не грузится в память - вопрос дискуссионный.
 

ARCHANGEL

Посетитель
Мудрец
Сообщения
47
Реакции
467
Считаю, что можно, потому так и делаю )
 

dosprog

Наставник
Мудрец
Сообщения
204
Реакции
557
Само название 'оверлей' это условность.

Прижилось со времён dos, когда программы могли динамически подкачивать в память и выполнять код, записанный в т.н. оверлейном файле (т.е. файле перекрытия).
Этот оверлейный файл мог быть прикопирован к EXE файлу, отсюда и пошло
это название для данных в конце файла, не описанных в заголовках EXE, и без которых он не теряет способности быть загруженным на выполнение.

Значит, все данные в конце файла, которые не описаны в заголовках и которые можно отрезать
без потери способности загружаться на выполнение, можно считать "оверлеем".
 
Последнее редактирование:

_MBK_

Ветеран
Новичок
Сообщения
180
Реакции
30
Прижилось со времён dos, когда программы могли динамически подкачивать в память и выполнять код, записанный в т.н. оверлейном файле
Не совсем так. Просто в те благословенные времена зеленой травы и доступных девушек компьютеры были большими, а память маленькой и весь код программы туда банально не влезал. А поскольку динамических библиотек на тот момент еще не изобрели, выкручивались разнообразными костылями, вроде ручной подгрузки отдельных ее частей в оверлейный буфер, без разницы из какого файла, того же или внешнего.
 

dosprog

Наставник
Мудрец
Сообщения
204
Реакции
557
Именно так.
выкручивались разнообразными костылями, вроде ручной подгрузки отдельных ее частей в оверлейный буфер
Это не было вручную.
Компилятор генерировал код автоматической подгрузки функции при её вызове,
это было прозрачно для пользователя.
Нужно было только следить, чтобы подгружаемые функции имели как можно меньше вызовов друг-друга,
чтобы не пререполнялся этот самый оверлейный буфер.

..
Ковыряние таких программ, конечно, было геморройным.
Из эпичных примеров оверлейных программ можно привести популярный некогда текстовый редактор "Слово и дело",
Там использовался вызов оверлейных функций, и не потому, что не хватало оперативной памяти,
а для того, чтобы главный модуль втиснуть в 64Кб (com-формат), который разработчик от души завертел всякими примочками.
В оверлейных функциях там тоже было некоторое количество пакостей, искать которые было не очень неприятно.

См. - W&D v.7.6 (исправленный)
 
Последнее редактирование:

sendersu

Ветеран
Мудрец
Сообщения
141
Реакции
470
640 КБ на самом деле хватит всем.

Многие знают эту фразу. Ее часто ошибочно приписывают Биллу Гейтсу. Однако, до сих пор существует активное сообщество, использующее DOS и разрабатывающее для неё ПО.
 

_MBK_

Ветеран
Новичок
Сообщения
180
Реакции
30
Так и 64к по началу хватало вполне
 
Верх Низ