class Elf
Attributes
arch[RW]
attr_accessor :gotplt
bits[RW]
attr_accessor :gotplt
dynamic[RW]
attr_accessor :gotplt
global[RW]
attr_accessor :gotplt
got[RW]
attr_accessor :gotplt
sections[RW]
attr_accessor :gotplt
Public Class Methods
new(file)
click to toggle source
# File lib/elf.rb, line 276 def initialize(file) # To avoid unicode binary = File.read(file).force_encoding('binary') # To fix bugs leading eof, that's why here is a newline ... elf = ElfParser.read binary + "\n" # parse information we need extract_info binary, elf end
Private Instance Methods
extract_info(binary, elf)
click to toggle source
# File lib/elf.rb, line 287 def extract_info(binary, elf) @arch = elf.arch.to_s @bits = elf.bits.to_i # parse section name parse_section_name binary, elf # parse symbol table parse_symtab binary, elf # Parse dynamic section parse_dynamic_constant binary, elf ## parse rel.plt parse_relplt binary, elf end
parse_dynamic_constant(binary, elf)
click to toggle source
# File lib/elf.rb, line 318 def parse_dynamic_constant(binary, elf) dynamic = nil elf.e_shnum.times do |i| content = binary[elf.sh[i].sh_offset, elf.sh[i].sh_size] if elf.sh[i].sh_type == 6 # DYNAMIC size = elf.sh[i].sh_size / elf.sh[i].sh_entsize if @bits == 32 dynamic = BinData::Array.new(:type => :dynamic32, :initial_length => size) else dynamic = BinData::Array.new(:type => :dynamic64, :initial_length => size) end dynamic.read content end end @dynamic = {} dynamic.each do |d| # PLTREL if d.d_tag == 20 if d.d_val == 7 @dynamic["rel_type"]= "RELA" elsif d.d_val == 17 @dynamic["rel_type"]= "REL" end # STRTAB elsif d.d_tag == 5 @dynamic["strtab"]= d.d_val.to_i # SYMTAB elsif d.d_tag == 6 @dynamic["symtab"]= d.d_val.to_i # JMPREL elsif d.d_tag == 0x17 @dynamic["jmprel"]= d.d_val.to_i end end end
parse_relplt(binary, elf)
click to toggle source
# File lib/elf.rb, line 385 def parse_relplt(binary, elf) rel = nil reldyn = nil elf.e_shnum.times do |i| if @dynamic["rel_type"] == "REL" if elf.sh[i].name_str == ".rel.plt" size = elf.sh[i].sh_size/elf.sh[i].sh_entsize if elf.e_ident[:ei_class] == 1 rel = BinData::Array.new(:type => :relplt32, :initial_length => size) else rel = BinData::Array.new(:type => :relplt64, :initial_length => size) end rel.read binary[elf.sh[i].sh_offset, elf.sh[i].sh_size] elsif elf.sh[i].name_str == ".rel.dyn" size = elf.sh[i].sh_size/elf.sh[i].sh_entsize if @bits == 32 reldyn = BinData::Array.new(:type => :relplt32, :initial_length => size) else reldyn = BinData::Array.new(:type => :relplt64, :initial_length => size) end reldyn.read binary[elf.sh[i].sh_offset, elf.sh[i].sh_size] end elsif @dynamic["rel_type"] == "RELA" if elf.sh[i].name_str == ".rela.plt" size = elf.sh[i].sh_size/elf.sh[i].sh_entsize if @bits == 32 rel = BinData::Array.new(:type => :relaplt32, :initial_length => size) else rel = BinData::Array.new(:type => :relaplt64, :initial_length => size) end rel.read binary[elf.sh[i].sh_offset, elf.sh[i].sh_size] elsif elf.sh[i].name_str == ".rela.dyn" size = elf.sh[i].sh_size/elf.sh[i].sh_entsize if @bits == 32 reldyn = BinData::Array.new(:type => :relaplt32, :initial_length => size) else reldyn = BinData::Array.new(:type => :relaplt64, :initial_length => size) end reldyn.read binary[elf.sh[i].sh_offset, elf.sh[i].sh_size] end end end # extract information @got = {} rel.each do |r| if r.type.to_i == 7 # JMP_SLOT @got[elf.symtab[r.sym_index.to_i].name_str.to_s] = r.r_offset.to_i end end @global = Hash.new {|h, k| h[k] = Hash.new} reldyn.each do |r| if r.type.to_i == 6 # GLOB_DAT @global[elf.symtab[r.sym_index.to_i].name_str.to_s]["offset"] = r.r_offset.to_i @global[elf.symtab[r.sym_index.to_i].name_str.to_s]["value"] = elf.symtab[r.sym_index.to_i].st_value.to_i end end end
parse_section_name(binary, elf)
click to toggle source
# File lib/elf.rb, line 300 def parse_section_name(binary, elf) strtab_offset = elf.sh[elf.e_shstrndx].sh_offset.to_i strtab = binary[(strtab_offset)..-1] @sections = Hash.new{|h, k| h[k] = Hash.new } elf.e_shnum.times do |i| sh_name = elf.sh[i].sh_name.to_i elf.sh[i].name_str.assign BinData::Stringz.read strtab[sh_name..-1] flag = "r" flag += (elf.sh[i].sh_flags & 1) > 0 ? "w" : "-" flag += (elf.sh[i].sh_flags & 4) > 0 ? "x" : "-" @sections[elf.sh[i].name_str.to_s]["addr"] = elf.sh[i].sh_addr.to_i @sections[elf.sh[i].name_str.to_s]["offset"] = elf.sh[i].sh_offset.to_i @sections[elf.sh[i].name_str.to_s]["size"] = elf.sh[i].sh_size.to_i @sections[elf.sh[i].name_str.to_s]["flag"] = flag end end
parse_symtab(binary, elf)
click to toggle source
# File lib/elf.rb, line 354 def parse_symtab(binary, elf) # find dynamic symtab symtab = nil elf.e_shnum.times do |i| if elf.sh[i].name_str.to_s == ".dynsym" size = elf.sh[i].sh_size/elf.sh[i].sh_entsize if elf.e_ident[:ei_class] == 1 symtab = BinData::Array.new(:type => :symtab32, :initial_length => size) else symtab = BinData::Array.new(:type => :symtab64, :initial_length => size) end symtab = symtab.read binary[elf.sh[i].sh_offset, elf.sh[i].sh_size] end end # find dynamic strtab strtab = nil elf.e_shnum.times do |i| if elf.sh[i].name_str.to_s == ".dynstr" strtab = binary[elf.sh[i].sh_offset, elf.sh[i].sh_size] end end # find the name of dynamic symbol symtab.size.times do |i| symtab[i].name_str.assign BinData::Stringz.read strtab[symtab[i].st_name..-1] end elf.symtab.assign symtab end