Take a look at radare2. It can parse file formats (see here for an example of parsing the ELF header).
Radare2 supports multiple architectures and is being actively developed. On top of that it has bindings for a lot of languages, including Python of course. Read through the bindings source code to see it is pretty straightforward to script it.
HTH!
Answer from Carlos Garcia on Stack ExchangeVideos
» pip install elf
» pip install elffile
» pip install pyelftools
Take a look at radare2. It can parse file formats (see here for an example of parsing the ELF header).
Radare2 supports multiple architectures and is being actively developed. On top of that it has bindings for a lot of languages, including Python of course. Read through the bindings source code to see it is pretty straightforward to script it.
HTH!
LIEF is a good choice for parsing ELF binaries. It's written in C++, but comes with proper Python bindings and is readily available via PyPi. Besides parsing ELF files it also supports Windows PE and MacOS binaries, reading and modifying and writing all of them, that is.
It's available since 2017 and is actively maintained (example).
LIEF is pretty light-weight and doesn't require many dependencies.
There's a new kid on the block - pyelftools - a pure Python library for parsing the ELF and DWARF formats. Give it a try.
It aims to be feature-complete and is currently in active development, so any problems should be handled quickly and enthusiastically :-)
The concept of "ELF debug info" doesn't really exist: the ELF specification leaves the content of the .debug section deliberately unspecified.
Common debug formats are STAB and DWARF. A library to read DWARF is libdwarf.
To change/edit any section of the ELF file I simply used pyelftools's ELFFile class methods to acquire the field's (i) offset and (ii) size. So then I know exactly where to look inside the binary file.
So after getting the values-margins of the field (A,B) I simply treated the file like a normal binary. The only thing I did is to do a file.seek(A) to move the file pointer to the specific section that I wish to modify.
def edit_elf_section(elf_object,original_file,section):
elf_section = elf_object.get_section_by_name(section)
# !! IMPORTANT !!
section_start = elf_section['sh_offset'] # NOT sh_addr. sh_addr is the logical address of the section
section_end = section_start + elf_section['sh_size']
original_file.seek(section_start)
# Write whatever you want to the file #
assert(original_file.tell() <= section_end) # You've written outside the section
To validate the results you can use the diff binary to see that the files are/aren't identical
You can use LIEF
import lief
b = lief.parse('main')
print(b.type)
s = b.get_symbol('main')
print(s.name)
s.name = 'test'
b.write('main.new')