Socket
Book a DemoInstallSign in
Socket

elftools

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

elftools

1.3.1
bundlerRubygems
Version published
Maintainers
1
Created
Source

Build Status Code Climate Issue Count Test Coverage Inline docs Yard Docs MIT License

rbelftools

Pure Ruby library for parsing and patching ELF files.

Introduction

An ELF parser implemented in pure Ruby. This work is inspired by pyelftools by Eli Bendersky.

The original motivation to create this gem is to be a dependency of pwntools-ruby. Since ELF parser is not an easy work, it should not be implemented directly in pwntools.

Now rbelftools is also used by the Homebrew project: https://github.com/Homebrew/brew/tree/master/Library/Homebrew/vendor/bundle/ruby/2.6.0/gems/elftools-1.1.3/lib

rbelftools's target is to create a nice ELF parsing library in Ruby. More features remain a work in progress.

Install

Available on RubyGems.org!

gem install elftools

Features

  • Supports both big and little endian
  • ELF parser
  • ELF headers patcher

See example usage for more details.

Example Usage

Start from a file object

require 'elftools'

elf = ELFTools::ELFFile.new(File.open('spec/files/amd64.elf'))
#=> #<ELFTools::ELFFile:0x00560b147f8328 @elf_class=64, @endian=:little, @stream=#<File:spec/files/amd64>>

elf.machine
#=> 'Advanced Micro Devices X86-64'

elf.build_id
#=> '73ab62cb7bc9959ce053c2b711322158708cdc07'

Sections

elf.section_by_name('.dynstr')
#=>
# #<ELFTools::Sections::StrTabSection:0x00560b148cef40
# @header=
#  {:sh_name=>86,
#   :sh_type=>3,
#   :sh_flags=>2,
#   :sh_addr=>4195224,
#   :sh_offset=>920,
#   :sh_size=>113,
#   :sh_link=>0,
#   :sh_info=>0,
#   :sh_addralign=>1,
#   :sh_entsize=>0},
# @name=".dynstr">
elf.sections.map(&:name).join(' ')
#=> " .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss .comment .shstrtab .symtab .strtab"
elf.section_by_name('.note.gnu.build-id').data
#=> "\x04\x00\x00\x00\x14\x00\x00\x00\x03\x00\x00\x00GNU\x00s\xABb\xCB{\xC9\x95\x9C\xE0S\xC2\xB7\x112!Xp\x8C\xDC\a"

Symbols

symtab_section = elf.section_by_name('.symtab')
symtab_section.num_symbols
#=> 75

symtab_section.symbol_by_name('puts@@GLIBC_2.2.5')
#=>
# #<ELFTools::Sections::Symbol:0x00560b14af67a0
#  @header={:st_name=>348, :st_info=>18, :st_other=>0, :st_shndx=>0, :st_value=>0, :st_size=>0},
#  @name="puts@@GLIBC_2.2.5">

symbols = symtab_section.symbols # Array of symbols
symbols.map(&:name).reject(&:empty?).first(5).join(' ')
#=> "crtstuff.c __JCR_LIST__ deregister_tm_clones register_tm_clones __do_global_dtors_aux"

Segments

elf.segment_by_type(:note)
#=>
# #<ELFTools::Segments::NoteSegment:0x00555beaafe218
# @header=
#  {:p_type=>4,
#   :p_flags=>4,
#   :p_offset=>624,
#   :p_vaddr=>624,
#   :p_paddr=>624,
#   :p_filesz=>68,
#   :p_memsz=>68,
#   :p_align=>4}>

elf.segment_by_type(:interp).interp_name
#=> "/lib64/ld-linux-x86-64.so.2"

Relocations

elf = ELFTools::ELFFile.new(File.open('spec/files/amd64.elf'))
# Use relocation to get plt names.
rela_section = elf.sections_by_type(:rela).last
rela_section.name
#=> ".rela.plt"
relocations = rela_section.relocations
relocations.map { |r| '%x' % r.header.r_info }
#=> ["100000007", "200000007", "300000007", "400000007", "500000007", "700000007"]
symtab = elf.section_at(rela_section.header.sh_link) # get the symbol table section
relocations.map { |r| symtab.symbol_at(r.symbol_index).name }
#=> ["puts", "__stack_chk_fail", "printf", "__libc_start_main", "fgets", "scanf"]

Patch

Patch ELF is so easy!

All kinds of headers (i.e. Ehdr, Shdr, Phdr, etc.) can be patched. Patched slots will not be applied on the opened file. Invoke elf.save(filename) to save the patched ELF into filename.

elf = ELFTools::ELFFile.new(File.open('spec/files/amd64.elf'))
elf.machine
#=> "Advanced Micro Devices X86-64"
elf.header.e_machine = 40
elf.machine
#=> "ARM"

interp_segment = elf.segment_by_type(:interp)
interp_segment.interp_name
#=> "/lib64/ld-linux-x86-64.so.2"
interp_segment.header.p_filesz
#=> 28
interp_segment.header.p_filesz = 20
interp_segment.interp_name
#=> "/lib64/ld-linux-x86"

# save the patched ELF
elf.save('elf.patched')

# in bash
# $ file elf.patched
# elf.patched: ELF 64-bit LSB executable, ARM, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86, for GNU...

Why rbelftools

  • Fully documented
    Always important for an Open-Source project. Online document is here
  • Fully tested
    Of course.
  • Lazy loading on everything
    To use rbelftools, passing the stream object of an ELF file. rbelftools will read the stream object as least times as possible when parsing the file. Most information will not be fetched until you need it, which makes rbelftools efficient.
  • To be a library
    rbelftools is designed to be a library for further usage. It will not add any too trivial features. For example, to check whether NX is disabled, rbelftools provides !elf.segment_by_type(:gnu_stack).executable? but not elf.nx?
  • Section and segment parser
    Providing common sections and segments parser. For example, .symtab, .shstrtab .dynamic sections and INTERP, DYNAMIC segments, etc.

Development

git clone https://github.com/david942j/rbelftools
cd rbelftools
bundle
bundle exec rake

Any comments or suggestions are welcome!

Cross Platform

rbelftools can be used and has been fully tested on all platforms include Linux, OSX, and Windows!

License

MIT License

FAQs

Package last updated on 22 Apr 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

About

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc

U.S. Patent No. 12,346,443 & 12,314,394. Other pending.