diff --git a/lib/msf/base/sessions/powershell.rb b/lib/msf/base/sessions/powershell.rb index 5b152ba92e..3bde436f5c 100644 --- a/lib/msf/base/sessions/powershell.rb +++ b/lib/msf/base/sessions/powershell.rb @@ -86,6 +86,17 @@ class Msf::Sessions::PowerShell < Msf::Sessions::CommandShell needs_single_quoting = true end + will_be_double_quoted_by_powershell = [' ', '\t', '\v'].any? do |bad_char| + arg.include?(bad_char) + end + + if will_be_double_quoted_by_powershell + # This is horrible, and I'm so so sorry. + # If an argument ends with a series of backslashes, and it will be quoted by PowerShell when *it* launches the process (e.g. because the arg contains a space), + # PowerShell will not correctly handle backslashes immediately preceeding the quote that it *itself* adds. So we need to be responsible for this. + arg = arg.gsub(/(\\*)$/, '\\1\\1') + end + if needs_single_quoting arg = "'#{arg}'" end diff --git a/spec/lib/msf/base/sessions/command_shell_windows_spec.rb b/spec/lib/msf/base/sessions/command_shell_windows_spec.rb index 6e0de2c9ed..917e32253a 100755 --- a/spec/lib/msf/base/sessions/command_shell_windows_spec.rb +++ b/spec/lib/msf/base/sessions/command_shell_windows_spec.rb @@ -34,7 +34,7 @@ RSpec.describe Msf::Sessions::CommandShellWindows do end it 'should handle the weird backslash escaping behaviour in front of quotes' do - expect(described_class.to_cmd(['test.exe'] + ['quote\\\\"'])).to eq('test.exe "quote\\\\\\\\"""') + expect(described_class.to_cmd(['test.exe'] + ['quote\\\\"'])).to eq('test.exe "quote\\\\\\\\""') expect(described_class.to_cmd(['test.exe'] + ['will be quoted\\\\'])).to eq('test.exe "will be quoted\\\\\\\\"') expect(described_class.to_cmd(['test.exe'] + ['will be quoted\\\\ '])).to eq('test.exe "will be quoted\\\\ "') # Should not be doubled up expect(described_class.to_cmd(['test.exe'] + ['"test"', 'test\\"', 'test\\\\"', 'test words\\\\\\\\', 'test words\\\\\\', '\\\\'])).to eq('test.exe """test""" "test\\\\"" "test\\\\\\\\"" "test words\\\\\\\\\\\\\\\\" "test words\\\\\\\\\\\\" \\\\') diff --git a/test/modules/post/test/cmd_exec.rb b/test/modules/post/test/cmd_exec.rb index 23748780c4..b34e25be5e 100644 --- a/test/modules/post/test/cmd_exec.rb +++ b/test/modules/post/test/cmd_exec.rb @@ -84,6 +84,10 @@ class MetasploitModule < Msf::Post # Match the binary name, to support the binary name containing relative or absolute paths, i.e. # "show_args.exe\r\none\r\ntwo", + if output_binary.nil? + vprint_status("#{__method__}: Malformed output: no process binary returned") + return false + end match = output_binary.include?(expected[0]) && output_args == expected[1..] if !match vprint_status("#{__method__}: expected: #{expected.inspect} - actual: #{output_lines.inspect}")