Class: PEdump::Loader

Inherits:
Object show all
Defined in:
lib/pedump/loader.rb,
lib/pedump/loader/section.rb

Defined Under Namespace

Classes: Section

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(io = nil, pedump_params = {}) ⇒ Loader

constructors



17
18
19
20
21
22
23
24
25
# File 'lib/pedump/loader.rb', line 17

def initialize io = nil, pedump_params = {}
  @pedump = PEdump.new(io, pedump_params)
  if io
    @mz_hdr     = @pedump.mz
    @dos_stub   = @pedump.dos_stub
    @pe_hdr     = @pedump.pe
    load_sections @pedump.sections, io
  end
end

Instance Attribute Details

#dos_stubObject

Returns the value of attribute dos_stub.



6
7
8
# File 'lib/pedump/loader.rb', line 6

def dos_stub
  @dos_stub
end

#mz_hdrObject

Returns the value of attribute mz_hdr.



6
7
8
# File 'lib/pedump/loader.rb', line 6

def mz_hdr
  @mz_hdr
end

#pe_hdrObject Also known as: pe

Returns the value of attribute pe_hdr.



6
7
8
# File 'lib/pedump/loader.rb', line 6

def pe_hdr
  @pe_hdr
end

#pedumpObject

Returns the value of attribute pedump.



6
7
8
# File 'lib/pedump/loader.rb', line 6

def pedump
  @pedump
end

#sectionsObject

Returns the value of attribute sections.



6
7
8
# File 'lib/pedump/loader.rb', line 6

def sections
  @sections
end

Instance Method Details

#[](va, size) ⇒ Object

virtual memory read/write



65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/pedump/loader.rb', line 65

def [] va, size
  section = va2section(va)
  raise "no section for va=0x#{va.to_s 16}" unless section
  offset = va - section.va
  raise "negative offset #{offset}" if offset < 0
  r = section.data[offset,size]
  if r.size < size
    # append some empty data
    r << ("\x00".force_encoding('binary')) * (size - r.size)
  end
  r
end

#[]=(va, size, data) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/pedump/loader.rb', line 78

def []= va, size, data
  raise "data.size != size" if data.size != size
  section = va2section(va)
  raise "no section for va=0x#{va.to_s 16}" unless section
  offset = va - section.va
  raise "negative offset #{offset}" if offset < 0
  if section.data.size < offset
    # append some empty data
    section.data << ("\x00".force_encoding('binary') * (offset-section.data.size))
  end
  section.data[offset, data.size] = data
end

#dump(f) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/pedump/loader.rb', line 102

def dump f
  align = @pe_hdr.ioh.FileAlignment

  mz_size = @mz_hdr.pack.size
  raise "odd mz_size #{mz_size}" if mz_size % 0x10 != 0
  @mz_hdr.header_paragraphs = mz_size / 0x10              # offset of dos_stub
  @mz_hdr.lfanew = mz_size + @dos_stub.size               # offset of PE hdr
  f.write @mz_hdr.pack
  f.write @dos_stub
  f.write @pe_hdr.pack
  f.write @pe_hdr.ioh.DataDirectory.map(&:pack).join

  section_tbl_offset = f.tell # store offset for 2nd write of section table
  f.write section_table

  @sections.each do |section|
    f.seek(align - (f.tell % align), IO::SEEK_CUR) if f.tell % align != 0
    section.hdr.PointerToRawData = f.tell  # fix raw_ptr
    f.write(section.data)
  end

  eof = f.tell

  # 2nd write of section table with correct raw_ptr's
  f.seek section_tbl_offset
  f.write section_table

  f.seek eof
end

#epObject



10
# File 'lib/pedump/loader.rb', line 10

def ep; @pe_hdr.ioh.AddressOfEntryPoint; end

#ep=(v) ⇒ Object



11
# File 'lib/pedump/loader.rb', line 11

def ep= v; @pe_hdr.ioh.AddressOfEntryPoint=v; end

#load_sections(section_hdrs, f = nil) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/pedump/loader.rb', line 27

def load_sections section_hdrs, f = nil
  if section_hdrs.is_a?(Array) && section_hdrs.map(&:class).uniq == [PEdump::IMAGE_SECTION_HEADER]
    @sections = section_hdrs.map{ |x| Section.new(x, :deferred_load_io => f) }
    if f.respond_to?(:seek) && f.respond_to?(:read)
      #
      # converted to deferred loading
      #
#        section_hdrs.each_with_index do |sect_hdr, idx|
#          f.seek sect_hdr.PointerToRawData
#          @sections[idx].data = f.read(sect_hdr.SizeOfRawData)
#        end
    elsif f
      raise "invalid 2nd arg: #{f.inspect}"
    end
  else
    raise "invalid arg: #{section_hdrs.inspect}"
  end
end

#section_tableObject

generating PE binary



95
96
97
98
99
100
# File 'lib/pedump/loader.rb', line 95

def section_table
  @sections.map do |section|
    section.hdr.SizeOfRawData = section.data.size
    section.hdr.pack
  end.join
end

#va2section(va) ⇒ Object

VA conversion



50
51
52
# File 'lib/pedump/loader.rb', line 50

def va2section va
  @sections.find{ |x| x.range.include?(va) }
end

#va2stream(va) ⇒ Object



54
55
56
57
58
59
# File 'lib/pedump/loader.rb', line 54

def va2stream va
  return nil unless section = va2section(va)
  StringIO.new(section.data).tap do |io|
    io.seek va-section.va
  end
end