Class: Msf::Exe::SegmentAppender

Inherits:
Object
  • Object
show all
Defined in:
lib/msf/core/exe/segment_appender.rb

Overview

Appends payload bytes to a template as a new PE section.

Direct Known Subclasses

SegmentHijacker, SegmentInjector

Constant Summary collapse

MAX_PE_SECTION_NAME_LENGTH =
8
MAX_SECTION_NAME_WITHOUT_DOT_LENGTH =
MAX_PE_SECTION_NAME_LENGTH - 1
DEFAULT_SECTION_CHARACTERISTICS =
%w[MEM_READ MEM_WRITE MEM_EXECUTE].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ SegmentAppender

Returns a new instance of SegmentAppender.



15
16
17
18
19
20
21
# File 'lib/msf/core/exe/segment_appender.rb', line 15

def initialize(opts = {})
  @payload = opts[:payload]
  @template = opts[:template]
  @arch = opts[:arch] || :x86
  @section_name = opts.key?(:section_name) ? opts[:section_name] : opts[:secname]
  @section_characteristics = opts.fetch(:section_characteristics, DEFAULT_SECTION_CHARACTERISTICS).dup
end

Instance Attribute Details

#archObject

Returns the value of attribute arch.



13
14
15
# File 'lib/msf/core/exe/segment_appender.rb', line 13

def arch
  @arch
end

#payloadObject

Returns the value of attribute payload.



13
14
15
# File 'lib/msf/core/exe/segment_appender.rb', line 13

def payload
  @payload
end

#section_characteristicsObject

Returns the value of attribute section_characteristics.



13
14
15
# File 'lib/msf/core/exe/segment_appender.rb', line 13

def section_characteristics
  @section_characteristics
end

#section_nameObject Also known as: secname

Returns the value of attribute section_name.



13
14
15
# File 'lib/msf/core/exe/segment_appender.rb', line 13

def section_name
  @section_name
end

#templateObject

Returns the value of attribute template.



13
14
15
# File 'lib/msf/core/exe/segment_appender.rb', line 13

def template
  @template
end

Instance Method Details

#append_section(pe, prefix: '', default_name: nil) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
# File 'lib/msf/core/exe/segment_appender.rb', line 62

def append_section(pe, prefix: '', default_name: nil)
  section = Metasm::PE::Section.new
  section.name = build_section_name(default_name)
  section.encoded = build_section_data(prefix: prefix)
  section.characteristics = section_characteristics

  pe.sections << section
  pe.invalidate_header

  section
end

#build_section_name(default_name = nil) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/msf/core/exe/segment_appender.rb', line 74

def build_section_name(default_name = nil)
  requested_section_name = section_name
  normalized_section_name = if requested_section_name.blank?
                              default_name || random_section_name
                            elsif requested_section_name.start_with?('.')
                              requested_section_name.downcase
                            else
                              '.' + requested_section_name.downcase
                            end

  if normalized_section_name.bytesize > MAX_PE_SECTION_NAME_LENGTH
    raise ArgumentError,
          ":section_name must fit in the #{MAX_PE_SECTION_NAME_LENGTH}-byte PE section name field (#{MAX_SECTION_NAME_WITHOUT_DOT_LENGTH} bytes when the leading '.' is omitted)"
  end

  @section_name = normalized_section_name
end

#copy_pe(pe_orig) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/msf/core/exe/segment_appender.rb', line 48

def copy_pe(pe_orig)
  pe = pe_orig.mini_copy

  # Copy the headers and exports
  pe.mz.encoded = pe_orig.encoded[0, pe_orig.coff_offset - 4]
  pe.mz.encoded.export = pe_orig.encoded[0, 512].export.dup
  pe.header.time = pe_orig.header.time

  # Don't rebase if we can help it since Metasm doesn't do relocations well
  pe.optheader.dll_characts.delete('DYNAMIC_BASE')

  pe
end

#generate_peObject



38
39
40
41
42
43
44
45
46
# File 'lib/msf/core/exe/segment_appender.rb', line 38

def generate_pe
  pe_orig = Metasm::PE.decode_file(template)
  pe = copy_pe(pe_orig)

  append_section(pe)
  pe.cpu = pe_orig.cpu

  pe.encode_string
end

#processorObject



27
28
29
30
31
32
33
34
35
36
# File 'lib/msf/core/exe/segment_appender.rb', line 27

def processor
  case arch
  when :x86
    Metasm::Ia32.new
  when :x64
    Metasm::X86_64.new
  else
    raise 'Incompatible architecture'
  end
end

#random_section_nameObject



92
93
94
# File 'lib/msf/core/exe/segment_appender.rb', line 92

def random_section_name
  '.' + Rex::Text.rand_text_alpha_lower(4)
end