Как я могу просмотреть имена функций и параметры, содержащиеся в файле ELF?

Если я посмотрю на байты файла, то определенно увижу там имена некоторых функций. Есть ли какой-нибудь инструмент, который перечислит их для меня? Может быть, даже их параметры?


Это должно напечатать все определенные символы в вашем объектном файле или библиотеке.

  nm -C --defined-only file.o  

nm имеет довольно много параметров, которые вы можно использовать для фильтрации символов, таких как -g для отображения только глобальных символов , -l для печати номера строки (если вы использовали gcc -g для включения символов отладки) и так далее.

Если у вас есть двоичный файл формата ELF (похоже, ваш случай), вы также можете использовать readelf

  readelf -Ws file.o  

Номер столбца 8 в этом выводе содержит имя символа, которое представляет интерес. Вы можете использовать c ++ filter , чтобы распутать имя:

  readelf -Ws file.o |  awk '{print $ 8}' |  c ++ filter  


Как такие инструменты, как objdump, находят имена функций и их начальный адрес в двоичных файлах ELF?

Я написал парсер ELF, который разбирает раздел .text с помощью Capstone

моя проблема в том, что я не знаю, как сегментировать текстовый раздел на основе функций и распечатать имя функции. точно так же, как вывод objdump -d

, потому что objdump выводит так:

0x01000 func1:

0x01000 ..

0x01001 ..

как я могу узнать имя и начальный адрес каждой функции в .text, чтобы я мог выводить что-то вроде objdump?

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

(примечание что я не говорю о функциях импорта и тому подобном, а только о функциях внутри фактического основного кода в разделе .text)


Для этого вам понадобятся некоторые знания о файлах ELF. Я не собираюсь подробно рассказывать о файлах ELF, так как их много, поэтому я постараюсь быть максимально точным.

ПРИМЕЧАНИЕ № 01: Я буду используйте radare2 для анализа файла, но вы можете сделать это с помощью любого шестнадцатеричного редактора.

ПРИМЕЧАНИЕ № 02: Вот ссылка на файл cpp, который я скомпилировать, чтобы объяснить вам файлы ELF. Не стесняйтесь брать или создавать свои собственные.

Во-первых, вам нужно знать структуру заголовков в файлах ELF. Здесь вы можете увидеть структуру заголовков.

Первое, что мы хотим найти, это e_ident , который представляет формат файла (32-битный или 64-битный) поскольку заголовок файла будет отличаться в зависимости от формата файла.

e_ident offset = 0x04, size = 1byte

Перейдите к смещению файла 0x04 и проверьте один байт. ( s означает поиск)

 :> s 0x040x00000004 02  

e_ident = 0x02 означает 64-битный формат.

Теперь, когда мы выбрали формат файла, нам нужно знать смещение заголовка раздела ( e_shoff ), размер каждой записи ( e_shentsize ) и количество записей в заголовке раздела ( e_shnum ).

e_shoff смещение = 0x28 size = 8 байтов
e_shentsize смещение = 0x3A size = 2 байта
e_shnum смещение = 0x3C size = 2 байта

 :> s 0x280x00000028 e03b 0000 0000 0000:> s 0x3A0x0000003a 4000:> s 0x3C0x0000003c 1d00  

e_shoff = 0x3be0 Это смещение заголовка раздела.
e_shentsize = 0x40 (64 байта)
e_shnum = 0x1d (29 записей)

Нам также понадобится индекс заголовка раздела, который содержит имена каждого заголовка раздела. Это хранилище в e_shstrndx

e_shstrndx offset = 0x3E size = 2bytes

 :> s 0x3e0x0000003e 1c00  

e_shstrndx = 0x1c (запись 28)

С номером записи вы можете получить адрес shstrtab:

 //e_shoff + (e_shentsize * e_shstrndx) + sh_offset:> s 0x3be0 + (0x40 * 0x1c) + 0x180x000042f8 df3a 0000 0000 0000  

shstrtab = 0x3adf

Теперь, когда у вас есть эта информация, вы можете запустить цикл, который проверяет все записи раздела:

 //псевдокод для (i = 0; i  

ПРИМЕЧАНИЕ # 03: I я не буду печатать эти значения здесь, потому что мне нужно объяснить больше, но это даст вам нечто похожее на команду readelf -W -l [program]

Каждая запись имеет структуру, подобную заголовку раздела. Чтобы получить имя каждой записи, добавьте sh_name в shstrtab

Я просто покажу вам, как я получил .text , но идея будет одинаковой для любой записи раздела. В моем случае .text был записью 0x0e (14). Мне понадобится sh_name , смещение в файле sh_offset и размер sh_size

sh_name смещение = 0x00 size = 4 байта
sh_offset смещение = 0x18 size = 8 байтов
sh_size смещение = 0x20 размер = 8 байт

 //e_shoff + (e_shentsize * e_shstrndx) + sh_name:> s 0x3be0 +  (0x40 * 0x0e) + 0x000x00003f60 9d00 0000//Получаем имя:> s 0x3adf + 0x9d0x00003b7c 2e74 6578 7400 2e66 696e 6900 2e72 6f64 .text..fini..rod//e_shoff + (e_shentsize * e_shstrndset> + 0_shstrndset)  (0x40 * 0x0e) + 0x180x00003f78 9010 0000 0000 0000//e_shoff + (e_shentsize * e_shstrndx) + sh_size:> s 0x3be0 + (0x40 * 0x0e) + 0x200x00003f80 3102 0000 0000 0000  

entry = 0x3be0//.text
sh_offset = 0x1090
sh_size = 0x0231 (561bytes)

Если вы не можете найти его таким образом, тогда ваш ELF-файл должен быть поврежден. Вы можете взять тот, который я собрал, чтобы следовать этому объяснению. Удачи.

Оцените статью
clickpad.ru
Добавить комментарий